diff options
Diffstat (limited to 'v_windows/v/old/vlib/v/pref')
-rw-r--r-- | v_windows/v/old/vlib/v/pref/default.v | 206 | ||||
-rw-r--r-- | v_windows/v/old/vlib/v/pref/os.v | 116 | ||||
-rw-r--r-- | v_windows/v/old/vlib/v/pref/pref.v | 828 | ||||
-rw-r--r-- | v_windows/v/old/vlib/v/pref/should_compile.v | 217 |
4 files changed, 1367 insertions, 0 deletions
diff --git a/v_windows/v/old/vlib/v/pref/default.v b/v_windows/v/old/vlib/v/pref/default.v new file mode 100644 index 0000000..2862c57 --- /dev/null +++ b/v_windows/v/old/vlib/v/pref/default.v @@ -0,0 +1,206 @@ +// 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 os +import v.vcache + +pub const ( + default_module_path = os.vmodules_dir() +) + +pub fn new_preferences() &Preferences { + mut p := &Preferences{} + p.fill_with_defaults() + return p +} + +fn (mut p Preferences) expand_lookup_paths() { + if p.vroot == '' { + // Location of all vlib files + p.vroot = os.dir(vexe_path()) + } + vlib_path := os.join_path(p.vroot, 'vlib') + if p.lookup_path.len == 0 { + p.lookup_path = ['@vlib', '@vmodules'] + } + mut expanded_paths := []string{} + for path in p.lookup_path { + match path { + '@vlib' { expanded_paths << vlib_path } + '@vmodules' { expanded_paths << os.vmodules_paths() } + else { expanded_paths << path } + } + } + p.lookup_path = expanded_paths +} + +pub fn (mut p Preferences) fill_with_defaults() { + if p.arch == ._auto { + p.arch = get_host_arch() + } + p.expand_lookup_paths() + rpath := os.real_path(p.path) + if p.out_name == '' { + filename := os.file_name(rpath).trim_space() + mut base := filename.all_before_last('.') + if base == '' { + // The file name is just `.v` or `.vsh` or `.*` + base = filename + } + target_dir := if os.is_dir(rpath) { rpath } else { os.dir(rpath) } + p.out_name = os.join_path(target_dir, base) + // Do *NOT* be tempted to generate binaries in the current work folder, + // when -o is not given by default, like Go, Clang, GCC etc do. + // + // These compilers also are frequently used with an external build system, + // in part because of that shortcoming, to ensure that they work in a + // predictable work folder/environment. + // + // In comparison, with V, building an executable by default places it + // next to its source code, so that it can be used directly with + // functions like `os.resource_abs_path()` and `os.executable()` to + // locate resources relative to it. That enables running examples like + // this: + // `./v run examples/flappylearning/` + // instead of: + // `./v -o examples/flappylearning/flappylearning run examples/flappylearning/` + // This topic comes up periodically from time to time on Discord, and + // many CI breakages already happened, when someone decides to make V + // behave in this aspect similarly to the dumb behaviour of other + // compilers. + // + // If you do decide to break it, please *at the very least*, test it + // extensively, and make a PR about it, instead of commiting directly + // and breaking the CI, VC, and users doing `v up`. + if rpath == '$p.vroot/cmd/v' && os.is_dir('vlib/compiler') { + // Building V? Use v2, since we can't overwrite a running + // executable on Windows + the precompiled V is more + // optimized. + println('Saving the resulting V executable in `./v2`') + println('Use `v -o v cmd/v` if you want to replace current ' + 'V executable.') + p.out_name = 'v2' + } + } + rpath_name := os.file_name(rpath) + p.building_v = !p.is_repl && (rpath_name == 'v' || rpath_name == 'vfmt.v') + if p.os == ._auto { + // No OS specifed? Use current system + p.os = get_host_os() + } + // + p.try_to_use_tcc_by_default() + if p.ccompiler == '' { + p.ccompiler = default_c_compiler() + } + p.find_cc_if_cross_compiling() + p.ccompiler_type = cc_from_string(p.ccompiler) + p.is_test = p.path.ends_with('_test.v') || p.path.ends_with('_test.vv') + || p.path.all_before_last('.v').all_before_last('.').ends_with('_test') + p.is_vsh = p.path.ends_with('.vsh') + p.is_script = p.is_vsh || p.path.ends_with('.v') || p.path.ends_with('.vv') + if p.third_party_option == '' { + p.third_party_option = p.cflags + $if !windows { + if !p.third_party_option.contains('-fPIC') { + p.third_party_option += ' -fPIC' + } + } + } + // Prepare the cache manager. All options that can affect the generated cached .c files + // should go into res.cache_manager.vopts, which is used as a salt for the cache hash. + p.cache_manager = vcache.new_cache_manager([ + @VHASH, + // ensure that different v versions use separate build artefacts + '$p.backend | $p.os | $p.ccompiler | $p.is_prod | $p.sanitize', + p.cflags.trim_space(), + p.third_party_option.trim_space(), + '$p.compile_defines_all', + '$p.compile_defines', + '$p.lookup_path', + ]) + // eprintln('prefs.cache_manager: $p') + // disable use_cache for specific cases: + if os.user_os() == 'windows' { + p.use_cache = false + } + if p.build_mode == .build_module { + // eprintln('-usecache and build-module flags are not compatible') + p.use_cache = false + } + if p.is_shared { + // eprintln('-usecache and -shared flags are not compatible') + p.use_cache = false + } + if p.bare_builtin_dir == '' { + p.bare_builtin_dir = os.join_path(p.vroot, 'vlib', 'builtin', 'linux_bare') + } +} + +fn (mut p Preferences) find_cc_if_cross_compiling() { + if p.os == .windows { + $if !windows { + // Cross compiling to Windows + p.ccompiler = 'x86_64-w64-mingw32-gcc' + } + } + if p.os == .linux { + $if !linux { + // Cross compiling to Linux + p.ccompiler = 'clang' + } + } +} + +fn (mut p Preferences) try_to_use_tcc_by_default() { + if p.ccompiler == 'tcc' { + p.ccompiler = default_tcc_compiler() + return + } + if p.ccompiler == '' { + // tcc is known to fail several tests on macos, so do not + // try to use it by default, only when it is explicitly set + $if macos { + return + } + // use an optimizing compiler (i.e. gcc or clang) on -prod mode + if p.is_prod { + return + } + p.ccompiler = default_tcc_compiler() + return + } +} + +pub fn default_tcc_compiler() string { + vexe := vexe_path() + vroot := os.dir(vexe) + vtccexe := os.join_path(vroot, 'thirdparty', 'tcc', 'tcc.exe') + if os.exists(vtccexe) { + return vtccexe + } + return '' +} + +pub fn default_c_compiler() string { + // fast_clang := '/usr/local/Cellar/llvm/8.0.0/bin/clang' + // if os.exists(fast_clang) { + // return fast_clang + // } + // TODO fix $if after 'string' + $if windows { + return 'gcc' + } + return 'cc' +} + +pub fn vexe_path() string { + vexe := os.getenv('VEXE') + if vexe != '' { + return vexe + } + real_vexe_path := os.real_path(os.executable()) + os.setenv('VEXE', real_vexe_path, true) + return real_vexe_path +} diff --git a/v_windows/v/old/vlib/v/pref/os.v b/v_windows/v/old/vlib/v/pref/os.v new file mode 100644 index 0000000..578b00d --- /dev/null +++ b/v_windows/v/old/vlib/v/pref/os.v @@ -0,0 +1,116 @@ +// 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 + +pub enum OS { + _auto // Reserved so .macos cannot be misunderstood as auto + ios + macos + linux + windows + freebsd + openbsd + netbsd + dragonfly + js_node + js_browser + js_freestanding + android + solaris + serenity + vinix + haiku + raw + all +} + +// Helper function to convert string names to OS enum +pub fn os_from_string(os_str string) ?OS { + match os_str { + 'linux' { return .linux } + 'windows' { return .windows } + 'ios' { return .ios } + 'macos' { return .macos } + 'freebsd' { return .freebsd } + 'openbsd' { return .openbsd } + 'netbsd' { return .netbsd } + 'dragonfly' { return .dragonfly } + 'js', 'js_node' { return .js_node } + 'js_freestanding' { return .js_freestanding } + 'js_browser' { return .js_browser } + 'solaris' { return .solaris } + 'serenity' { return .serenity } + 'vinix' { return .vinix } + 'android' { return .android } + 'haiku' { return .haiku } + 'raw' { return .raw } + 'nix' { return .linux } + '' { return ._auto } + else { return error('bad OS $os_str') } + } +} + +pub fn (o OS) str() string { + match o { + ._auto { return 'RESERVED: AUTO' } + .ios { return 'iOS' } + .macos { return 'MacOS' } + .linux { return 'Linux' } + .windows { return 'Windows' } + .freebsd { return 'FreeBSD' } + .openbsd { return 'OpenBSD' } + .netbsd { return 'NetBSD' } + .dragonfly { return 'Dragonfly' } + .js_node { return 'NodeJS' } + .js_freestanding { return 'JavaScript' } + .js_browser { return 'JavaScript(Browser)' } + .android { return 'Android' } + .solaris { return 'Solaris' } + .serenity { return 'SerenityOS' } + .vinix { return 'Vinix' } + .haiku { return 'Haiku' } + .raw { return 'Raw' } + .all { return 'all' } + } +} + +pub fn get_host_os() OS { + $if linux { + return .linux + } + $if ios { + return .ios + } + $if macos { + return .macos + } + $if windows { + return .windows + } + $if freebsd { + return .freebsd + } + $if openbsd { + return .openbsd + } + $if netbsd { + return .netbsd + } + $if dragonfly { + return .dragonfly + } + $if serenity { + return .serenity + } + $if vinix { + return .vinix + } + $if solaris { + return .solaris + } + $if haiku { + return .haiku + } + panic('unknown host OS') +} diff --git a/v_windows/v/old/vlib/v/pref/pref.v b/v_windows/v/old/vlib/v/pref/pref.v new file mode 100644 index 0000000..8ca843a --- /dev/null +++ b/v_windows/v/old/vlib/v/pref/pref.v @@ -0,0 +1,828 @@ +// 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 + is_debug bool // turned on by -g or -cg, it tells v to pass -g to the C backend compiler. + is_vlines bool // turned on by -g (it slows down .tmp.c generation slightly). + // 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). + sanitize bool // use Clang's new "-fsanitize" option + 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 + 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 + show_depgraph bool // -show-depgraph, print the program module dependency graph, in a Graphviz DOT format to stdout + 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 // when set, use cached modules to speed up subsequent compilations, at the cost of slower initial ones (while the modules are cached) + 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 // when set, use `upx` to compress the generated executable + // 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 + } + '-show-depgraph' { + res.show_depgraph = 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 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' + } + } else if is_source_file(command) { + res.path = command + } + 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 (pref &Preferences) should_output_to_stdout() bool { + return pref.out_name.ends_with('/-') || pref.out_name.ends_with(r'\-') +} + +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) +} diff --git a/v_windows/v/old/vlib/v/pref/should_compile.v b/v_windows/v/old/vlib/v/pref/should_compile.v new file mode 100644 index 0000000..5f69fa4 --- /dev/null +++ b/v_windows/v/old/vlib/v/pref/should_compile.v @@ -0,0 +1,217 @@ +module pref + +import os + +pub fn (prefs &Preferences) should_compile_filtered_files(dir string, files_ []string) []string { + mut res := []string{} + mut files := files_.clone() + files.sort() + mut all_v_files := []string{} + for file in files { + if !file.ends_with('.v') && !file.ends_with('.vh') { + continue + } + if file.ends_with('_test.v') + || file.all_before_last('.v').all_before_last('.').ends_with('_test') { + continue + } + if prefs.backend == .c && !prefs.should_compile_c(file) { + continue + } + if prefs.backend.is_js() && !prefs.should_compile_js(file) { + continue + } + if prefs.backend == .native && !prefs.should_compile_native(file) { + continue + } + if !prefs.backend.is_js() && !prefs.should_compile_asm(file) { + continue + } + if file.starts_with('.#') { + continue + } + if file.contains('_d_') { + if prefs.compile_defines_all.len == 0 { + continue + } + mut allowed := false + for cdefine in prefs.compile_defines { + file_postfix := '_d_${cdefine}.v' + if file.ends_with(file_postfix) { + allowed = true + break + } + } + if !allowed { + continue + } + } + if file.contains('_notd_') { + mut allowed := true + for cdefine in prefs.compile_defines { + file_postfix := '_notd_${cdefine}.v' + if file.ends_with(file_postfix) { + allowed = false + break + } + } + if !allowed { + continue + } + } + all_v_files << os.join_path(dir, file) + } + // + mut defaults := []string{} + mut fnames_no_postfixes := map[string][]string{} + for file in all_v_files { + if file.contains('default.c.v') { + defaults << file + } else { + res << file + no_postfix_key := fname_without_platform_postfix(file) + mut candidates := fnames_no_postfixes[no_postfix_key] + candidates << file + fnames_no_postfixes[no_postfix_key] = candidates + } + } + for file in defaults { + no_postfix_key := fname_without_platform_postfix(file) + if no_postfix_key in fnames_no_postfixes { + if prefs.is_verbose { + println('>>> should_compile_filtered_files: skipping _default.c.v file $file ; the specialized versions are: ${fnames_no_postfixes[no_postfix_key]}') + } + continue + } + res << file + } + if prefs.is_verbose { + // println('>>> prefs: $prefs') + println('>>> should_compile_filtered_files: res: $res') + } + return res +} + +fn fname_without_platform_postfix(file string) string { + res := file.replace_each([ + 'default.c.v', + '_', + 'nix.c.v', + '_', + 'windows.c.v', + '_', + 'linux.c.v', + '_', + 'darwin.c.v', + '_', + 'macos.c.v', + '_', + 'android.c.v', + '_', + 'freebsd.c.v', + '_', + 'netbsd.c.v', + '_', + 'dragonfly.c.v', + '_', + 'solaris.c.v', + '_', + 'native.v', + '_', + ]) + return res +} + +pub fn (prefs &Preferences) should_compile_native(file string) bool { + // allow custom filtering for native backends, + // but if there are no other rules, default to the c backend rules + return prefs.should_compile_c(file) +} + +pub fn (prefs &Preferences) should_compile_c(file string) bool { + if file.ends_with('.js.v') { + // Probably something like `a.js.v`. + return false + } + if prefs.is_bare && file.ends_with('.freestanding.v') { + return true + } + if prefs.os == .all { + return true + } + if prefs.backend != .native && file.ends_with('_native.v') { + return false + } + if prefs.os != .windows && (file.ends_with('_windows.c.v') || file.ends_with('_windows.v')) { + return false + } + if prefs.os != .linux && (file.ends_with('_linux.c.v') || file.ends_with('_linux.v')) { + return false + } + if prefs.os != .macos && (file.ends_with('_darwin.c.v') || file.ends_with('_darwin.v')) { + return false + } + if (file.ends_with('_ios.c.v') || file.ends_with('_ios.v')) && prefs.os != .ios { + return false + } + if file.ends_with('_nix.c.v') && prefs.os == .windows { + return false + } + if prefs.os != .macos && (file.ends_with('_macos.c.v') || file.ends_with('_macos.v')) { + return false + } + if prefs.os == .windows && file.ends_with('_nix.c.v') { + return false + } + if prefs.os != .android && file.ends_with('_android.c.v') { + return false + } + if prefs.os != .freebsd && file.ends_with('_freebsd.c.v') { + return false + } + if prefs.os != .openbsd && file.ends_with('_openbsd.c.v') { + return false + } + if prefs.os != .netbsd && file.ends_with('_netbsd.c.v') { + return false + } + if prefs.os != .dragonfly && file.ends_with('_dragonfly.c.v') { + return false + } + if prefs.os != .solaris && file.ends_with('_solaris.c.v') { + return false + } + if prefs.os != .serenity && file.ends_with('_serenity.c.v') { + return false + } + if prefs.os != .vinix && file.ends_with('_vinix.c.v') { + return false + } + return true +} + +pub fn (prefs &Preferences) should_compile_asm(path string) bool { + if path.count('.') != 2 || path.ends_with('c.v') || path.ends_with('js.v') { + return true + } + file := path.all_before_last('.v') + arch := arch_from_string(file.all_after_last('.')) or { Arch._auto } + + if arch != prefs.arch && prefs.arch != ._auto && arch != ._auto { + return false + } + os := os_from_string(file.all_after_last('_').all_before('.')) or { OS._auto } + + if os != prefs.os && prefs.os != ._auto && os != ._auto { + return false + } + return true +} + +pub fn (prefs &Preferences) should_compile_js(file string) bool { + if !file.ends_with('.js.v') && file.split('.').len > 2 { + // Probably something like `a.c.v`. + return false + } + return true +} |