823 lines
24 KiB
V
823 lines
24 KiB
V
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
module pref
|
|
|
|
// import v.ast // TODO this results in a compiler bug
|
|
import os.cmdline
|
|
import os
|
|
import v.vcache
|
|
import rand
|
|
|
|
pub enum BuildMode {
|
|
// `v program.v'
|
|
// Build user code only, and add pre-compiled vlib (`cc program.o builtin.o os.o...`)
|
|
default_mode // `v -lib ~/v/os`
|
|
// build any module (generate os.o + os.vh)
|
|
build_module
|
|
}
|
|
|
|
pub enum AssertFailureMode {
|
|
default
|
|
aborts
|
|
backtraces
|
|
}
|
|
|
|
pub enum GarbageCollectionMode {
|
|
no_gc
|
|
boehm_full // full garbage collection mode
|
|
boehm_incr // incremental garbage colletion mode
|
|
boehm_full_opt // full garbage collection mode
|
|
boehm_incr_opt // incremental garbage colletion mode
|
|
boehm_leak // leak detection mode (makes `gc_check_leaks()` work)
|
|
}
|
|
|
|
pub enum OutputMode {
|
|
stdout
|
|
silent
|
|
}
|
|
|
|
pub enum ColorOutput {
|
|
auto
|
|
always
|
|
never
|
|
}
|
|
|
|
pub enum Backend {
|
|
c // The (default) C backend
|
|
js_node // The JavaScript NodeJS backend
|
|
js_browser // The JavaScript browser backend
|
|
js_freestanding // The JavaScript freestanding backend
|
|
native // The Native backend
|
|
}
|
|
|
|
pub fn (b Backend) is_js() bool {
|
|
match b {
|
|
.js_node, .js_browser, .js_freestanding {
|
|
return true
|
|
}
|
|
else {
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
pub enum CompilerType {
|
|
gcc
|
|
tinyc
|
|
clang
|
|
mingw
|
|
msvc
|
|
cplusplus
|
|
}
|
|
|
|
pub enum Arch {
|
|
_auto
|
|
amd64 // aka x86_64
|
|
arm64 // 64-bit arm
|
|
arm32 // 32-bit arm
|
|
rv64 // 64-bit risc-v
|
|
rv32 // 32-bit risc-v
|
|
i386
|
|
_max
|
|
}
|
|
|
|
const (
|
|
list_of_flags_with_param = ['o', 'd', 'define', 'b', 'backend', 'cc', 'os', 'target-os', 'cf',
|
|
'cflags', 'path', 'arch']
|
|
)
|
|
|
|
[heap]
|
|
pub struct Preferences {
|
|
pub mut:
|
|
os OS // the OS to compile for
|
|
backend Backend
|
|
build_mode BuildMode
|
|
arch Arch
|
|
output_mode OutputMode = .stdout
|
|
// verbosity VerboseLevel
|
|
is_verbose bool
|
|
// nofmt bool // disable vfmt
|
|
is_test bool // `v test string_test.v`
|
|
is_script bool // single file mode (`v program.v`), main function can be skipped
|
|
is_vsh bool // v script (`file.vsh`) file, the `os` module should be made global
|
|
is_livemain bool // main program that contains live/hot code
|
|
is_liveshared bool // a shared library, that will be used in a -live main program
|
|
is_shared bool // an ordinary shared library, -shared, no matter if it is live or not
|
|
is_prof bool // benchmark every function
|
|
profile_file string // the profile results will be stored inside profile_file
|
|
profile_no_inline bool // when true, [inline] functions would not be profiled
|
|
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
|
|
is_prod bool // use "-O2"
|
|
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
|
is_repl bool
|
|
is_run bool
|
|
sanitize bool // use Clang's new "-fsanitize" option
|
|
is_debug bool // false by default, turned on by -g or -cg, it tells v to pass -g to the C backend compiler.
|
|
sourcemap bool // JS Backend: -sourcemap will create a source map - default false
|
|
sourcemap_inline bool = true // JS Backend: -sourcemap-inline will embed the source map in the generated JaaScript file - currently default true only implemented
|
|
sourcemap_src_included bool // JS Backend: -sourcemap-src-included includes V source code in source map - default false
|
|
is_vlines bool // turned on by -g, false by default (it slows down .tmp.c generation slightly).
|
|
show_cc bool // -showcc, print cc command
|
|
show_c_output bool // -show-c-output, print all cc output even if the code was compiled correctly
|
|
show_callgraph bool // -show-callgraph, print the program callgraph, in a Graphviz DOT format to stdout
|
|
// NB: passing -cg instead of -g will set is_vlines to false and is_debug to true, thus making v generate cleaner C files,
|
|
// which are sometimes easier to debug / inspect manually than the .tmp.c files by plain -g (when/if v line number generation breaks).
|
|
// use cached modules to speed up compilation.
|
|
dump_c_flags string // `-dump-c-flags file.txt` - let V store all C flags, passed to the backend C compiler
|
|
// in `file.txt`, one C flag/value per line.
|
|
use_cache bool // = true
|
|
retry_compilation bool = true // retry the compilation with another C compiler, if tcc fails.
|
|
is_stats bool // `v -stats file_test.v` will produce more detailed statistics for the tests that were run
|
|
// TODO Convert this into a []string
|
|
cflags string // Additional options which will be passed to the C compiler.
|
|
// For example, passing -cflags -Os will cause the C compiler to optimize the generated binaries for size.
|
|
// You could pass several -cflags XXX arguments. They will be merged with each other.
|
|
// You can also quote several options at the same time: -cflags '-Os -fno-inline-small-functions'.
|
|
m64 bool // true = generate 64-bit code, defaults to x64
|
|
ccompiler string // the name of the C compiler used
|
|
ccompiler_type CompilerType // the type of the C compiler used
|
|
third_party_option string
|
|
building_v bool
|
|
autofree bool // `v -manualfree` => false, `v -autofree` => true; false by default for now.
|
|
// Disabling `free()` insertion results in better performance in some applications (e.g. compilers)
|
|
compress bool
|
|
// skip_builtin bool // Skips re-compilation of the builtin module
|
|
// to increase compilation time.
|
|
// This is on by default, since a vast majority of users do not
|
|
// work on the builtin module itself.
|
|
// generating_vh bool
|
|
enable_globals bool // allow __global for low level code
|
|
is_fmt bool
|
|
is_vet bool
|
|
is_bare bool
|
|
no_preludes bool // Prevents V from generating preludes in resulting .c files
|
|
custom_prelude string // Contents of custom V prelude that will be prepended before code in resulting .c files
|
|
lookup_path []string
|
|
bare_builtin_dir string // Path to implementation of malloc, memset, etc. Only used if is_bare is true
|
|
output_cross_c bool // true, when the user passed `-os cross`
|
|
prealloc bool
|
|
vroot string
|
|
out_name_c string // full os.real_path to the generated .tmp.c file; set by builder.
|
|
out_name string
|
|
path string // Path to file/folder to compile
|
|
// -d vfmt and -d another=0 for `$if vfmt { will execute }` and `$if another ? { will NOT get here }`
|
|
compile_defines []string // just ['vfmt']
|
|
compile_defines_all []string // contains both: ['vfmt','another']
|
|
run_args []string // `v run x.v 1 2 3` => `1 2 3`
|
|
printfn_list []string // a list of generated function names, whose source should be shown, for debugging
|
|
print_v_files bool // when true, just print the list of all parsed .v files then stop.
|
|
skip_running bool // when true, do no try to run the produced file (set by b.cc(), when -o x.c or -o x.js)
|
|
skip_warnings bool // like C's "-w", forces warnings to be ignored.
|
|
warn_impure_v bool // -Wimpure-v, force a warning for JS.fn()/C.fn(), outside of .js.v/.c.v files. TODO: turn to an error by default
|
|
warns_are_errors bool // -W, like C's "-Werror", treat *every* warning is an error
|
|
fatal_errors bool // unconditionally exit after the first error with exit(1)
|
|
reuse_tmpc bool // do not use random names for .tmp.c and .tmp.c.rsp files, and do not remove them
|
|
use_color ColorOutput // whether the warnings/errors should use ANSI color escapes.
|
|
is_parallel bool
|
|
error_limit int
|
|
is_vweb bool // skip _ var warning in templates
|
|
only_check_syntax bool // when true, just parse the files, then stop, before running checker
|
|
experimental bool // enable experimental features
|
|
skip_unused bool // skip generating C code for functions, that are not used
|
|
show_timings bool // show how much time each compiler stage took
|
|
is_ios_simulator bool
|
|
is_apk bool // build as Android .apk format
|
|
cleanup_files []string // list of temporary *.tmp.c and *.tmp.c.rsp files. Cleaned up on successfull builds.
|
|
build_options []string // list of options, that should be passed down to `build-module`, if needed for -usecache
|
|
cache_manager vcache.CacheManager
|
|
is_help bool // -h, -help or --help was passed
|
|
gc_mode GarbageCollectionMode = .no_gc // .no_gc, .boehm, .boehm_leak, ...
|
|
is_cstrict bool // turn on more C warnings; slightly slower
|
|
assert_failure_mode AssertFailureMode // whether to call abort() or print_backtrace() after an assertion failure
|
|
// checker settings:
|
|
checker_match_exhaustive_cutoff_limit int = 12
|
|
}
|
|
|
|
pub fn parse_args(known_external_commands []string, args []string) (&Preferences, string) {
|
|
mut res := &Preferences{}
|
|
$if x64 {
|
|
res.m64 = true // follow V model by default
|
|
}
|
|
mut command := ''
|
|
mut command_pos := 0
|
|
// for i, arg in args {
|
|
for i := 0; i < args.len; i++ {
|
|
arg := args[i]
|
|
current_args := args[i..].clone()
|
|
match arg {
|
|
'-apk' {
|
|
res.is_apk = true
|
|
res.build_options << arg
|
|
}
|
|
'-arch' {
|
|
target_arch := cmdline.option(current_args, '-arch', '')
|
|
i++
|
|
target_arch_kind := arch_from_string(target_arch) or {
|
|
eprintln('unknown architecture target `$target_arch`')
|
|
exit(1)
|
|
}
|
|
res.arch = target_arch_kind
|
|
res.build_options << '$arg $target_arch'
|
|
}
|
|
'-assert' {
|
|
assert_mode := cmdline.option(current_args, '-assert', '')
|
|
match assert_mode {
|
|
'aborts' {
|
|
res.assert_failure_mode = .aborts
|
|
}
|
|
'backtraces' {
|
|
res.assert_failure_mode = .backtraces
|
|
}
|
|
else {
|
|
eprintln('unknown assert mode `-gc $assert_mode`, supported modes are:`')
|
|
eprintln(' `-assert aborts` .... calls abort() after assertion failure')
|
|
eprintln(' `-assert backtraces` .... calls print_backtrace() after assertion failure')
|
|
exit(1)
|
|
}
|
|
}
|
|
i++
|
|
}
|
|
'-show-timings' {
|
|
res.show_timings = true
|
|
}
|
|
'-check-syntax' {
|
|
res.only_check_syntax = true
|
|
}
|
|
'-h', '-help', '--help' {
|
|
// NB: help is *very important*, just respond to all variations:
|
|
res.is_help = true
|
|
}
|
|
'-v' {
|
|
// `-v` flag is for setting verbosity, but without any args it prints the version, like Clang
|
|
if args.len > 1 {
|
|
res.is_verbose = true
|
|
} else {
|
|
command = 'version'
|
|
command_pos = i
|
|
}
|
|
}
|
|
'-progress' {
|
|
// processed by testing tools in cmd/tools/modules/testing/common.v
|
|
}
|
|
'-Wimpure-v' {
|
|
res.warn_impure_v = true
|
|
}
|
|
'-Wfatal-errors' {
|
|
res.fatal_errors = true
|
|
}
|
|
'-silent' {
|
|
res.output_mode = .silent
|
|
}
|
|
'-cstrict' {
|
|
res.is_cstrict = true
|
|
}
|
|
'-gc' {
|
|
gc_mode := cmdline.option(current_args, '-gc', '')
|
|
match gc_mode {
|
|
'', 'none' {
|
|
res.gc_mode = .no_gc
|
|
}
|
|
'boehm_full' {
|
|
res.gc_mode = .boehm_full
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_full')
|
|
}
|
|
'boehm_incr' {
|
|
res.gc_mode = .boehm_incr
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_incr')
|
|
}
|
|
'boehm_full_opt' {
|
|
res.gc_mode = .boehm_full_opt
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_full')
|
|
parse_define(mut res, 'gcboehm_opt')
|
|
}
|
|
'boehm_incr_opt' {
|
|
res.gc_mode = .boehm_incr_opt
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_incr')
|
|
parse_define(mut res, 'gcboehm_opt')
|
|
}
|
|
'boehm' {
|
|
res.gc_mode = .boehm_full_opt // default mode
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_full')
|
|
parse_define(mut res, 'gcboehm_opt')
|
|
}
|
|
'boehm_leak' {
|
|
res.gc_mode = .boehm_leak
|
|
parse_define(mut res, 'gcboehm')
|
|
parse_define(mut res, 'gcboehm_leak')
|
|
}
|
|
else {
|
|
eprintln('unknown garbage collection mode `-gc $gc_mode`, supported modes are:`')
|
|
eprintln(' `-gc boehm` ............ default GC-mode (currently `boehm_full_opt`)')
|
|
eprintln(' `-gc boehm_full` ....... classic full collection')
|
|
eprintln(' `-gc boehm_incr` ....... incremental collection')
|
|
eprintln(' `-gc boehm_full_opt` ... optimized classic full collection')
|
|
eprintln(' `-gc boehm_incr_opt` ... optimized incremental collection')
|
|
eprintln(' `-gc boehm_leak` ....... leak detection (for debugging)')
|
|
eprintln(' `-gc none` ............. no garbage collection')
|
|
exit(1)
|
|
}
|
|
}
|
|
i++
|
|
}
|
|
'-g' {
|
|
res.is_debug = true
|
|
res.is_vlines = true
|
|
res.build_options << arg
|
|
}
|
|
'-cg' {
|
|
res.is_debug = true
|
|
res.is_vlines = false
|
|
res.build_options << arg
|
|
}
|
|
'-debug-tcc' {
|
|
res.ccompiler = 'tcc'
|
|
res.build_options << '$arg "$res.ccompiler"'
|
|
res.retry_compilation = false
|
|
res.show_cc = true
|
|
res.show_c_output = true
|
|
}
|
|
'-sourcemap' {
|
|
res.sourcemap = true
|
|
}
|
|
'-sourcemap-src-included' {
|
|
res.sourcemap_src_included = true
|
|
}
|
|
'-sourcemap-inline' {
|
|
res.sourcemap_inline = true
|
|
}
|
|
'-repl' {
|
|
res.is_repl = true
|
|
}
|
|
'-live' {
|
|
res.is_livemain = true
|
|
}
|
|
'-sharedlive' {
|
|
res.is_liveshared = true
|
|
res.is_shared = true
|
|
}
|
|
'-shared' {
|
|
res.is_shared = true
|
|
}
|
|
'--enable-globals' {
|
|
eprintln('`--enable-globals` flag is deprecated, please use `-enable-globals` instead')
|
|
res.enable_globals = true
|
|
}
|
|
'-enable-globals' {
|
|
res.enable_globals = true
|
|
}
|
|
'-autofree' {
|
|
res.autofree = true
|
|
res.build_options << arg
|
|
}
|
|
'-manualfree' {
|
|
res.autofree = false
|
|
res.build_options << arg
|
|
}
|
|
'-skip-unused' {
|
|
res.skip_unused = true
|
|
}
|
|
'-compress' {
|
|
res.compress = true
|
|
}
|
|
'-freestanding' {
|
|
res.is_bare = true
|
|
res.build_options << arg
|
|
}
|
|
'-no-retry-compilation' {
|
|
res.retry_compilation = false
|
|
}
|
|
'-no-preludes' {
|
|
res.no_preludes = true
|
|
res.build_options << arg
|
|
}
|
|
'-prof', '-profile' {
|
|
res.profile_file = cmdline.option(current_args, arg, '-')
|
|
res.is_prof = true
|
|
res.build_options << '$arg $res.profile_file'
|
|
i++
|
|
}
|
|
'-profile-no-inline' {
|
|
res.profile_no_inline = true
|
|
}
|
|
'-prod' {
|
|
res.is_prod = true
|
|
res.build_options << arg
|
|
}
|
|
'-sanitize' {
|
|
res.sanitize = true
|
|
res.build_options << arg
|
|
}
|
|
'-simulator' {
|
|
res.is_ios_simulator = true
|
|
}
|
|
'-stats' {
|
|
res.is_stats = true
|
|
}
|
|
'-obf', '-obfuscate' {
|
|
res.obfuscate = true
|
|
}
|
|
'-translated' {
|
|
res.translated = true
|
|
}
|
|
'-m32', '-m64' {
|
|
res.m64 = arg[2] == `6`
|
|
res.cflags += ' $arg'
|
|
}
|
|
'-color' {
|
|
res.use_color = .always
|
|
}
|
|
'-nocolor' {
|
|
res.use_color = .never
|
|
}
|
|
'-showcc' {
|
|
res.show_cc = true
|
|
}
|
|
'-show-c-output' {
|
|
res.show_c_output = true
|
|
}
|
|
'-show-callgraph' {
|
|
res.show_callgraph = true
|
|
}
|
|
'-dump-c-flags' {
|
|
res.dump_c_flags = cmdline.option(current_args, arg, '-')
|
|
i++
|
|
}
|
|
'-experimental' {
|
|
res.experimental = true
|
|
}
|
|
'-usecache' {
|
|
res.use_cache = true
|
|
}
|
|
'-nocache' {
|
|
res.use_cache = false
|
|
}
|
|
'-prealloc' {
|
|
res.prealloc = true
|
|
res.build_options << arg
|
|
}
|
|
'-parallel' {
|
|
res.is_parallel = true
|
|
}
|
|
'-native' {
|
|
res.backend = .native
|
|
res.build_options << arg
|
|
}
|
|
'-W' {
|
|
res.warns_are_errors = true
|
|
}
|
|
'-keepc' {
|
|
res.reuse_tmpc = true
|
|
}
|
|
'-w' {
|
|
res.skip_warnings = true
|
|
}
|
|
'-watch' {
|
|
eprintln('The -watch option is deprecated. Please use the watch command `v watch file.v` instead.')
|
|
exit(1)
|
|
}
|
|
'-print-v-files' {
|
|
res.print_v_files = true
|
|
}
|
|
'-error-limit' {
|
|
res.error_limit = cmdline.option(current_args, '-error-limit', '0').int()
|
|
}
|
|
'-os' {
|
|
target_os := cmdline.option(current_args, '-os', '')
|
|
i++
|
|
target_os_kind := os_from_string(target_os) or {
|
|
if target_os == 'cross' {
|
|
res.output_cross_c = true
|
|
continue
|
|
}
|
|
eprintln('unknown operating system target `$target_os`')
|
|
exit(1)
|
|
}
|
|
res.os = target_os_kind
|
|
res.build_options << '$arg $target_os'
|
|
}
|
|
'-printfn' {
|
|
res.printfn_list << cmdline.option(current_args, '-printfn', '').split(',')
|
|
i++
|
|
}
|
|
'-cflags' {
|
|
res.cflags += ' ' + cmdline.option(current_args, '-cflags', '')
|
|
res.build_options << '$arg "$res.cflags.trim_space()"'
|
|
i++
|
|
}
|
|
'-d', '-define' {
|
|
if current_args.len > 1 {
|
|
define := current_args[1]
|
|
parse_define(mut res, define)
|
|
}
|
|
i++
|
|
}
|
|
'-cc' {
|
|
res.ccompiler = cmdline.option(current_args, '-cc', 'cc')
|
|
res.build_options << '$arg "$res.ccompiler"'
|
|
i++
|
|
}
|
|
'-checker-match-exhaustive-cutoff-limit' {
|
|
res.checker_match_exhaustive_cutoff_limit = cmdline.option(current_args,
|
|
arg, '10').int()
|
|
i++
|
|
}
|
|
'-o', '-output' {
|
|
res.out_name = cmdline.option(current_args, arg, '')
|
|
if res.out_name.ends_with('.js') {
|
|
res.backend = .js_node
|
|
}
|
|
if !os.is_abs_path(res.out_name) {
|
|
res.out_name = os.join_path(os.getwd(), res.out_name)
|
|
}
|
|
i++
|
|
}
|
|
'-b', '-backend' {
|
|
sbackend := cmdline.option(current_args, arg, 'c')
|
|
res.build_options << '$arg $sbackend'
|
|
b := backend_from_string(sbackend) or { continue }
|
|
if b.is_js() {
|
|
res.output_cross_c = true
|
|
}
|
|
res.backend = b
|
|
i++
|
|
}
|
|
'-path' {
|
|
path := cmdline.option(current_args, '-path', '')
|
|
res.build_options << '$arg "$path"'
|
|
res.lookup_path = path.replace('|', os.path_delimiter).split(os.path_delimiter)
|
|
i++
|
|
}
|
|
'-bare-builtin-dir' {
|
|
bare_builtin_dir := cmdline.option(current_args, arg, '')
|
|
res.build_options << '$arg "$bare_builtin_dir"'
|
|
res.bare_builtin_dir = bare_builtin_dir
|
|
i++
|
|
}
|
|
'-custom-prelude' {
|
|
path := cmdline.option(current_args, '-custom-prelude', '')
|
|
res.build_options << '$arg $path'
|
|
prelude := os.read_file(path) or {
|
|
eprintln('cannot open custom prelude file: $err')
|
|
exit(1)
|
|
}
|
|
res.custom_prelude = prelude
|
|
i++
|
|
}
|
|
else {
|
|
if command == 'build' && is_source_file(arg) {
|
|
eprintln('Use `v $arg` instead.')
|
|
exit(1)
|
|
}
|
|
if arg[0] == `-` {
|
|
if arg[1..] in pref.list_of_flags_with_param {
|
|
// skip parameter
|
|
i++
|
|
continue
|
|
}
|
|
} else {
|
|
if command == '' {
|
|
command = arg
|
|
command_pos = i
|
|
if command == 'run' {
|
|
break
|
|
}
|
|
} else if is_source_file(command) && is_source_file(arg)
|
|
&& command !in known_external_commands {
|
|
eprintln('Too many targets. Specify just one target: <target.v|target_directory>.')
|
|
exit(1)
|
|
}
|
|
continue
|
|
}
|
|
if arg in ['-V', '-version', '--version'] {
|
|
command = 'version'
|
|
command_pos = i
|
|
continue
|
|
}
|
|
if command != '' && command != 'build-module' {
|
|
// arguments for e.g. fmt should be checked elsewhere
|
|
continue
|
|
}
|
|
extension := if command.len == 0 { '' } else { ' for command `$command`' }
|
|
eprintln('Unknown argument `$arg`$extension')
|
|
exit(1)
|
|
}
|
|
}
|
|
}
|
|
if res.is_debug {
|
|
parse_define(mut res, 'debug')
|
|
}
|
|
|
|
// res.use_cache = true
|
|
if command != 'doc' && res.out_name.ends_with('.v') {
|
|
eprintln('Cannot save output binary in a .v file.')
|
|
exit(1)
|
|
}
|
|
if is_source_file(command) {
|
|
res.path = command
|
|
} else if command == 'run' {
|
|
res.is_run = true
|
|
if command_pos + 2 > args.len {
|
|
eprintln('v run: no v files listed')
|
|
exit(1)
|
|
}
|
|
res.path = args[command_pos + 1]
|
|
res.run_args = args[command_pos + 2..]
|
|
if res.path == '-' {
|
|
tmp_file_path := rand.ulid()
|
|
mut tmp_exe_file_path := res.out_name
|
|
mut output_option := ''
|
|
if tmp_exe_file_path == '' {
|
|
tmp_exe_file_path = '${tmp_file_path}.exe'
|
|
output_option = '-o "$tmp_exe_file_path"'
|
|
}
|
|
tmp_v_file_path := '${tmp_file_path}.v'
|
|
contents := os.get_raw_lines_joined()
|
|
os.write_file(tmp_v_file_path, contents) or {
|
|
panic('Failed to create temporary file $tmp_v_file_path')
|
|
}
|
|
run_options := cmdline.options_before(args, ['run']).join(' ')
|
|
command_options := cmdline.options_after(args, ['run'])[1..].join(' ')
|
|
vexe := vexe_path()
|
|
tmp_cmd := '"$vexe" $output_option $run_options run "$tmp_v_file_path" $command_options'
|
|
//
|
|
res.vrun_elog('tmp_cmd: $tmp_cmd')
|
|
tmp_result := os.system(tmp_cmd)
|
|
res.vrun_elog('exit code: $tmp_result')
|
|
//
|
|
if output_option.len != 0 {
|
|
res.vrun_elog('remove tmp exe file: $tmp_exe_file_path')
|
|
os.rm(tmp_exe_file_path) or {}
|
|
}
|
|
res.vrun_elog('remove tmp v file: $tmp_v_file_path')
|
|
os.rm(tmp_v_file_path) or { panic(err) }
|
|
exit(tmp_result)
|
|
}
|
|
must_exist(res.path)
|
|
if !res.path.ends_with('.v') && os.is_executable(res.path) && os.is_file(res.path)
|
|
&& os.is_file(res.path + '.v') {
|
|
eprintln('It looks like you wanted to run "${res.path}.v", so we went ahead and did that since "$res.path" is an executable.')
|
|
res.path += '.v'
|
|
}
|
|
}
|
|
if !res.is_bare && res.bare_builtin_dir != '' {
|
|
eprintln('`-bare-builtin-dir` must be used with `-freestanding`')
|
|
}
|
|
if command == 'build-module' {
|
|
res.build_mode = .build_module
|
|
if command_pos + 1 >= args.len {
|
|
eprintln('v build-module: no module specified')
|
|
exit(1)
|
|
}
|
|
res.path = args[command_pos + 1]
|
|
}
|
|
// keep only the unique res.build_options:
|
|
mut m := map[string]string{}
|
|
for x in res.build_options {
|
|
m[x] = ''
|
|
}
|
|
res.build_options = m.keys()
|
|
// eprintln('>> res.build_options: $res.build_options')
|
|
res.fill_with_defaults()
|
|
return res, command
|
|
}
|
|
|
|
pub fn (pref &Preferences) vrun_elog(s string) {
|
|
if pref.is_verbose {
|
|
eprintln('> v run -, $s')
|
|
}
|
|
}
|
|
|
|
pub fn arch_from_string(arch_str string) ?Arch {
|
|
match arch_str {
|
|
'amd64', 'x86_64', 'x64', 'x86' { // amd64 recommended
|
|
|
|
return Arch.amd64
|
|
}
|
|
'aarch64', 'arm64' { // arm64 recommended
|
|
|
|
return Arch.arm64
|
|
}
|
|
'aarch32', 'arm32', 'arm' { // arm32 recommended
|
|
|
|
return Arch.arm32
|
|
}
|
|
'rv64', 'riscv64', 'risc-v64', 'riscv', 'risc-v' { // rv64 recommended
|
|
|
|
return Arch.rv64
|
|
}
|
|
'rv32', 'riscv32' { // rv32 recommended
|
|
|
|
return Arch.rv32
|
|
}
|
|
'x86_32', 'x32', 'i386', 'IA-32', 'ia-32', 'ia32' { // i386 recommended
|
|
|
|
return Arch.i386
|
|
}
|
|
'' {
|
|
return ._auto
|
|
}
|
|
else {
|
|
return error('invalid arch: $arch_str')
|
|
}
|
|
}
|
|
}
|
|
|
|
fn must_exist(path string) {
|
|
if !os.exists(path) {
|
|
eprintln('v expects that `$path` exists, but it does not')
|
|
exit(1)
|
|
}
|
|
}
|
|
|
|
[inline]
|
|
fn is_source_file(path string) bool {
|
|
return path.ends_with('.v') || os.exists(path)
|
|
}
|
|
|
|
pub fn backend_from_string(s string) ?Backend {
|
|
match s {
|
|
'c' { return .c }
|
|
'js' { return .js_node }
|
|
'js_node' { return .js_node }
|
|
'js_browser' { return .js_browser }
|
|
'js_freestanding' { return .js_freestanding }
|
|
'native' { return .native }
|
|
else { return error('Unknown backend type $s') }
|
|
}
|
|
}
|
|
|
|
// Helper function to convert string names to CC enum
|
|
pub fn cc_from_string(cc_str string) CompilerType {
|
|
if cc_str.len == 0 {
|
|
return .gcc
|
|
}
|
|
// TODO
|
|
normalized_cc := cc_str.replace('\\', '/')
|
|
normalized_cc_array := normalized_cc.split('/')
|
|
last_elem := normalized_cc_array.last()
|
|
cc := last_elem.all_before('.')
|
|
if cc.contains('++') {
|
|
return .cplusplus
|
|
}
|
|
if cc.contains('tcc') || cc.contains('tinyc') {
|
|
return .tinyc
|
|
}
|
|
if cc.contains('clang') {
|
|
return .clang
|
|
}
|
|
if cc.contains('mingw') {
|
|
return .mingw
|
|
}
|
|
if cc.contains('msvc') {
|
|
return .msvc
|
|
}
|
|
return .gcc
|
|
}
|
|
|
|
pub fn get_host_arch() Arch {
|
|
// NB: we can not use `$if arch` here, because V skips cgen for the non
|
|
// current comptime branches by default, so there is a bootstrapping
|
|
// problem => the __V_architecture macro is used to resolve it.
|
|
// TODO: think about how to solve it for non C backends, perhaps we
|
|
// need a comptime `$if native {` too, and/or a mechanism to always
|
|
// generate all branches for specific functions?
|
|
if C.__V_architecture <= int(Arch._auto) || C.__V_architecture >= int(Arch._max) {
|
|
return Arch.amd64
|
|
}
|
|
return Arch(C.__V_architecture)
|
|
}
|
|
|
|
fn parse_define(mut prefs Preferences, define string) {
|
|
define_parts := define.split('=')
|
|
prefs.build_options << '-d $define'
|
|
if define_parts.len == 1 {
|
|
prefs.compile_defines << define
|
|
prefs.compile_defines_all << define
|
|
return
|
|
}
|
|
if define_parts.len == 2 {
|
|
prefs.compile_defines_all << define_parts[0]
|
|
match define_parts[1] {
|
|
'0' {}
|
|
'1' {
|
|
prefs.compile_defines << define_parts[0]
|
|
}
|
|
else {
|
|
println(
|
|
'V error: Unknown define argument value `${define_parts[1]}` for ${define_parts[0]}.' +
|
|
' Expected `0` or `1`.')
|
|
exit(1)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
println('V error: Unknown define argument: ${define}. Expected at most one `=`.')
|
|
exit(1)
|
|
}
|