cmd/v: rewrite flags
parent
522de0871a
commit
aab31f4b35
|
@ -8,7 +8,7 @@ uname -a
|
||||||
|
|
||||||
make -j4
|
make -j4
|
||||||
|
|
||||||
./v --version
|
./v -version
|
||||||
|
|
||||||
du -s .
|
du -s .
|
||||||
|
|
||||||
|
|
|
@ -131,7 +131,7 @@ jobs:
|
||||||
../../vprod gen1m.v
|
../../vprod gen1m.v
|
||||||
./gen1m > 1m.v
|
./gen1m > 1m.v
|
||||||
echo "Building it..."
|
echo "Building it..."
|
||||||
../../vprod -x64 -o 1m 1m.v
|
../../vprod -backend x64 -o 1m 1m.v
|
||||||
echo "Running it..."
|
echo "Running it..."
|
||||||
ls
|
ls
|
||||||
# ./1m
|
# ./1m
|
||||||
|
@ -144,7 +144,7 @@ jobs:
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y postgresql libpq-dev libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
run: sudo rm -f /etc/apt/sources.list.d/dotnetdev.list /etc/apt/sources.list.d/microsoft-prod.list; sudo apt-get update; sudo apt-get install --quiet -y postgresql libpq-dev libglfw3 libglfw3-dev libfreetype6-dev libssl-dev sqlite3 libsqlite3-dev libsdl2-dev libsdl2-ttf-dev libsdl2-mixer-dev libsdl2-image-dev
|
||||||
- name: Download V
|
- name: Download V
|
||||||
run: wget https://github.com/vlang/v/releases/latest/download/v_linux.zip && unzip v_linux.zip && ./v --version
|
run: wget https://github.com/vlang/v/releases/latest/download/v_linux.zip && unzip v_linux.zip && ./v -version
|
||||||
- name: Test V
|
- name: Test V
|
||||||
run: ./v examples/hello_world.v && examples/hello_world #&& ./v -silent build-examples
|
run: ./v examples/hello_world.v && examples/hello_world #&& ./v -silent build-examples
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ jobs:
|
||||||
brew install freetype glfw openssl sdl2 sdl2_ttf sdl2_mixer sdl2_image
|
brew install freetype glfw openssl sdl2 sdl2_ttf sdl2_mixer sdl2_image
|
||||||
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/"
|
export LIBRARY_PATH="$LIBRARY_PATH:/usr/local/opt/openssl/lib/"
|
||||||
- name: Download V
|
- name: Download V
|
||||||
run: wget https://github.com/vlang/v/releases/latest/download/v_macos.zip && unzip v_macos.zip && ./v --version
|
run: wget https://github.com/vlang/v/releases/latest/download/v_macos.zip && unzip v_macos.zip && ./v -version
|
||||||
- name: Test V
|
- name: Test V
|
||||||
run: ./v examples/hello_world.v && examples/hello_world #&& ./v -silent build-examples
|
run: ./v examples/hello_world.v && examples/hello_world #&& ./v -silent build-examples
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ jobs:
|
||||||
curl -L https://github.com/vlang/v/releases/latest/download/v_windows.zip -o v_windows.zip
|
curl -L https://github.com/vlang/v/releases/latest/download/v_windows.zip -o v_windows.zip
|
||||||
echo Unzipping...
|
echo Unzipping...
|
||||||
unzip v_windows.zip
|
unzip v_windows.zip
|
||||||
v.exe --version
|
v.exe -version
|
||||||
echo Done
|
echo Done
|
||||||
dir
|
dir
|
||||||
- name: Test V
|
- name: Test V
|
||||||
|
|
|
@ -17,4 +17,4 @@ RUN apk --no-cache add \
|
||||||
|
|
||||||
RUN apk --no-cache add --virtual sdl2deps sdl2-dev sdl2_ttf-dev sdl2_mixer-dev sdl2_image-dev
|
RUN apk --no-cache add --virtual sdl2deps sdl2-dev sdl2_ttf-dev sdl2_mixer-dev sdl2_image-dev
|
||||||
|
|
||||||
RUN git clone https://github.com/vlang/v /opt/vlang && make && v --version
|
RUN git clone https://github.com/vlang/v /opt/vlang && make && v -version
|
||||||
|
|
|
@ -19,11 +19,12 @@ pub mut:
|
||||||
show_ok_tests bool
|
show_ok_tests bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_test_session(vargs string) TestSession {
|
pub fn new_test_session(_vargs string) TestSession {
|
||||||
|
vargs := _vargs.replace('-silent', '')
|
||||||
return TestSession{
|
return TestSession{
|
||||||
vexe: pref.vexe_path()
|
vexe: pref.vexe_path()
|
||||||
vargs: vargs
|
vargs: vargs
|
||||||
show_ok_tests: !vargs.contains('-silent')
|
show_ok_tests: !_vargs.contains('-silent')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ fn (c &Context) prepare_v(cdir string, commit string) {
|
||||||
scripting.show_sizes_of_files(['$cdir/cv', '$cdir/cv_stripped', '$cdir/cv_stripped_upxed'])
|
scripting.show_sizes_of_files(['$cdir/cv', '$cdir/cv_stripped', '$cdir/cv_stripped_upxed'])
|
||||||
scripting.show_sizes_of_files(['$cdir/v', '$cdir/v_stripped', '$cdir/v_stripped_upxed'])
|
scripting.show_sizes_of_files(['$cdir/v', '$cdir/v_stripped', '$cdir/v_stripped_upxed'])
|
||||||
scripting.show_sizes_of_files(['$cdir/vprod', '$cdir/vprod_stripped', '$cdir/vprod_stripped_upxed'])
|
scripting.show_sizes_of_files(['$cdir/vprod', '$cdir/vprod_stripped', '$cdir/vprod_stripped_upxed'])
|
||||||
vversion := scripting.run('$cdir/v --version')
|
vversion := scripting.run('$cdir/v -version')
|
||||||
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
vcommit := scripting.run('git rev-parse --short --verify HEAD')
|
||||||
println('V version is: ${vversion} , local source commit: ${vcommit}')
|
println('V version is: ${vversion} , local source commit: ${vcommit}')
|
||||||
if vgit_context.vvlocation == 'cmd/v' {
|
if vgit_context.vvlocation == 'cmd/v' {
|
||||||
|
|
|
@ -168,7 +168,12 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
mut compiler_params := &pref.Preferences{}
|
mut compiler_params := &pref.Preferences{}
|
||||||
target_os := file_to_target_os(file)
|
target_os := file_to_target_os(file)
|
||||||
if target_os != '' {
|
if target_os != '' {
|
||||||
compiler_params.os = pref.os_from_string(target_os)
|
//TODO Remove temporary variable once it compiles correctly in C
|
||||||
|
tmp := pref.os_from_string(target_os) or {
|
||||||
|
eprintln('unknown operating system $target_os')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
compiler_params.os = tmp
|
||||||
}
|
}
|
||||||
mut cfile := file
|
mut cfile := file
|
||||||
mut mod_folder_parent := tmpfolder
|
mut mod_folder_parent := tmpfolder
|
||||||
|
@ -189,7 +194,7 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
}
|
}
|
||||||
os.write_file(main_program_file, main_program_content)
|
os.write_file(main_program_file, main_program_content)
|
||||||
cfile = main_program_file
|
cfile = main_program_file
|
||||||
compiler_params.user_mod_path = mod_folder_parent
|
compiler_params.lookup_path = [mod_folder_parent, '@vlib', '@vmodule']
|
||||||
}
|
}
|
||||||
if !is_test_file && mod_name == 'main' {
|
if !is_test_file && mod_name == 'main' {
|
||||||
// NB: here, file is guaranted to be a main. We do not know however
|
// NB: here, file is guaranted to be a main. We do not know however
|
||||||
|
@ -229,19 +234,17 @@ fn (foptions &FormatOptions) format_file(file string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_compiler_options( compiler_params &pref.Preferences ) {
|
fn print_compiler_options( compiler_params &pref.Preferences ) {
|
||||||
eprintln(' os: ' + compiler_params.os.str() )
|
eprintln(' os: ' + compiler_params.os.str() )
|
||||||
eprintln(' ccompiler: $compiler_params.ccompiler' )
|
eprintln(' ccompiler: $compiler_params.ccompiler' )
|
||||||
eprintln(' mod: $compiler_params.mod ')
|
eprintln(' mod: $compiler_params.mod ')
|
||||||
eprintln(' path: $compiler_params.path ')
|
eprintln(' path: $compiler_params.path ')
|
||||||
eprintln(' out_name: $compiler_params.out_name ')
|
eprintln(' out_name: $compiler_params.out_name ')
|
||||||
eprintln(' vroot: $compiler_params.vroot ')
|
eprintln(' vroot: $compiler_params.vroot ')
|
||||||
eprintln(' vpath: $compiler_params.vpath ')
|
eprintln('lookup_path: $compiler_params.lookup_path ')
|
||||||
eprintln(' vlib_path: $compiler_params.vlib_path ')
|
eprintln(' out_name: $compiler_params.out_name ')
|
||||||
eprintln(' out_name: $compiler_params.out_name ')
|
eprintln(' cflags: $compiler_params.cflags ')
|
||||||
eprintln(' umpath: $compiler_params.user_mod_path ')
|
eprintln(' is_test: $compiler_params.is_test ')
|
||||||
eprintln(' cflags: $compiler_params.cflags ')
|
eprintln(' is_script: $compiler_params.is_script ')
|
||||||
eprintln(' is_test: $compiler_params.is_test ')
|
|
||||||
eprintln(' is_script: $compiler_params.is_script ')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path string) {
|
fn (foptions &FormatOptions) post_process_file(file string, formatted_file_path string) {
|
||||||
|
|
|
@ -144,7 +144,7 @@ pub fn run_repl(workdir string, vrepl_prefix string) []string {
|
||||||
if r.line.starts_with('print') {
|
if r.line.starts_with('print') {
|
||||||
source_code := r.functions.join('\n') + r.lines.join('\n') + '\n' + r.line
|
source_code := r.functions.join('\n') + r.lines.join('\n') + '\n' + r.line
|
||||||
os.write_file(file, source_code)
|
os.write_file(file, source_code)
|
||||||
s := os.exec('"$vexe" run $file -repl') or {
|
s := os.exec('"$vexe" -repl run $file') or {
|
||||||
rerror(err)
|
rerror(err)
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ pub fn run_repl(workdir string, vrepl_prefix string) []string {
|
||||||
}
|
}
|
||||||
temp_source_code := r.functions.join('\n') + r.lines.join('\n') + '\n' + r.temp_lines.join('\n') + '\n' + temp_line
|
temp_source_code := r.functions.join('\n') + r.lines.join('\n') + '\n' + r.temp_lines.join('\n') + '\n' + temp_line
|
||||||
os.write_file(temp_file, temp_source_code)
|
os.write_file(temp_file, temp_source_code)
|
||||||
s := os.exec('"$vexe" run $temp_file -repl') or {
|
s := os.exec('"$vexe" -repl run $temp_file') or {
|
||||||
println("SDFSDF")
|
println("SDFSDF")
|
||||||
rerror(err)
|
rerror(err)
|
||||||
return []
|
return []
|
||||||
|
@ -237,6 +237,6 @@ pub fn rerror(s string) {
|
||||||
|
|
||||||
fn v_version() string {
|
fn v_version() string {
|
||||||
vexe := os.getenv('VEXE')
|
vexe := os.getenv('VEXE')
|
||||||
vversion_res := os.exec('$vexe --version') or { panic('"$vexe --version" is not working') }
|
vversion_res := os.exec('$vexe -version') or { panic('"$vexe -version" is not working') }
|
||||||
return vversion_res.output
|
return vversion_res.output
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,227 +0,0 @@
|
||||||
// Copyright (c) 2019-2020 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 main
|
|
||||||
|
|
||||||
import (
|
|
||||||
compiler
|
|
||||||
filepath
|
|
||||||
os
|
|
||||||
os.cmdline
|
|
||||||
v.pref
|
|
||||||
)
|
|
||||||
|
|
||||||
//TODO Cleanup this file. This file ended up like a dump for functions that do not belong in `compiler`.
|
|
||||||
//Maybe restructure the functions below into different V files
|
|
||||||
|
|
||||||
pub fn new_v(args []string) &compiler.V {
|
|
||||||
// Create modules dirs if they are missing
|
|
||||||
if !os.is_dir(compiler.v_modules_path) {
|
|
||||||
os.mkdir(compiler.v_modules_path)or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
os.mkdir('$compiler.v_modules_path${filepath.separator}cache')or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
vroot := filepath.dir(pref.vexe_path())
|
|
||||||
// optional, custom modules search path
|
|
||||||
user_mod_path := cmdline.option(args, '-user_mod_path', '')
|
|
||||||
vlib_path := cmdline.option(args, '-vlib-path', '')
|
|
||||||
vpath := cmdline.option(args, '-vpath', '')
|
|
||||||
target_os := cmdline.option(args, '-os', '')
|
|
||||||
if target_os == 'msvc' {
|
|
||||||
// notice that `-os msvc` became `-cc msvc`
|
|
||||||
println('V error: use the flag `-cc msvc` to build using msvc')
|
|
||||||
os.flush()
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
mut out_name := cmdline.option(args, '-o', '')
|
|
||||||
mut dir := args[args.len-1]//.last()
|
|
||||||
if 'run' in args {
|
|
||||||
args_after_run := cmdline.only_non_options( cmdline.options_after(args,['run']) )
|
|
||||||
dir = if args_after_run.len>0 { args_after_run[0] } else { '' }
|
|
||||||
}
|
|
||||||
if dir == 'v.v' {
|
|
||||||
println('looks like you are trying to build V with an old command')
|
|
||||||
println('use `v -o v cmd/v` instead of `v -o v v.v`')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
if dir.ends_with(filepath.separator) {
|
|
||||||
dir = dir.all_before_last(filepath.separator)
|
|
||||||
}
|
|
||||||
if dir.starts_with('.$filepath.separator') {
|
|
||||||
dir = dir[2..]
|
|
||||||
}
|
|
||||||
if args.len < 2 {
|
|
||||||
dir = ''
|
|
||||||
}
|
|
||||||
|
|
||||||
// build mode
|
|
||||||
mut build_mode := pref.BuildMode.default_mode
|
|
||||||
mut mod := ''
|
|
||||||
joined_args := args.join(' ')
|
|
||||||
if joined_args.contains('build module ') {
|
|
||||||
build_mode = .build_module
|
|
||||||
os.chdir(vroot)
|
|
||||||
// v build module ~/v/os => os.o
|
|
||||||
mod_path := if dir.contains('vlib') { dir.all_after('vlib' + filepath.separator) } else if dir.starts_with('.\\') || dir.starts_with('./') { dir[2..] } else if dir.starts_with(filepath.separator) { dir.all_after(filepath.separator) } else { dir }
|
|
||||||
mod = mod_path.replace(filepath.separator, '.')
|
|
||||||
println('Building module "${mod}" (dir="$dir")...')
|
|
||||||
// out_name = '$TmpPath/vlib/${base}.o'
|
|
||||||
if !out_name.ends_with('.c') {
|
|
||||||
out_name = mod
|
|
||||||
}
|
|
||||||
// Cross compiling? Use separate dirs for each os
|
|
||||||
/*
|
|
||||||
if target_os != os.user_os() {
|
|
||||||
os.mkdir('$TmpPath/vlib/$target_os') or { panic(err) }
|
|
||||||
out_name = '$TmpPath/vlib/$target_os/${base}.o'
|
|
||||||
println('target_os=$target_os user_os=${os.user_os()}')
|
|
||||||
println('!Cross compiling $out_name')
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
}
|
|
||||||
// `v -o dir/exec`, create "dir/" if it doesn't exist
|
|
||||||
if out_name.contains(filepath.separator) {
|
|
||||||
d := out_name.all_before_last(filepath.separator)
|
|
||||||
if !os.is_dir(d) {
|
|
||||||
println('creating a new directory "$d"')
|
|
||||||
os.mkdir(d)or{
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// println('VROOT=$vroot')
|
|
||||||
cflags := cmdline.options(args, '-cflags').join(' ')
|
|
||||||
defines := cmdline.options(args, '-d')
|
|
||||||
compile_defines, compile_defines_all := parse_defines( defines )
|
|
||||||
|
|
||||||
rdir := os.realpath(dir)
|
|
||||||
rdir_name := filepath.filename(rdir)
|
|
||||||
if '-bare' in args {
|
|
||||||
println('V error: use -freestanding instead of -bare')
|
|
||||||
os.flush()
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
is_repl := '-repl' in args
|
|
||||||
ccompiler := cmdline.option(args, '-cc', '')
|
|
||||||
mut prefs := &pref.Preferences{
|
|
||||||
os: pref.os_from_string(target_os)
|
|
||||||
is_so: '-shared' in args
|
|
||||||
is_solive: '-solive' in args
|
|
||||||
is_prod: '-prod' in args
|
|
||||||
is_verbose: '-verbose' in args || '--verbose' in args
|
|
||||||
is_debug: '-g' in args || '-cg' in args
|
|
||||||
is_vlines: '-g' in args && !('-cg' in args)
|
|
||||||
is_keep_c: '-keep_c' in args
|
|
||||||
is_pretty_c: '-pretty_c' in args
|
|
||||||
is_cache: '-cache' in args
|
|
||||||
is_stats: '-stats' in args
|
|
||||||
obfuscate: '-obf' in args
|
|
||||||
is_prof: '-prof' in args
|
|
||||||
is_live: '-live' in args
|
|
||||||
sanitize: '-sanitize' in args
|
|
||||||
// nofmt: '-nofmt' in args
|
|
||||||
|
|
||||||
show_c_cmd: '-show_c_cmd' in args
|
|
||||||
translated: 'translated' in args
|
|
||||||
is_run: 'run' in args
|
|
||||||
autofree: '-autofree' in args
|
|
||||||
compress: '-compress' in args
|
|
||||||
enable_globals: '--enable-globals' in args
|
|
||||||
fast: '-fast' in args
|
|
||||||
is_bare: '-freestanding' in args
|
|
||||||
x64: '-x64' in args
|
|
||||||
output_cross_c: '-output-cross-platform-c' in args
|
|
||||||
prealloc: '-prealloc' in args
|
|
||||||
is_repl: is_repl
|
|
||||||
build_mode: build_mode
|
|
||||||
cflags: cflags
|
|
||||||
ccompiler: ccompiler
|
|
||||||
building_v: !is_repl && (rdir_name == 'compiler' || rdir_name == 'v' || rdir_name == 'vfmt.v' || rdir_name == 'cmd/v' || dir.contains('vlib'))
|
|
||||||
// is_fmt: comptime_define == 'vfmt'
|
|
||||||
|
|
||||||
user_mod_path: user_mod_path
|
|
||||||
vlib_path: vlib_path
|
|
||||||
vpath: vpath
|
|
||||||
v2: '-v2' in args
|
|
||||||
vroot: vroot
|
|
||||||
out_name: out_name
|
|
||||||
path: dir
|
|
||||||
compile_defines: compile_defines
|
|
||||||
compile_defines_all: compile_defines_all
|
|
||||||
mod: mod
|
|
||||||
}
|
|
||||||
if prefs.is_verbose || prefs.is_debug {
|
|
||||||
println('C compiler=$prefs.ccompiler')
|
|
||||||
}
|
|
||||||
$if !linux {
|
|
||||||
if prefs.is_bare && !out_name.ends_with('.c') {
|
|
||||||
println('V error: -freestanding only works on Linux for now')
|
|
||||||
os.flush()
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
prefs.fill_with_defaults()
|
|
||||||
|
|
||||||
// v.exe's parent directory should contain vlib
|
|
||||||
if !os.is_dir(prefs.vlib_path) || !os.is_dir(prefs.vlib_path + filepath.separator + 'builtin') {
|
|
||||||
// println('vlib not found, downloading it...')
|
|
||||||
/*
|
|
||||||
ret := os.system('git clone --depth=1 https://github.com/vlang/v .')
|
|
||||||
if ret != 0 {
|
|
||||||
println('failed to `git clone` vlib')
|
|
||||||
println('make sure you are online and have git installed')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
println('vlib not found. It should be next to the V executable.')
|
|
||||||
println('Go to https://vlang.io to install V.')
|
|
||||||
println('(os.executable=${os.executable()} vlib_path=$prefs.vlib_path vexe_path=${pref.vexe_path()}')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if prefs.is_script && !os.exists(dir) {
|
|
||||||
println('`$dir` does not exist')
|
|
||||||
exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return compiler.new_v(prefs)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_c_compiler_thirdparty_options(args []string) string {
|
|
||||||
mut cflags := cmdline.options(args, '-cflags')
|
|
||||||
$if !windows {
|
|
||||||
cflags << '-fPIC'
|
|
||||||
}
|
|
||||||
if '-m32' in args {
|
|
||||||
cflags << '-m32'
|
|
||||||
}
|
|
||||||
return cflags.join(' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_defines(defines []string) ([]string,[]string) {
|
|
||||||
// '-d abc -d xyz=1 -d qwe=0' should produce:
|
|
||||||
// compile_defines: ['abc','xyz']
|
|
||||||
// compile_defines_all ['abc','xyz','qwe']
|
|
||||||
mut compile_defines := []string
|
|
||||||
mut compile_defines_all := []string
|
|
||||||
for dfn in defines {
|
|
||||||
dfn_parts := dfn.split('=')
|
|
||||||
if dfn_parts.len == 1 {
|
|
||||||
compile_defines << dfn
|
|
||||||
compile_defines_all << dfn
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if dfn_parts.len == 2 {
|
|
||||||
compile_defines_all << dfn_parts[0]
|
|
||||||
if dfn_parts[1] == '1' {
|
|
||||||
compile_defines << dfn_parts[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return compile_defines, compile_defines_all
|
|
||||||
}
|
|
115
cmd/v/flag.v
115
cmd/v/flag.v
|
@ -3,56 +3,25 @@
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module main
|
module main
|
||||||
|
|
||||||
import os
|
import (
|
||||||
|
internal.flag
|
||||||
|
os
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//list_of_flags contains a list of flags where an argument is expected past it.
|
//list_of_flags contains a list of flags where an argument is expected past it.
|
||||||
list_of_flags = [
|
list_of_flags = [
|
||||||
'-o', '-os', '-cc', '-cflags', '-d'
|
'o', 'output', 'd', 'define', 'b', 'backend', 'cc', 'os', 'target-os', 'arch',
|
||||||
|
'csource', 'cf', 'cflags', 'path'
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
fn get_basic_command_and_option(args []string) (string, []string) {
|
|
||||||
mut option := []string
|
|
||||||
for i, arg in args {
|
|
||||||
if i == 0 {
|
|
||||||
//Skip executable
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if arg == '--' {
|
|
||||||
//End of list of options. The next one is the command.
|
|
||||||
if i+1 < os.args.len {
|
|
||||||
return os.args[i+1], option
|
|
||||||
}
|
|
||||||
//There's no option past this
|
|
||||||
return '', option
|
|
||||||
}
|
|
||||||
if arg in list_of_flags {
|
|
||||||
i++
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if arg[0] == `-` {
|
|
||||||
option << arg
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
//It's not a flag. We did not skip it. It's a command.
|
|
||||||
return arg, option
|
|
||||||
}
|
|
||||||
|
|
||||||
//There's no arguments that were not part of a flag.
|
|
||||||
return '', option
|
|
||||||
}
|
|
||||||
|
|
||||||
fn non_empty(arg []string) []string {
|
|
||||||
return arg.filter(it != '')
|
|
||||||
}
|
|
||||||
|
|
||||||
fn join_flags_and_argument() []string {
|
fn join_flags_and_argument() []string {
|
||||||
vosargs := os.getenv('VOSARGS')
|
vosargs := os.getenv('VOSARGS')
|
||||||
if vosargs != '' {
|
if vosargs != '' {
|
||||||
return non_empty(vosargs.split(' '))
|
return vosargs.split(' ')
|
||||||
}
|
}
|
||||||
|
// No VOSARGS? Look for VFLAGS and concat it with command-line options.
|
||||||
mut args := []string
|
mut args := []string
|
||||||
vflags := os.getenv('VFLAGS')
|
vflags := os.getenv('VFLAGS')
|
||||||
if vflags != '' {
|
if vflags != '' {
|
||||||
|
@ -61,8 +30,70 @@ fn join_flags_and_argument() []string {
|
||||||
if os.args.len > 1 {
|
if os.args.len > 1 {
|
||||||
args << os.args[1..]
|
args << os.args[1..]
|
||||||
}
|
}
|
||||||
return non_empty(args)
|
return args
|
||||||
|
}
|
||||||
|
// No VFLAGS too? Just return command-line args.
|
||||||
|
return os.args
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_flags(flag string, f mut flag.Instance, prefs mut flag.MainCmdPreferences) {
|
||||||
|
match flag {
|
||||||
|
'v' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_one
|
||||||
|
}
|
||||||
|
'vv' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_two
|
||||||
|
}
|
||||||
|
'vvv' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_three
|
||||||
|
}
|
||||||
|
'verbose' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
level := f.int() or {
|
||||||
|
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match level {
|
||||||
|
0 {} //Zero verbosity is already default.
|
||||||
|
1 {
|
||||||
|
prefs.verbosity = .level_one
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
prefs.verbosity = .level_two
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
prefs.verbosity = .level_three
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'h', 'help' {
|
||||||
|
f.is_equivalent_to(['h', 'help'])
|
||||||
|
prefs.action = .help
|
||||||
|
}
|
||||||
|
'v', 'version' {
|
||||||
|
f.is_equivalent_to(['v', 'version'])
|
||||||
|
prefs.action = .version
|
||||||
|
}
|
||||||
|
'-version', '-help' {
|
||||||
|
println('V error: `-$flag` has been deprecated. Use `$flag` instead.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prefs.unknown_flag = '-$flag'
|
||||||
|
if !(flag in list_of_flags) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.string() or {
|
||||||
|
println('V error: Error parsing flag. Expected value for `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return non_empty(os.args)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
import (
|
||||||
|
os
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
fn check_for_common_mistake(args []string, p &pref.Preferences) {
|
||||||
|
// Note: This feature is still currently commonly used. Uncomment this when
|
||||||
|
// proper deprecation detection is ready.
|
||||||
|
if p.out_name.ends_with('.c') && p.backend == .c {
|
||||||
|
//println('HINT: `-o $p.out_name` implies `-csource keep` and does not results in an executable currently.')
|
||||||
|
//println(' To overwrite this, specify `-csource drop` explicitly.')
|
||||||
|
}
|
||||||
|
if p.out_name.ends_with('.js') && p.backend != .js {
|
||||||
|
println('HINT: `-o $p.out_name` implies `-backend js` currently.')
|
||||||
|
//println(' To overwrite this, specify the intended backend explicitly.')
|
||||||
|
}
|
||||||
|
if p.path == 'vlib/compiler' || p.path == 'v.v' {
|
||||||
|
println('HINT: The V compiler is now located in `cmd/v`.')
|
||||||
|
println(' `$p.path` is no longer the correct path to compile if you are intending to do so.')
|
||||||
|
}
|
||||||
|
if !p.path.ends_with('.v') && !os.is_dir(p.path) && os.is_dir(p.path + os.path_separator) {
|
||||||
|
println('HINT: `$p.path` is not a directory nor a file suffixed with `.v`.')
|
||||||
|
println(' Did you perhaps accidentally reference the compiled executable?')
|
||||||
|
println(' To make sure V detects the directory correctly, add the path separator to the end of the path like so:')
|
||||||
|
println(' `v $p.path$os.path_separator`')
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,40 +1,29 @@
|
||||||
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license
|
// Use of this source code is governed by an MIT license
|
||||||
// that can be found in the LICENSE file.
|
// that can be found in the LICENSE file.
|
||||||
module main
|
module compile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
benchmark
|
benchmark
|
||||||
|
compiler
|
||||||
os
|
os
|
||||||
os.cmdline
|
|
||||||
compiler
|
compiler
|
||||||
)
|
)
|
||||||
|
|
||||||
fn compile(command string, args []string) {
|
pub fn compile(command string, args []string) {
|
||||||
// Construct the V object from command line arguments
|
// Construct the V object from command line arguments
|
||||||
mut v := new_v(args)
|
parse_and_output_new_format(args)
|
||||||
if v.pref.is_verbose {
|
prefs, remaining := parse_arguments(args)
|
||||||
|
check_for_common_mistake(args, &prefs)
|
||||||
|
mut v := compiler.new_v(prefs)
|
||||||
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
println(args)
|
println(args)
|
||||||
}
|
}
|
||||||
if command == 'run' {
|
|
||||||
// always recompile for now, too error prone to skip recompilation otherwise
|
|
||||||
// for example for -repl usage, especially when piping lines to v
|
|
||||||
if v.pref.x64 {
|
|
||||||
v.compile_x64()
|
|
||||||
}
|
|
||||||
else if v.pref.v2 {
|
|
||||||
v.compile2()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
v.compile()
|
|
||||||
}
|
|
||||||
run_compiled_executable_and_exit(v, args)
|
|
||||||
}
|
|
||||||
mut tmark := benchmark.new_benchmark()
|
mut tmark := benchmark.new_benchmark()
|
||||||
if v.pref.x64 {
|
if v.pref.backend == .x64 {
|
||||||
v.compile_x64()
|
v.compile_x64()
|
||||||
}
|
}
|
||||||
else if v.pref.v2 {
|
else if v.pref.backend == .experimental {
|
||||||
v.compile2()
|
v.compile2()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -44,20 +33,22 @@ fn compile(command string, args []string) {
|
||||||
tmark.stop()
|
tmark.stop()
|
||||||
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
println('compilation took: ' + tmark.total_duration().str() + 'ms')
|
||||||
}
|
}
|
||||||
if v.pref.is_test {
|
if v.pref.is_test || v.pref.is_run {
|
||||||
run_compiled_executable_and_exit(v, args)
|
run_compiled_executable_and_exit(v, remaining)
|
||||||
}
|
}
|
||||||
v.finalize_compilation()
|
v.finalize_compilation()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_compiled_executable_and_exit(v &compiler.V, args []string) {
|
pub fn run_compiled_executable_and_exit(v &compiler.V, remaining_args []string) {
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
println('============ running $v.pref.out_name ============')
|
println('============ running $v.pref.out_name ============')
|
||||||
}
|
}
|
||||||
mut cmd := '"${v.pref.out_name}"'
|
mut cmd := '"${v.pref.out_name}"'
|
||||||
args_after_no_options := cmdline.only_non_options( cmdline.options_after(args,['run','test']) )
|
if remaining_args.len > 1 {
|
||||||
if args_after_no_options.len > 1 {
|
cmd += ' ' + remaining_args[1..].join(' ')
|
||||||
cmd += ' ' + args_after_no_options[1..].join(' ')
|
}
|
||||||
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
|
println('command to run executable: $cmd')
|
||||||
}
|
}
|
||||||
if v.pref.is_test {
|
if v.pref.is_test {
|
||||||
ret := os.system(cmd)
|
ret := os.system(cmd)
|
|
@ -0,0 +1,81 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
// This file contains the options specific to the C backend of V.
|
||||||
|
// To add a flag to all backends at once, please add the flag to `parse_options()` in `compile_options.v`.
|
||||||
|
// To add a flag to both x64 and C, please add the flag to `parse_executable_options()` in `compile_x64_options.v`.
|
||||||
|
|
||||||
|
import (
|
||||||
|
internal.flag
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn parse_c_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
||||||
|
match flag {
|
||||||
|
'cc', 'compiler' {
|
||||||
|
f.is_equivalent_to(['cc', 'compiler'])
|
||||||
|
//TODO Remove `tmp` variable when it doesn't error out in C.
|
||||||
|
tmp := f.string() or {
|
||||||
|
println('V error: Expected argument after `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
prefs.ccompiler = tmp
|
||||||
|
}
|
||||||
|
'cg', 'cdebug' {
|
||||||
|
f.is_equivalent_to(['cg', 'cdebug', 'g', 'debug'])
|
||||||
|
if f.bool() {
|
||||||
|
prefs.is_debug = true
|
||||||
|
prefs.is_vlines = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'live' {
|
||||||
|
prefs.is_live = f.bool()
|
||||||
|
}
|
||||||
|
'csource' {
|
||||||
|
operation := f.string() or {
|
||||||
|
println('V error: Expected argument after `-csource`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match operation {
|
||||||
|
'keep' {
|
||||||
|
prefs.is_keep_c = true
|
||||||
|
}
|
||||||
|
'prettify' {
|
||||||
|
prefs.is_keep_c = true
|
||||||
|
prefs.is_pretty_c = true
|
||||||
|
}
|
||||||
|
'drop' {} //Default
|
||||||
|
else {
|
||||||
|
println('V error: Unknown argument for `-csource` (`$operation`).')
|
||||||
|
println('Allowed options: `keep`, `prettify` and `drop`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'sanitize' {
|
||||||
|
prefs.sanitize = f.bool()
|
||||||
|
}
|
||||||
|
'cf', 'cflags' {
|
||||||
|
f.allow_duplicate()
|
||||||
|
cflag := f.string() or {
|
||||||
|
println('V error: Expected argument after `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
prefs.cflags += ' $cflag'
|
||||||
|
}
|
||||||
|
// TODO Deprecate these once v2 parser is live
|
||||||
|
'repl' {
|
||||||
|
prefs.is_repl = f.bool()
|
||||||
|
}
|
||||||
|
'solive' {
|
||||||
|
prefs.is_solive = f.bool()
|
||||||
|
prefs.is_so = prefs.is_solive
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parse_executable_options(flag, mut f, mut prefs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
// This file contains the options specific to the JS backend of V.
|
||||||
|
|
||||||
|
import (
|
||||||
|
internal.flag
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn parse_js_options(flag string, f flag.Instance, prefs pref.Preferences) {
|
||||||
|
// No notable flags for JS-only currently. Add them here when they are needed.
|
||||||
|
// For now, we just fail as this is meant to be a fallback.
|
||||||
|
println('V error: Unknown flag `-$flag` provided.')
|
||||||
|
println('Use `--` to terminate flag list if necessary.')
|
||||||
|
exit(1)
|
||||||
|
}
|
|
@ -0,0 +1,222 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
import (
|
||||||
|
internal.flag
|
||||||
|
os.cmdline
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
fn parse_arguments(args []string) (pref.Preferences, []string) {
|
||||||
|
mut p := pref.Preferences{
|
||||||
|
//TODO: Refactor away this preference.
|
||||||
|
// It's no longer controlled by a command-line flag.
|
||||||
|
enable_globals: true
|
||||||
|
}
|
||||||
|
mut backend := cmdline.options(args, '-b')
|
||||||
|
backend << cmdline.options(args, '-backend')
|
||||||
|
if backend.len > 1 {
|
||||||
|
println('V error: Only one backend may be enabled at once. (Multiple `-b`/`-backend` flags provided)')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if backend.len == 1 {
|
||||||
|
p.backend = pref.backend_from_string(backend[0]) or {
|
||||||
|
println('V error: Unknown backend ${backend[0]} provided.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.backend = .c
|
||||||
|
}
|
||||||
|
mut remaining := flag.parse_pref(args, parse_options, &p) or {
|
||||||
|
println('V error: Error while parsing flags.')
|
||||||
|
println(err)
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match remaining[0] {
|
||||||
|
'run' {
|
||||||
|
p.is_run = true
|
||||||
|
remaining = remaining[1..]
|
||||||
|
}
|
||||||
|
'build' {
|
||||||
|
remaining = remaining[1..]
|
||||||
|
if remaining[0] == 'module' {
|
||||||
|
remaining = remaining[1..]
|
||||||
|
//TODO Figure out module
|
||||||
|
println('V error: Module compilation is not ready yet.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
if remaining.len == 0 {
|
||||||
|
println('V error: Expected file/directory to compile.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if !p.is_run && remaining.len > 1 {
|
||||||
|
println('V error: Expected only one file/directory to compile.')
|
||||||
|
println('Did you perhaps put flags after the file/directory?')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
p.path = remaining[0]
|
||||||
|
p.fill_with_defaults()
|
||||||
|
return p, remaining
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
||||||
|
match flag {
|
||||||
|
'path' {
|
||||||
|
// -path
|
||||||
|
path_str := f.string() or {
|
||||||
|
println('V error: Expected argument for `-path`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
prefs.lookup_path = path_str.split('|')
|
||||||
|
}
|
||||||
|
'o', 'output' {
|
||||||
|
f.is_equivalent_to(['o', 'output'])
|
||||||
|
//TODO Remove `tmp` variable when it doesn't error out in C.
|
||||||
|
tmp := f.string() or {
|
||||||
|
println('V error: Expected argument for `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
prefs.out_name = tmp
|
||||||
|
}
|
||||||
|
'd', 'define' {
|
||||||
|
f.allow_duplicate()
|
||||||
|
define := f.string() or {
|
||||||
|
println('V error: Expected argument for `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
parse_define(mut prefs, define)
|
||||||
|
}
|
||||||
|
'g', 'debug' {
|
||||||
|
f.is_equivalent_to(['g', 'debug', 'cg', 'cdebug'])
|
||||||
|
if f.bool() {
|
||||||
|
prefs.is_debug = true
|
||||||
|
prefs.is_vlines = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'e', 'experiments' {
|
||||||
|
f.allow_duplicate()
|
||||||
|
to_enable := f.string() or {
|
||||||
|
println('V error: Expected argument for `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match to_enable {
|
||||||
|
'prealloc' {
|
||||||
|
prefs.prealloc = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println('V error: Unknown experiment `$to_enable`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'prod' {
|
||||||
|
prefs.is_prod = true
|
||||||
|
}
|
||||||
|
'v' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_one
|
||||||
|
}
|
||||||
|
'vv' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_two
|
||||||
|
}
|
||||||
|
'vvv' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
prefs.verbosity = .level_three
|
||||||
|
}
|
||||||
|
'verbose' {
|
||||||
|
f.is_equivalent_to(['v', 'vv', 'vvv', 'verbose'])
|
||||||
|
level := f.int() or {
|
||||||
|
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match level {
|
||||||
|
0 {} //Zero verbosity is already default.
|
||||||
|
1 {
|
||||||
|
prefs.verbosity = .level_one
|
||||||
|
}
|
||||||
|
2 {
|
||||||
|
prefs.verbosity = .level_two
|
||||||
|
}
|
||||||
|
3 {
|
||||||
|
prefs.verbosity = .level_three
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println('V error: Expected `0`, `1`, `2` or `3` as argument to `-verbose` to specify verbosity level.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'full-rebuild' {
|
||||||
|
prefs.is_cache = !f.bool()
|
||||||
|
}
|
||||||
|
'stats' {
|
||||||
|
prefs.is_stats = f.bool()
|
||||||
|
}
|
||||||
|
'obf', 'obfuscate' {
|
||||||
|
f.is_equivalent_to(['-obf', '-obfuscate'])
|
||||||
|
prefs.obfuscate = f.bool()
|
||||||
|
}
|
||||||
|
'prof', 'profile' {
|
||||||
|
f.is_equivalent_to(['-prof', '-profile'])
|
||||||
|
prefs.is_prof = f.bool()
|
||||||
|
}
|
||||||
|
'translated' {
|
||||||
|
prefs.translated = f.bool()
|
||||||
|
}
|
||||||
|
'backend' {
|
||||||
|
// Just consume it. The option is handled outside of this function
|
||||||
|
f.string() or { return }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
match prefs.backend {
|
||||||
|
.c, .experimental {
|
||||||
|
parse_c_options(flag, mut f, mut prefs)
|
||||||
|
}
|
||||||
|
.x64 {
|
||||||
|
parse_x64_options(flag, mut f, mut prefs)
|
||||||
|
}
|
||||||
|
.js {
|
||||||
|
parse_js_options(flag, f, prefs)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO: Remove when compiler allows for it.
|
||||||
|
// This enum matching IS exhaustive.
|
||||||
|
panic('unexpected backend type: $prefs.backend')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn parse_define(prefs mut pref.Preferences, define string) {
|
||||||
|
define_parts := define.split('=')
|
||||||
|
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)
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
// This file contains the options specific to the x64 backend of V and backends that generate executable files.
|
||||||
|
// To add a flag to all backends at once, please add the flag to `parse_options()` in `compile_options.v`.
|
||||||
|
// To add a flag to the C backend-only, please add the flag to `parse_c_options()` in `compile_c_options.v`.
|
||||||
|
|
||||||
|
import (
|
||||||
|
internal.flag
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn parse_x64_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
||||||
|
// No notable flags for x64-only currently. Add them here when they are needed.
|
||||||
|
if flag == 'arch' {
|
||||||
|
println('V error: The `-arch` flag is not supported on the x64 backend.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
parse_executable_options(flag, mut f, mut prefs)
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn parse_executable_options(flag string, f mut flag.Instance, prefs mut pref.Preferences) {
|
||||||
|
match flag {
|
||||||
|
'os', 'target-os' {
|
||||||
|
f.is_equivalent_to(['os', 'target-os'])
|
||||||
|
target_os := f.string() or {
|
||||||
|
println('V error: Expected argument after `-$flag`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if target_os == 'cross' {
|
||||||
|
prefs.output_cross_c = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//TODO Remove `tmp` variable when it doesn't error out in C.
|
||||||
|
tmp := pref.os_from_string(target_os) or {
|
||||||
|
println('V error: Unknown operating system target `$target_os`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
prefs.os = tmp
|
||||||
|
}
|
||||||
|
'arch' {
|
||||||
|
target_arch := f.string() or {
|
||||||
|
println('V error: Expected argument after `-arch`.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
match target_arch {
|
||||||
|
'x86' {
|
||||||
|
prefs.cflags += ' -m32'
|
||||||
|
}
|
||||||
|
'x64' {} // Default. Do nothing.
|
||||||
|
else {
|
||||||
|
println('V error: Unknown architecture type. Only x86 and x64 are supported currently.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'freestanding' {
|
||||||
|
prefs.is_bare = f.bool()
|
||||||
|
}
|
||||||
|
'shared' {
|
||||||
|
prefs.is_so = f.bool()
|
||||||
|
}
|
||||||
|
'live' {
|
||||||
|
prefs.is_solive = f.bool()
|
||||||
|
}
|
||||||
|
'manual-free' {
|
||||||
|
prefs.autofree = !f.bool()
|
||||||
|
}
|
||||||
|
'compress' {
|
||||||
|
prefs.compress = f.bool()
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No more fallback. We don't recognize this flag.
|
||||||
|
println('V error: Unknown flag `-$flag` provided.')
|
||||||
|
println('Use `--` to terminate flag list if necessary.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
// Copyright (c) 2019-2020 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 compile
|
||||||
|
|
||||||
|
import (
|
||||||
|
os.cmdline
|
||||||
|
)
|
||||||
|
|
||||||
|
struct Deprecated {
|
||||||
|
old string
|
||||||
|
new string
|
||||||
|
not_exactly bool
|
||||||
|
}
|
||||||
|
|
||||||
|
//parse_and_output_new_format parses the old format and tells the user how to use the new options.
|
||||||
|
//This function exits if it detects the old format and returns if it doesn't.
|
||||||
|
fn parse_and_output_new_format(args []string) {
|
||||||
|
mut list := []Deprecated
|
||||||
|
mut obsolete := []string
|
||||||
|
//Check `-os msvc`
|
||||||
|
os := cmdline.option(args, '-os', '')
|
||||||
|
if os == 'msvc' {
|
||||||
|
list << Deprecated {
|
||||||
|
old: '-os msvc'
|
||||||
|
new: '-cc msvc'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check simple options
|
||||||
|
//TODO Refactor them to actually just modify mutable arrays
|
||||||
|
list << add_if_found_deprecated(args, '-cache', '-full-rebuild=false')
|
||||||
|
list << add_if_found_deprecated(args, 'translated', '-translated')
|
||||||
|
list << add_if_found_deprecated(args, '-x64', '-backend x64')
|
||||||
|
list << add_if_found_deprecated(args, '-v2', '-backend experimental')
|
||||||
|
list << add_if_found_deprecated(args, '-keep_c', '-csource keep')
|
||||||
|
list << add_if_found_deprecated(args, '-pretty_c', '-csource prettify')
|
||||||
|
list << add_if_found_deprecated(args, '-show_c_cmd', '-v')
|
||||||
|
list << add_if_found_deprecated(args, '-autofree', '-manual-free=false')
|
||||||
|
list << add_if_found_deprecated(args, '-fast', '-cc tcc')
|
||||||
|
list << add_if_found_deprecated(args, '-output-cross-platform-c', '-os cross')
|
||||||
|
list << add_if_found_deprecated(args, '-m32', '-arch x86')
|
||||||
|
list << add_if_found_deprecated(args, '-bare', '-freestanding')
|
||||||
|
obsolete << add_if_found_string(args, '--enable-globals')
|
||||||
|
list << add_if_found_deprecated(args, '-prealloc', '-e prealloc')
|
||||||
|
list << add_if_found_deprecated(args, '-user_mod_path', '-path*')
|
||||||
|
list << add_if_found_deprecated(args, '-vlib-path', '-path*')
|
||||||
|
list << add_if_found_deprecated(args, '-vpath', '-path*')
|
||||||
|
//Nothing to do here
|
||||||
|
if list.len == 0 && obsolete.len == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//Output messages
|
||||||
|
println('V has encountered deprecated/obsolete options. Please edit your command.\n')
|
||||||
|
if list.len > 0 {
|
||||||
|
println('Deprecated options that have been replaced:')
|
||||||
|
for deprecation in list {
|
||||||
|
if deprecation.not_exactly {
|
||||||
|
println(' `$deprecation.old` has been superseded by `$deprecation.new` (see help for more details)')
|
||||||
|
} else {
|
||||||
|
println(' use `$deprecation.new` instead of `$deprecation.old`')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println('')
|
||||||
|
}
|
||||||
|
if obsolete.len > 0 {
|
||||||
|
println('Obsolete options that are no longer supported:')
|
||||||
|
for obsoleted in obsolete {
|
||||||
|
println(' `$obsoleted` has been removed')
|
||||||
|
}
|
||||||
|
println('')
|
||||||
|
}
|
||||||
|
println('For more details, please use the command `v help build` for a list of options.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
//=====
|
||||||
|
//HELPER FUNCTIONS
|
||||||
|
//=====
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn add_if_found_deprecated(args []string, deprecated string, alt string) []Deprecated {
|
||||||
|
if deprecated in args {
|
||||||
|
new := if alt.ends_with('*') {
|
||||||
|
Deprecated {
|
||||||
|
old: deprecated
|
||||||
|
new: alt[..alt.len-1]
|
||||||
|
not_exactly: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Deprecated {
|
||||||
|
old: deprecated
|
||||||
|
new: alt
|
||||||
|
not_exactly: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return [new]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn add_if_found_string(args []string, deprecated string) []string {
|
||||||
|
if deprecated in args {
|
||||||
|
return [deprecated]
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
|
@ -0,0 +1,123 @@
|
||||||
|
// Copyright (c) 2019-2020 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license
|
||||||
|
// that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// This module is designed to be general purpose. The only reason it currently only lives here is because there's no
|
||||||
|
// generics support and all types are defined manually.
|
||||||
|
// TODO Move to vlib once generics are implemented properly.
|
||||||
|
module flag
|
||||||
|
|
||||||
|
const (
|
||||||
|
// List as taken from `pkg.go.dev/flag`
|
||||||
|
truthy = ['1', 't', 'T', 'true', 'TRUE', 'True']
|
||||||
|
falsey = ['0', 'f', 'F', 'false', 'FALSE', 'False']
|
||||||
|
)
|
||||||
|
|
||||||
|
pub struct Instance {
|
||||||
|
args []string
|
||||||
|
mut:
|
||||||
|
current_flag string
|
||||||
|
current_pos int
|
||||||
|
equal_val string
|
||||||
|
encountered map[string]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (p mut Instance) parse_impl(args []string, value voidptr, callback void_cb) ?[]string {
|
||||||
|
for p.current_pos+1 < p.args.len {
|
||||||
|
p.current_pos++
|
||||||
|
next := p.args[p.current_pos]
|
||||||
|
if !next.starts_with('-') || next == '-' {
|
||||||
|
// End of arguments.
|
||||||
|
// Note: - by itself is not considered a flag.
|
||||||
|
return args[p.current_pos..]
|
||||||
|
}
|
||||||
|
if next == '--' {
|
||||||
|
// Terminator. End of arguments.
|
||||||
|
return args[p.current_pos+1..]
|
||||||
|
}
|
||||||
|
// Start parsing flag by determining flag name
|
||||||
|
mut flag_name := ''
|
||||||
|
if idx := next.index('=') {
|
||||||
|
p.equal_val = next[idx+1..]
|
||||||
|
flag_name = next[1..idx]
|
||||||
|
} else {
|
||||||
|
p.equal_val = ''
|
||||||
|
flag_name = next[1..]
|
||||||
|
}
|
||||||
|
if p.encountered[flag_name] {
|
||||||
|
// Duplicate flags are opt-in
|
||||||
|
// This can be prevented with p.allow_duplicate()
|
||||||
|
return error('Duplicate flag: -$flag_name')
|
||||||
|
}
|
||||||
|
p.encountered[flag_name] = true
|
||||||
|
p.current_flag = flag_name
|
||||||
|
callback(flag_name, p, value)
|
||||||
|
}
|
||||||
|
// We didn't hit any exit condition. There's no argument left so nothing.
|
||||||
|
return []string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) string() ?string {
|
||||||
|
if p.equal_val != '' {
|
||||||
|
return p.equal_val
|
||||||
|
}
|
||||||
|
p.current_pos++
|
||||||
|
if p.current_pos >= p.args.len {
|
||||||
|
return error('out of arguments')
|
||||||
|
}
|
||||||
|
return p.args[p.current_pos]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) int() ?int {
|
||||||
|
val := p.string() or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return val.int()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) f32() ?f32 {
|
||||||
|
val := p.string() or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return val.f32()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) f64() ?f64 {
|
||||||
|
val := p.string() or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return val.f64()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) i64() ?i64 {
|
||||||
|
val := p.string() or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return val.i64()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) bool() bool {
|
||||||
|
val := p.string() or {
|
||||||
|
// Could not fetch arguments? Parse it as `true`.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if val in truthy {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if val in falsey {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Unrecognized boolean type. Probably is not related to boolean.
|
||||||
|
p.current_pos--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) allow_duplicate() {
|
||||||
|
p.encountered[p.current_flag] = false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (p mut Instance) is_equivalent_to(flags []string) {
|
||||||
|
for v in flags {
|
||||||
|
p.encountered[v] = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
// Copyright (c) 2019-2020 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 flag
|
||||||
|
|
||||||
|
import (
|
||||||
|
v.pref
|
||||||
|
)
|
||||||
|
|
||||||
|
type void_cb fn(string, &Instance, voidptr)
|
||||||
|
|
||||||
|
// This file contains all instance of usage in cmd/v. Should be replaced by generics.
|
||||||
|
pub fn parse_pref(args []string, callback fn(string, &Instance, &pref.Preferences), obj &pref.Preferences) ?[]string {
|
||||||
|
mut p := Instance {
|
||||||
|
args: args
|
||||||
|
current_pos: 0
|
||||||
|
}
|
||||||
|
casted_callback := *(&void_cb(&callback))
|
||||||
|
tmp := p.parse_impl(args, voidptr(obj), casted_callback) or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return tmp
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum MainCmdAction {
|
||||||
|
unspecified
|
||||||
|
version
|
||||||
|
help
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MainCmdPreferences {
|
||||||
|
pub mut:
|
||||||
|
verbosity pref.VerboseLevel
|
||||||
|
action MainCmdAction
|
||||||
|
unknown_flag string
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_main_cmd(args []string, callback fn(string, &Instance, &MainCmdPreferences), obj &MainCmdPreferences) ?[]string {
|
||||||
|
mut p := Instance {
|
||||||
|
args: args
|
||||||
|
current_pos: 0
|
||||||
|
}
|
||||||
|
casted_callback := *(&void_cb(&callback))
|
||||||
|
tmp := p.parse_impl(args, voidptr(obj), casted_callback) or {
|
||||||
|
return error(err)
|
||||||
|
}
|
||||||
|
return tmp
|
||||||
|
}
|
|
@ -10,27 +10,23 @@ import (
|
||||||
v.pref
|
v.pref
|
||||||
)
|
)
|
||||||
|
|
||||||
fn launch_tool(is_verbose bool, tname string, cmdname string) {
|
fn launch_tool(verbosity pref.VerboseLevel, tool_name string) {
|
||||||
vexe := pref.vexe_path()
|
vexe := pref.vexe_path()
|
||||||
vroot := filepath.dir(vexe)
|
vroot := filepath.dir(vexe)
|
||||||
compiler.set_vroot_folder(vroot)
|
compiler.set_vroot_folder(vroot)
|
||||||
|
|
||||||
mut tname_index := os.args.index(cmdname)
|
|
||||||
if tname_index == -1 {
|
|
||||||
tname_index = os.args.len
|
|
||||||
}
|
|
||||||
mut compilation_options := os.args[1..tname_index].clone()
|
|
||||||
tool_args := os.args[1..].join(' ')
|
tool_args := os.args[1..].join(' ')
|
||||||
tool_exe := path_of_executable(os.realpath('$vroot/cmd/tools/$tname'))
|
tool_exe := path_of_executable(os.realpath('$vroot/cmd/tools/$tool_name'))
|
||||||
tool_source := os.realpath('$vroot/cmd/tools/${tname}.v')
|
tool_source := os.realpath('$vroot/cmd/tools/${tool_name}.v')
|
||||||
tool_command := '"$tool_exe" $tool_args'
|
tool_command := '"$tool_exe" $tool_args'
|
||||||
if is_verbose {
|
if verbosity.is_higher_or_equal(.level_two) {
|
||||||
eprintln('launch_tool vexe : $vroot')
|
eprintln('launch_tool vexe : $vroot')
|
||||||
eprintln('launch_tool vroot : $vroot')
|
eprintln('launch_tool vroot : $vroot')
|
||||||
eprintln('launch_tool tool_args : $tool_args')
|
eprintln('launch_tool tool_args : $tool_args')
|
||||||
eprintln('launch_tool tool_command: $tool_command')
|
eprintln('launch_tool tool_command: $tool_command')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Caching should be done on the `vlib/v` level.
|
||||||
mut should_compile := false
|
mut should_compile := false
|
||||||
if !os.exists(tool_exe) {
|
if !os.exists(tool_exe) {
|
||||||
should_compile = true
|
should_compile = true
|
||||||
|
@ -40,7 +36,7 @@ fn launch_tool(is_verbose bool, tname string, cmdname string) {
|
||||||
// rebuild the tool too just in case
|
// rebuild the tool too just in case
|
||||||
should_compile = true
|
should_compile = true
|
||||||
|
|
||||||
if tname == 'vself' || tname == 'vup' {
|
if tool_name == 'vself' || tool_name == 'vup' {
|
||||||
// The purpose of vself/up is to update and recompile v itself.
|
// The purpose of vself/up is to update and recompile v itself.
|
||||||
// After the first 'v self' execution, v will be modified, so
|
// After the first 'v self' execution, v will be modified, so
|
||||||
// then a second 'v self' will detect, that v is newer than the
|
// then a second 'v self' will detect, that v is newer than the
|
||||||
|
@ -54,25 +50,26 @@ fn launch_tool(is_verbose bool, tname string, cmdname string) {
|
||||||
should_compile = true
|
should_compile = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_verbose {
|
if verbosity.is_higher_or_equal(.level_two) {
|
||||||
eprintln('launch_tool should_compile: $should_compile')
|
eprintln('launch_tool should_compile: $should_compile')
|
||||||
}
|
}
|
||||||
|
|
||||||
if should_compile {
|
if should_compile {
|
||||||
if tname == 'vfmt' {
|
mut compilation_command := '"$vexe" '
|
||||||
compilation_options << ['-d', 'vfmt']
|
if tool_name == 'vfmt' {
|
||||||
|
// TODO Remove when it's no longer required by fmt
|
||||||
|
compilation_command += '-d vfmt '
|
||||||
}
|
}
|
||||||
compilation_args := compilation_options.join(' ')
|
compilation_command += '"$tool_source"'
|
||||||
compilation_command := '"$vexe" $compilation_args "$tool_source"'
|
if verbosity.is_higher_or_equal(.level_three) {
|
||||||
if is_verbose {
|
eprintln('Compiling $tool_name with: "$compilation_command"')
|
||||||
eprintln('Compiling $tname with: "$compilation_command"')
|
|
||||||
}
|
}
|
||||||
tool_compilation := os.exec(compilation_command) or { panic(err) }
|
tool_compilation := os.exec(compilation_command) or { panic(err) }
|
||||||
if tool_compilation.exit_code != 0 {
|
if tool_compilation.exit_code != 0 {
|
||||||
panic('V tool "$tool_source" could not be compiled\n' + tool_compilation.output)
|
panic('V tool "$tool_source" could not be compiled\n' + tool_compilation.output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if is_verbose {
|
if verbosity.is_higher_or_equal(.level_three) {
|
||||||
eprintln('launch_tool running tool command: $tool_command ...')
|
eprintln('launch_tool running tool command: $tool_command ...')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
149
cmd/v/v.v
149
cmd/v/v.v
|
@ -5,6 +5,8 @@ module main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
compiler
|
compiler
|
||||||
|
internal.compile
|
||||||
|
internal.flag
|
||||||
internal.help
|
internal.help
|
||||||
os
|
os
|
||||||
v.table
|
v.table
|
||||||
|
@ -23,69 +25,120 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
arg := join_flags_and_argument()
|
prefs := flag.MainCmdPreferences{}
|
||||||
command,option := get_basic_command_and_option(arg)
|
values := flag.parse_main_cmd(os.args, parse_flags, &prefs) or {
|
||||||
is_verbose := '-verbose' in arg || '--verbose' in arg
|
println('V Error: An error has occured while parsing flags: ')
|
||||||
if '-v' in option || '--version' in option || command == 'version' {
|
println(err)
|
||||||
// Print the version and exit.
|
exit(1)
|
||||||
version_hash := compiler.vhash()
|
|
||||||
println('V $compiler.Version $version_hash')
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if '-h' in option || '--help' in option || command == 'help' {
|
if prefs.verbosity.is_higher_or_equal(.level_two) {
|
||||||
if is_verbose {
|
println('V $compiler.Version $compiler.vhash()')
|
||||||
println(help.verbose_help_text)
|
}
|
||||||
|
if prefs.verbosity.is_higher_or_equal(.level_three) {
|
||||||
|
println('Parsed preferences: ')
|
||||||
|
println(prefs)
|
||||||
|
println('Remaining: $values')
|
||||||
|
}
|
||||||
|
// Do a quick check for `v -v`. Too much error has been made this way.
|
||||||
|
if prefs.verbosity == .level_one && values.len == 0 {
|
||||||
|
println("`v -v` now runs V with verbose mode set to level one which doesn't do anything.")
|
||||||
|
println('Did you mean `v -version` instead?')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
// Start calling the correct functions/external tools
|
||||||
|
// Note for future contributors: Please add new subcommands in the `match` block below.
|
||||||
|
if prefs.action == .version {
|
||||||
|
disallow_unknown_flags(prefs)
|
||||||
|
print_version_and_exit()
|
||||||
|
}
|
||||||
|
if values.len == 0 && prefs.action == .help {
|
||||||
|
println('Use `v help` for usage information.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
if values.len == 0 || values[0] == '-' || values[0] == 'repl' {
|
||||||
|
// Check for REPL.
|
||||||
|
if values.len == 0 {
|
||||||
|
println('Running REPL as no arguments are provided.')
|
||||||
|
println('For usage information, quit V REPL using `exit` and use `v help`.')
|
||||||
}
|
}
|
||||||
else {
|
launch_tool(prefs.verbosity, 'vrepl')
|
||||||
println(help.help_text)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if is_verbose {
|
|
||||||
eprintln('v args: $arg')
|
|
||||||
eprintln('v command: $command')
|
|
||||||
eprintln('v options: $option')
|
|
||||||
}
|
|
||||||
if command == 'doc' {
|
|
||||||
mod := arg[arg.len-1]
|
|
||||||
table := table.new_table()
|
|
||||||
println(doc.doc(mod, table))
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
command := values[0]
|
||||||
if command in simple_cmd {
|
if command in simple_cmd {
|
||||||
// External tools
|
// External tools
|
||||||
launch_tool(is_verbose, 'v' + command, command)
|
launch_tool(prefs.verbosity, 'v' + command)
|
||||||
return
|
|
||||||
}
|
|
||||||
if command == 'run' || command == 'build' || command.ends_with('.v') || os.exists(command) {
|
|
||||||
compile(command, arg)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
match command {
|
match command {
|
||||||
'', '-' {
|
|
||||||
if arg.len == 1 {
|
|
||||||
println('Running REPL as no arguments are provided. For usage information, use `v help`.')
|
|
||||||
}
|
|
||||||
launch_tool(is_verbose, 'vrepl', '')
|
|
||||||
}
|
|
||||||
'translate' {
|
'translate' {
|
||||||
println('Translating C to V will be available in V 0.3')
|
println('Translating C to V will be available in V 0.3')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
'search', 'install', 'update', 'remove' {
|
'search', 'install', 'update', 'remove' {
|
||||||
launch_tool(is_verbose, 'vpm', command)
|
launch_tool(prefs.verbosity, 'vpm')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
'get' {
|
'get' {
|
||||||
println('Use `v install` to install modules from vpm.vlang.io')
|
println('V Error: Use `v install` to install modules from vpm.vlang.io')
|
||||||
}
|
|
||||||
'symlink' {
|
|
||||||
create_symlink()
|
|
||||||
}
|
|
||||||
//'doc' {
|
|
||||||
//println('Currently unimplemented')
|
|
||||||
//}
|
|
||||||
else {
|
|
||||||
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
|
'symlink' {
|
||||||
|
disallow_unknown_flags(prefs)
|
||||||
|
create_symlink()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
'doc' {
|
||||||
|
disallow_unknown_flags(prefs)
|
||||||
|
if values.len == 1 {
|
||||||
|
println('V Error: Expected argument: Module name to output documentations for')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
table := table.new_table()
|
||||||
|
println(doc.doc(values[1], table))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
'help' {
|
||||||
|
// We check if the arguments are empty as we don't want to steal it from tools
|
||||||
|
// TODO Call actual help tool
|
||||||
|
disallow_unknown_flags(prefs)
|
||||||
|
if prefs.verbosity.is_higher_or_equal(.level_one) {
|
||||||
|
println(help.verbose_help_text)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
println(help.help_text)
|
||||||
|
}
|
||||||
|
if values.len > 1 {
|
||||||
|
println('Note: Actual help module is coming soon. Feel free to ask on the official channels for clarification.')
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
'version' {
|
||||||
|
disallow_unknown_flags(prefs)
|
||||||
|
print_version_and_exit()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else {}
|
||||||
}
|
}
|
||||||
|
if command == 'run' || command == 'build' || command.ends_with('.v') || os.exists(command) {
|
||||||
|
arg := join_flags_and_argument()
|
||||||
|
compile.compile(command, arg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
eprintln('v $command: unknown command\nRun "v help" for usage.')
|
||||||
|
exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_version_and_exit() {
|
||||||
|
version_hash := compiler.vhash()
|
||||||
|
println('V $compiler.Version $version_hash')
|
||||||
|
exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
fn disallow_unknown_flags(prefs flag.MainCmdPreferences) {
|
||||||
|
if prefs.unknown_flag == '' {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
println('V Error: Unexpected flag found: $prefs.unknown_flag')
|
||||||
|
exit(1)
|
||||||
}
|
}
|
||||||
|
|
6
make.bat
6
make.bat
|
@ -77,8 +77,8 @@ if %ERRORLEVEL% NEQ 0 (
|
||||||
)
|
)
|
||||||
|
|
||||||
echo rebuild from source (twice, in case of C definitions changes)
|
echo rebuild from source (twice, in case of C definitions changes)
|
||||||
v2.exe -cc msvc -o v3.exe cmd/v
|
v2.exe -o v3.exe cmd/v
|
||||||
v3.exe -cc msvc -o v -prod cmd/v
|
v3.exe -o v -prod cmd/v
|
||||||
if %ERRORLEVEL% NEQ 0 (
|
if %ERRORLEVEL% NEQ 0 (
|
||||||
echo V failed to build itself with error %ERRORLEVEL%
|
echo V failed to build itself with error %ERRORLEVEL%
|
||||||
goto :compileerror
|
goto :compileerror
|
||||||
|
@ -115,4 +115,4 @@ exit /b 1
|
||||||
|
|
||||||
:success
|
:success
|
||||||
echo V build OK!
|
echo V build OK!
|
||||||
v -v
|
v -version
|
||||||
|
|
|
@ -3186,7 +3186,7 @@ fn (p mut Parser) check_unused_imports() {
|
||||||
}
|
}
|
||||||
// the imports are usually at the start of the file
|
// the imports are usually at the start of the file
|
||||||
// p.production_error_with_token_index('the following imports were never used: $output', 0)
|
// p.production_error_with_token_index('the following imports were never used: $output', 0)
|
||||||
if p.pref.is_verbose {
|
if p.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
eprintln('Used imports table: ${p.import_table.used_imports.str()}')
|
eprintln('Used imports table: ${p.import_table.used_imports.str()}')
|
||||||
}
|
}
|
||||||
p.warn('the following imports were never used: $output')
|
p.warn('the following imports were never used: $output')
|
||||||
|
|
|
@ -17,7 +17,7 @@ fn todo() {
|
||||||
fn (v &V) no_cc_installed() bool {
|
fn (v &V) no_cc_installed() bool {
|
||||||
$if windows {
|
$if windows {
|
||||||
os.exec('$v.pref.ccompiler -v')or{
|
os.exec('$v.pref.ccompiler -v')or{
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println('C compiler not found, trying to build with msvc...')
|
println('C compiler not found, trying to build with msvc...')
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
|
@ -328,7 +328,7 @@ start:
|
||||||
// TODO remove
|
// TODO remove
|
||||||
cmd := '${v.pref.ccompiler} $args'
|
cmd := '${v.pref.ccompiler} $args'
|
||||||
// Run
|
// Run
|
||||||
if v.pref.show_c_cmd || v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println('\n==========')
|
println('\n==========')
|
||||||
println(cmd)
|
println(cmd)
|
||||||
}
|
}
|
||||||
|
@ -402,7 +402,7 @@ If you're confident that all of the above is true, please try running V with the
|
||||||
}
|
}
|
||||||
diff := time.ticks() - ticks
|
diff := time.ticks() - ticks
|
||||||
// Print the C command
|
// Print the C command
|
||||||
if v.pref.show_c_cmd || v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println('${v.pref.ccompiler} took $diff ms')
|
println('${v.pref.ccompiler} took $diff ms')
|
||||||
println('=========\n')
|
println('=========\n')
|
||||||
}
|
}
|
||||||
|
@ -513,7 +513,7 @@ fn (c mut V) cc_windows_cross() {
|
||||||
|
|
||||||
println(cmd)
|
println(cmd)
|
||||||
//cmd := 'clang -o $obj_name -w $include -m32 -c -target x86_64-win32 $v_modules_path/$c.out_name_c'
|
//cmd := 'clang -o $obj_name -w $include -m32 -c -target x86_64-win32 $v_modules_path/$c.out_name_c'
|
||||||
if c.pref.show_c_cmd {
|
if c.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println(cmd)
|
println(cmd)
|
||||||
}
|
}
|
||||||
if os.system(cmd) != 0 {
|
if os.system(cmd) != 0 {
|
||||||
|
|
|
@ -176,7 +176,7 @@ fn (p mut Parser) print_error_context() {
|
||||||
// os.write_to_file('/var/tmp/lang.types', '')//pes(p.table.types))
|
// os.write_to_file('/var/tmp/lang.types', '')//pes(p.table.types))
|
||||||
os.write_file('fns.txt', p.table.debug_fns())
|
os.write_file('fns.txt', p.table.debug_fns())
|
||||||
}
|
}
|
||||||
if p.pref.is_verbose || p.pref.is_debug {
|
if p.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('pass=$p.pass fn=`$p.cur_fn.name`\n')
|
println('pass=$p.pass fn=`$p.cur_fn.name`\n')
|
||||||
}
|
}
|
||||||
p.cgen.save()
|
p.cgen.save()
|
||||||
|
|
|
@ -209,7 +209,7 @@ fn (p mut Parser) comp_time() {
|
||||||
p.check(.lpar)
|
p.check(.lpar)
|
||||||
p.check(.rpar)
|
p.check(.rpar)
|
||||||
v_code := tmpl.compile_template(path)
|
v_code := tmpl.compile_template(path)
|
||||||
if p.pref.is_verbose {
|
if p.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('\n\n')
|
println('\n\n')
|
||||||
println('>>> vweb template for ${path}:')
|
println('>>> vweb template for ${path}:')
|
||||||
println(v_code)
|
println(v_code)
|
||||||
|
|
|
@ -951,7 +951,7 @@ fn (p mut Parser) factor() string {
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if p.pref.is_verbose || p.pref.is_debug {
|
if p.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
next := p.peek()
|
next := p.peek()
|
||||||
println('prev=${p.prev_tok.str()}')
|
println('prev=${p.prev_tok.str()}')
|
||||||
println('next=${next.str()}')
|
println('next=${next.str()}')
|
||||||
|
|
|
@ -431,7 +431,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
str_args := f.str_args(p.table)
|
str_args := f.str_args(p.table)
|
||||||
// Special case for main() args
|
// Special case for main() args
|
||||||
if f.name == 'main__main' && !has_receiver {
|
if f.name == 'main__main' && !has_receiver {
|
||||||
if p.pref.x64 && !p.first_pass() {
|
if p.pref.backend == .x64 && !p.first_pass() {
|
||||||
//p.x64.save_main_fn_addr()
|
//p.x64.save_main_fn_addr()
|
||||||
}
|
}
|
||||||
if str_args != '' || typ != 'void' {
|
if str_args != '' || typ != 'void' {
|
||||||
|
@ -581,7 +581,7 @@ fn (p mut Parser) fn_decl() {
|
||||||
f.defer_text[f.scope_level] = ' ${cgen_name}_time += time__ticks() - _PROF_START;'
|
f.defer_text[f.scope_level] = ' ${cgen_name}_time += time__ticks() - _PROF_START;'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if p.pref.x64 {
|
if p.pref.backend == .x64 {
|
||||||
//p.x64.register_function_address(f.name)
|
//p.x64.register_function_address(f.name)
|
||||||
}
|
}
|
||||||
p.statements_no_rcbr()
|
p.statements_no_rcbr()
|
||||||
|
@ -597,10 +597,10 @@ fn (p mut Parser) fn_decl() {
|
||||||
if typ != 'void' && !p.returns {
|
if typ != 'void' && !p.returns {
|
||||||
p.error_with_token_index('$f.name must return "$typ"', f.fn_name_token_idx)
|
p.error_with_token_index('$f.name must return "$typ"', f.fn_name_token_idx)
|
||||||
}
|
}
|
||||||
if p.pref.x64 && f.name == 'main__main' && !p.first_pass() {
|
if p.pref.backend == .x64 && f.name == 'main__main' && !p.first_pass() {
|
||||||
//p.x64.gen_exit()
|
//p.x64.gen_exit()
|
||||||
}
|
}
|
||||||
if p.pref.x64 && !p.first_pass() {
|
if p.pref.backend == .x64 && !p.first_pass() {
|
||||||
//p.x64.ret()
|
//p.x64.ret()
|
||||||
}
|
}
|
||||||
// {} closed correctly? scope_level should be 0
|
// {} closed correctly? scope_level should be 0
|
||||||
|
@ -778,7 +778,7 @@ fn (p mut Parser) fn_call(f mut Fn, method_ph int, receiver_var, receiver_type s
|
||||||
if is_comptime_define {
|
if is_comptime_define {
|
||||||
p.cgen.nogen = true
|
p.cgen.nogen = true
|
||||||
}
|
}
|
||||||
if p.pref.x64 && !p.first_pass() {
|
if p.pref.backend == .x64 && !p.first_pass() {
|
||||||
//p.x64.call_fn(f.name)
|
//p.x64.call_fn(f.name)
|
||||||
}
|
}
|
||||||
p.calling_c = f.is_c
|
p.calling_c = f.is_c
|
||||||
|
@ -1104,7 +1104,7 @@ fn (p mut Parser) fn_call_args(f mut Fn, generic_param_types []string) {
|
||||||
p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(')
|
p.gen('/*YY f=$f.name arg=$arg.name is_moved=$arg.is_moved*/string_clone(')
|
||||||
}
|
}
|
||||||
// x64 println gen
|
// x64 println gen
|
||||||
if p.pref.x64 && i == 0 && f.name == 'println' && p.tok == .str && p.peek() == .rpar {
|
if p.pref.backend == .x64 && i == 0 && f.name == 'println' && p.tok == .str && p.peek() == .rpar {
|
||||||
//p.x64.gen_print(p.lit)
|
//p.x64.gen_print(p.lit)
|
||||||
}
|
}
|
||||||
mut typ := p.bool_expression()
|
mut typ := p.bool_expression()
|
||||||
|
|
|
@ -143,13 +143,13 @@ fn (p mut Parser) for_st() {
|
||||||
if is_range {
|
if is_range {
|
||||||
p.check_types(typ, 'int')
|
p.check_types(typ, 'int')
|
||||||
p.check_space(.dotdot)
|
p.check_space(.dotdot)
|
||||||
if p.pref.x64 {
|
if p.pref.backend == .x64 {
|
||||||
to = p.lit.int()
|
to = p.lit.int()
|
||||||
}
|
}
|
||||||
range_typ,range_expr := p.tmp_expr()
|
range_typ,range_expr := p.tmp_expr()
|
||||||
p.check_types(range_typ, 'int')
|
p.check_types(range_typ, 'int')
|
||||||
range_end = range_expr
|
range_end = range_expr
|
||||||
if p.pref.x64 {
|
if p.pref.backend == .x64 {
|
||||||
//label = p.x64.gen_loop_start(expr.int())
|
//label = p.x64.gen_loop_start(expr.int())
|
||||||
// to = range_expr.int() // TODO why empty?
|
// to = range_expr.int() // TODO why empty?
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,12 +95,12 @@ fn (v &V) generate_hot_reload_code() {
|
||||||
}
|
}
|
||||||
so_debug_flag := if v.pref.is_debug { '-g' } else { '' }
|
so_debug_flag := if v.pref.is_debug { '-g' } else { '' }
|
||||||
cmd_compile_shared_library := '$vexe $msvc $so_debug_flag -o $file_base -solive -shared $file'
|
cmd_compile_shared_library := '$vexe $msvc $so_debug_flag -o $file_base -solive -shared $file'
|
||||||
if v.pref.show_c_cmd {
|
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println(cmd_compile_shared_library)
|
println(cmd_compile_shared_library)
|
||||||
}
|
}
|
||||||
ticks := time.ticks()
|
ticks := time.ticks()
|
||||||
os.system(cmd_compile_shared_library)
|
os.system(cmd_compile_shared_library)
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
diff := time.ticks() - ticks
|
diff := time.ticks() - ticks
|
||||||
println('compiling shared library took $diff ms')
|
println('compiling shared library took $diff ms')
|
||||||
println('=========\n')
|
println('=========\n')
|
||||||
|
|
|
@ -142,12 +142,12 @@ pub fn (v mut V) compile() {
|
||||||
}
|
}
|
||||||
mut cgen := v.cgen
|
mut cgen := v.cgen
|
||||||
cgen.genln('// Generated by V')
|
cgen.genln('// Generated by V')
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('all .v files before:')
|
println('all .v files before:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
v.add_v_files_to_compile()
|
v.add_v_files_to_compile()
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('all .v files:')
|
println('all .v files:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
|
@ -303,7 +303,7 @@ pub fn (v mut V) compile() {
|
||||||
v.generate_init()
|
v.generate_init()
|
||||||
v.generate_main()
|
v.generate_main()
|
||||||
v.generate_hot_reload_code()
|
v.generate_hot_reload_code()
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
v.log('flags=')
|
v.log('flags=')
|
||||||
for flag in v.get_os_cflags() {
|
for flag in v.get_os_cflags() {
|
||||||
println(' * ' + flag.format())
|
println(' * ' + flag.format())
|
||||||
|
@ -324,7 +324,7 @@ pub fn (v mut V) compile2() {
|
||||||
}
|
}
|
||||||
//cgen.genln('// Generated by V')
|
//cgen.genln('// Generated by V')
|
||||||
println('compile2()')
|
println('compile2()')
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('all .v files before:')
|
println('all .v files before:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
|
@ -335,7 +335,7 @@ pub fn (v mut V) compile2() {
|
||||||
v.files << v.get_builtin_files()
|
v.files << v.get_builtin_files()
|
||||||
v.files << v.get_user_files()
|
v.files << v.get_user_files()
|
||||||
v.set_module_lookup_paths()
|
v.set_module_lookup_paths()
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('all .v files:')
|
println('all .v files:')
|
||||||
println(v.files)
|
println(v.files)
|
||||||
}
|
}
|
||||||
|
@ -583,7 +583,7 @@ pub fn (v &V) v_files_from_dir(dir string) []string {
|
||||||
mut files := os.ls(dir)or{
|
mut files := os.ls(dir)or{
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println('v_files_from_dir ("$dir")')
|
println('v_files_from_dir ("$dir")')
|
||||||
}
|
}
|
||||||
files.sort()
|
files.sort()
|
||||||
|
@ -645,7 +645,7 @@ pub fn (v mut V) add_v_files_to_compile() {
|
||||||
builtin_files = [builtin_vh]
|
builtin_files = [builtin_vh]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
v.log('v.add_v_files_to_compile > builtin_files: $builtin_files')
|
v.log('v.add_v_files_to_compile > builtin_files: $builtin_files')
|
||||||
}
|
}
|
||||||
// Parse builtin imports
|
// Parse builtin imports
|
||||||
|
@ -674,7 +674,7 @@ pub fn (v mut V) add_v_files_to_compile() {
|
||||||
}
|
}
|
||||||
// Parse lib imports
|
// Parse lib imports
|
||||||
v.parse_lib_imports()
|
v.parse_lib_imports()
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
v.log('imports:')
|
v.log('imports:')
|
||||||
println(v.table.imports)
|
println(v.table.imports)
|
||||||
}
|
}
|
||||||
|
@ -687,6 +687,8 @@ pub fn (v mut V) add_v_files_to_compile() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// use cached built module if exists
|
// use cached built module if exists
|
||||||
|
// Cached modules are broken currently
|
||||||
|
/*
|
||||||
if v.pref.vpath != '' && v.pref.build_mode != .build_module && !mod.contains('vweb') {
|
if v.pref.vpath != '' && v.pref.build_mode != .build_module && !mod.contains('vweb') {
|
||||||
mod_path := mod.replace('.', filepath.separator)
|
mod_path := mod.replace('.', filepath.separator)
|
||||||
vh_path := '$v_modules_path${filepath.separator}vlib${filepath.separator}${mod_path}.vh'
|
vh_path := '$v_modules_path${filepath.separator}vlib${filepath.separator}${mod_path}.vh'
|
||||||
|
@ -697,6 +699,7 @@ pub fn (v mut V) add_v_files_to_compile() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
// standard module
|
// standard module
|
||||||
vfiles := v.get_imported_module_files(mod)
|
vfiles := v.get_imported_module_files(mod)
|
||||||
for file in vfiles {
|
for file in vfiles {
|
||||||
|
@ -716,14 +719,24 @@ pub fn (v mut V) add_v_files_to_compile() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (v &V) get_builtin_files() []string {
|
pub fn (v &V) get_builtin_files() []string {
|
||||||
// .vh cache exists? Use it
|
// Lookup for built-in folder in lookup path.
|
||||||
if v.pref.is_bare {
|
// Assumption: `builtin/` folder implies usable implementation of builtin
|
||||||
return v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','bare'))
|
for location in v.pref.lookup_path {
|
||||||
|
if !os.exists(filepath.join(location, 'builtin')) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.pref.is_bare {
|
||||||
|
return v.v_files_from_dir(filepath.join(location, 'builtin', 'bare'))
|
||||||
|
}
|
||||||
|
$if js {
|
||||||
|
return v.v_files_from_dir(filepath.join(location, 'builtin','js'))
|
||||||
|
}
|
||||||
|
return v.v_files_from_dir(filepath.join(location, 'builtin'))
|
||||||
}
|
}
|
||||||
$if js {
|
// Panic. We couldn't find the folder.
|
||||||
return v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin','js'))
|
verror('`builtin/` not included on module lookup path.
|
||||||
}
|
Did you forget to add vlib to the path? (Use @vlib for default vlib)')
|
||||||
return v.v_files_from_dir(filepath.join(v.pref.vlib_path,'builtin'))
|
panic('Unreachable code reached.')
|
||||||
}
|
}
|
||||||
|
|
||||||
// get user files
|
// get user files
|
||||||
|
@ -763,7 +776,7 @@ pub fn (v &V) get_user_files() []string {
|
||||||
if is_internal_module_test {
|
if is_internal_module_test {
|
||||||
// v volt/slack_test.v: compile all .v files to get the environment
|
// v volt/slack_test.v: compile all .v files to get the environment
|
||||||
single_test_v_file := os.realpath(dir)
|
single_test_v_file := os.realpath(dir)
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
v.log('> Compiling an internal module _test.v file $single_test_v_file .')
|
v.log('> Compiling an internal module _test.v file $single_test_v_file .')
|
||||||
v.log('> That brings in all other ordinary .v files in the same module too .')
|
v.log('> That brings in all other ordinary .v files in the same module too .')
|
||||||
}
|
}
|
||||||
|
@ -774,12 +787,12 @@ pub fn (v &V) get_user_files() []string {
|
||||||
single_v_file := dir
|
single_v_file := dir
|
||||||
// Just compile one file and get parent dir
|
// Just compile one file and get parent dir
|
||||||
user_files << single_v_file
|
user_files << single_v_file
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
v.log('> just compile one file: "${single_v_file}"')
|
v.log('> just compile one file: "${single_v_file}"')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
v.log('> add all .v files from directory "${dir}" ...')
|
v.log('> add all .v files from directory "${dir}" ...')
|
||||||
}
|
}
|
||||||
// Add .v files from the directory being compiled
|
// Add .v files from the directory being compiled
|
||||||
|
@ -792,7 +805,7 @@ pub fn (v &V) get_user_files() []string {
|
||||||
println('No input .v files')
|
println('No input .v files')
|
||||||
exit(1)
|
exit(1)
|
||||||
}
|
}
|
||||||
if v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
v.log('user_files: $user_files')
|
v.log('user_files: $user_files')
|
||||||
}
|
}
|
||||||
return user_files
|
return user_files
|
||||||
|
@ -840,7 +853,7 @@ pub fn (v mut V) parse_lib_imports() {
|
||||||
|
|
||||||
|
|
||||||
pub fn (v &V) log(s string) {
|
pub fn (v &V) log(s string) {
|
||||||
if !v.pref.is_verbose {
|
if !v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
println(s)
|
println(s)
|
||||||
|
|
|
@ -154,7 +154,6 @@ fn (v &V) module_path(mod string) string {
|
||||||
// 'installed_mod' => '~/.vmodules/installed_mod'
|
// 'installed_mod' => '~/.vmodules/installed_mod'
|
||||||
// 'local_mod' => '/path/to/current/dir/local_mod'
|
// 'local_mod' => '/path/to/current/dir/local_mod'
|
||||||
fn (v mut V) set_module_lookup_paths() {
|
fn (v mut V) set_module_lookup_paths() {
|
||||||
mlookup_path := if v.pref.vpath.len > 0 { v.pref.vpath } else { v_modules_path }
|
|
||||||
// Module search order:
|
// Module search order:
|
||||||
// 0) V test files are very commonly located right inside the folder of the
|
// 0) V test files are very commonly located right inside the folder of the
|
||||||
// module, which they test. Adding the parent folder of the module folder
|
// module, which they test. Adding the parent folder of the module folder
|
||||||
|
@ -163,21 +162,18 @@ fn (v mut V) set_module_lookup_paths() {
|
||||||
// 1) search in the *same* directory, as the compiled final v program source
|
// 1) search in the *same* directory, as the compiled final v program source
|
||||||
// (i.e. the . in `v .` or file.v in `v file.v`)
|
// (i.e. the . in `v .` or file.v in `v file.v`)
|
||||||
// 2) search in the modules/ in the same directory.
|
// 2) search in the modules/ in the same directory.
|
||||||
// 3) search in vlib/
|
// 3) search in the provided paths
|
||||||
// 4.1) search in -vpath (if given)
|
// By default, these are what (3) contains:
|
||||||
// 4.2) search in ~/.vmodules/ (i.e. modules installed with vpm) (no -vpath)
|
// 3.1) search in vlib/
|
||||||
|
// 3.2) search in ~/.vmodules/ (i.e. modules installed with vpm)
|
||||||
v.module_lookup_paths = []
|
v.module_lookup_paths = []
|
||||||
if v.pref.is_test {
|
if v.pref.is_test {
|
||||||
v.module_lookup_paths << filepath.basedir(v.compiled_dir) // pdir of _test.v
|
v.module_lookup_paths << filepath.basedir(v.compiled_dir) // pdir of _test.v
|
||||||
}
|
}
|
||||||
v.module_lookup_paths << v.compiled_dir
|
v.module_lookup_paths << v.compiled_dir
|
||||||
v.module_lookup_paths << filepath.join(v.compiled_dir,'modules')
|
v.module_lookup_paths << filepath.join(v.compiled_dir,'modules')
|
||||||
v.module_lookup_paths << v.pref.vlib_path
|
v.module_lookup_paths << v.pref.lookup_path
|
||||||
v.module_lookup_paths << mlookup_path
|
if v.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
if v.pref.user_mod_path.len > 0 {
|
|
||||||
v.module_lookup_paths << v.pref.user_mod_path
|
|
||||||
}
|
|
||||||
if v.pref.is_verbose {
|
|
||||||
v.log('v.module_lookup_paths: $v.module_lookup_paths')
|
v.log('v.module_lookup_paths: $v.module_lookup_paths')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -195,11 +191,11 @@ fn (p mut Parser) find_module_path(mod string) ?string {
|
||||||
mod_path := p.v.module_path(mod)
|
mod_path := p.v.module_path(mod)
|
||||||
for lookup_path in module_lookup_paths {
|
for lookup_path in module_lookup_paths {
|
||||||
try_path := filepath.join(lookup_path,mod_path)
|
try_path := filepath.join(lookup_path,mod_path)
|
||||||
if p.v.pref.is_verbose {
|
if p.v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println(' >> trying to find $mod in $try_path ...')
|
println(' >> trying to find $mod in $try_path ...')
|
||||||
}
|
}
|
||||||
if os.is_dir(try_path) {
|
if os.is_dir(try_path) {
|
||||||
if p.v.pref.is_verbose {
|
if p.v.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println(' << found $try_path .')
|
println(' << found $try_path .')
|
||||||
}
|
}
|
||||||
return try_path
|
return try_path
|
||||||
|
|
|
@ -280,7 +280,7 @@ pub fn (v mut V) cc_msvc() {
|
||||||
cmd := '"$r.full_cl_exe_path" $args'
|
cmd := '"$r.full_cl_exe_path" $args'
|
||||||
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
// It is hard to see it at first, but the quotes above ARE balanced :-| ...
|
||||||
// Also the double quotes at the start ARE needed.
|
// Also the double quotes at the start ARE needed.
|
||||||
if v.pref.show_c_cmd || v.pref.is_verbose {
|
if v.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println('\n========== cl cmd line:')
|
println('\n========== cl cmd line:')
|
||||||
println(cmd)
|
println(cmd)
|
||||||
println('==========\n')
|
println('==========\n')
|
||||||
|
|
|
@ -10,7 +10,7 @@ fn test_the_v_compiler_can_be_invoked() {
|
||||||
vexec := runner.full_path_to_v(5)
|
vexec := runner.full_path_to_v(5)
|
||||||
println('vexecutable: $vexec')
|
println('vexecutable: $vexec')
|
||||||
assert vexec != ''
|
assert vexec != ''
|
||||||
vcmd := '"$vexec" --version'
|
vcmd := '"$vexec" -version'
|
||||||
r := os.exec(vcmd) or {
|
r := os.exec(vcmd) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ fn test_the_v_compiler_can_be_invoked() {
|
||||||
}
|
}
|
||||||
// println('"$vcmd_error" exit_code: $r_error.exit_code | output: $r_error.output')
|
// println('"$vcmd_error" exit_code: $r_error.exit_code | output: $r_error.output')
|
||||||
assert r_error.exit_code == 1
|
assert r_error.exit_code == 1
|
||||||
assert r_error.output == '`nonexisting.v` does not exist'
|
assert r_error.output == "V error: nonexisting.v doesn't exist"
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Session {
|
struct Session {
|
||||||
|
|
|
@ -138,7 +138,7 @@ pub fn (b &Builder) v_files_from_dir(dir string) []string {
|
||||||
mut files := os.ls(dir) or {
|
mut files := os.ls(dir) or {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
if b.pref.is_verbose {
|
if b.pref.verbosity.is_higher_or_equal(.level_one) {
|
||||||
println('v_files_from_dir ("$dir")')
|
println('v_files_from_dir ("$dir")')
|
||||||
}
|
}
|
||||||
files.sort()
|
files.sort()
|
||||||
|
@ -193,7 +193,7 @@ fn verror(err string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (b &Builder) log(s string) {
|
pub fn (b &Builder) log(s string) {
|
||||||
if b.pref.is_verbose {
|
if b.pref.verbosity.is_higher_or_equal(.level_two) {
|
||||||
println(s)
|
println(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,11 +208,11 @@ pub fn (b &Builder) find_module_path(mod string) ?string {
|
||||||
mod_path := module_path(mod)
|
mod_path := module_path(mod)
|
||||||
for search_path in b.module_search_paths {
|
for search_path in b.module_search_paths {
|
||||||
try_path := filepath.join(search_path,mod_path)
|
try_path := filepath.join(search_path,mod_path)
|
||||||
if b.pref.is_verbose {
|
if b.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println(' >> trying to find $mod in $try_path ..')
|
println(' >> trying to find $mod in $try_path ..')
|
||||||
}
|
}
|
||||||
if os.is_dir(try_path) {
|
if os.is_dir(try_path) {
|
||||||
if b.pref.is_verbose {
|
if b.pref.verbosity.is_higher_or_equal(.level_three) {
|
||||||
println(' << found $try_path .')
|
println(' << found $try_path .')
|
||||||
}
|
}
|
||||||
return try_path
|
return try_path
|
||||||
|
|
|
@ -17,14 +17,15 @@ pub fn (p mut Preferences) fill_with_defaults() {
|
||||||
// Location of all vlib files
|
// Location of all vlib files
|
||||||
p.vroot = filepath.dir(vexe_path())
|
p.vroot = filepath.dir(vexe_path())
|
||||||
}
|
}
|
||||||
if p.vlib_path == '' {
|
vlib_path := filepath.join(p.vroot, 'vlib')
|
||||||
p.vlib_path = filepath.join(p.vroot,'vlib')
|
if p.lookup_path.len == 0 {
|
||||||
|
p.lookup_path = ['@vlib', '@vmodules']
|
||||||
}
|
}
|
||||||
if p.vpath == '' {
|
for i, path in p.lookup_path {
|
||||||
p.vpath = default_module_path
|
p.lookup_path[i] = path.replace('@vlib', vlib_path).replace('@vmodules', default_module_path)
|
||||||
}
|
}
|
||||||
|
rpath := os.realpath(p.path)
|
||||||
if p.out_name == ''{
|
if p.out_name == ''{
|
||||||
rpath := os.realpath(p.path)
|
|
||||||
filename := filepath.filename(rpath).trim_space()
|
filename := filepath.filename(rpath).trim_space()
|
||||||
mut base := filename.all_before_last('.')
|
mut base := filename.all_before_last('.')
|
||||||
if base == '' {
|
if base == '' {
|
||||||
|
@ -43,6 +44,8 @@ pub fn (p mut Preferences) fill_with_defaults() {
|
||||||
p.out_name = 'v2'
|
p.out_name = 'v2'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rpath_name := filepath.filename(rpath)
|
||||||
|
p.building_v = !p.is_repl && (rpath_name == 'v' || rpath_name == 'vfmt.v')
|
||||||
if p.os == ._auto {
|
if p.os == ._auto {
|
||||||
// No OS specifed? Use current system
|
// No OS specifed? Use current system
|
||||||
p.os = get_host_os()
|
p.os = get_host_os()
|
||||||
|
@ -52,6 +55,14 @@ pub fn (p mut Preferences) fill_with_defaults() {
|
||||||
}
|
}
|
||||||
p.is_test = p.path.ends_with('_test.v')
|
p.is_test = p.path.ends_with('_test.v')
|
||||||
p.is_script = p.path.ends_with('.v') || p.path.ends_with('.vsh')
|
p.is_script = p.path.ends_with('.v') || p.path.ends_with('.vsh')
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_c_compiler() string {
|
fn default_c_compiler() string {
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub enum OS {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper function to convert string names to OS enum
|
// Helper function to convert string names to OS enum
|
||||||
pub fn os_from_string(os_str string) OS {
|
pub fn os_from_string(os_str string) ?OS {
|
||||||
match os_str {
|
match os_str {
|
||||||
'linux' {
|
'linux' {
|
||||||
return .linux
|
return .linux
|
||||||
|
@ -64,7 +64,7 @@ pub fn os_from_string(os_str string) OS {
|
||||||
return ._auto
|
return ._auto
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
panic('bad os $os_str')
|
return error('bad OS $os_str')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,26 @@ pub enum BuildMode {
|
||||||
build_module
|
build_module
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub enum Backend {
|
||||||
|
c // The (default) C backend
|
||||||
|
experimental // The experimental v2 backend
|
||||||
|
js // The JavaScript backend
|
||||||
|
x64 // The x64 backend
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum VerboseLevel {
|
||||||
|
clean // `-verbose 0` or unspecified
|
||||||
|
level_one // `-v` or `-verbose 1`
|
||||||
|
level_two // `-vv` or `-verbose 2`
|
||||||
|
level_three // `-vvv` or `-verbose 3`
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Preferences {
|
pub struct Preferences {
|
||||||
pub mut:
|
pub mut:
|
||||||
os OS // the OS to compile for
|
os OS // the OS to compile for
|
||||||
|
backend Backend
|
||||||
build_mode BuildMode
|
build_mode BuildMode
|
||||||
|
verbosity VerboseLevel
|
||||||
// nofmt bool // disable vfmt
|
// nofmt bool // disable vfmt
|
||||||
is_test bool // `v test string_test.v`
|
is_test bool // `v test string_test.v`
|
||||||
is_script bool // single file mode (`v program.v`), main function can be skipped
|
is_script bool // single file mode (`v program.v`), main function can be skipped
|
||||||
|
@ -25,11 +41,9 @@ pub mut:
|
||||||
is_prof bool // benchmark every function
|
is_prof bool // benchmark every function
|
||||||
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
|
translated bool // `v translate doom.v` are we running V code translated from C? allow globals, ++ expressions, etc
|
||||||
is_prod bool // use "-O2"
|
is_prod bool // use "-O2"
|
||||||
is_verbose bool // print extra information with `v.log()`
|
|
||||||
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
obfuscate bool // `v -obf program.v`, renames functions to "f_XXX"
|
||||||
is_repl bool
|
is_repl bool
|
||||||
is_run bool
|
is_run bool
|
||||||
show_c_cmd bool // `v -show_c_cmd` prints the C command to build program.v.c
|
|
||||||
sanitize bool // use Clang's new "-fsanitize" option
|
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.
|
is_debug bool // false by default, turned on by -g or -cg, it tells v to pass -g to the C backend compiler.
|
||||||
is_vlines bool // turned on by -g, false by default (it slows down .tmp.c generation slightly).
|
is_vlines bool // turned on by -g, false by default (it slows down .tmp.c generation slightly).
|
||||||
|
@ -40,6 +54,7 @@ pub mut:
|
||||||
is_cache bool // turns on v usage of the module cache to speed up compilation.
|
is_cache bool // turns on v usage of the module cache to speed up compilation.
|
||||||
is_stats bool // `v -stats file_test.v` will produce more detailed statistics for the tests that were run
|
is_stats bool // `v -stats file_test.v` will produce more detailed statistics for the tests that were run
|
||||||
no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers)
|
no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers)
|
||||||
|
// TODO Convert this into a []string
|
||||||
cflags string // Additional options which will be passed to the C compiler.
|
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.
|
// 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 could pass several -cflags XXX arguments. They will be merged with each other.
|
||||||
|
@ -58,13 +73,9 @@ pub mut:
|
||||||
enable_globals bool // allow __global for low level code
|
enable_globals bool // allow __global for low level code
|
||||||
// is_fmt bool
|
// is_fmt bool
|
||||||
is_bare bool
|
is_bare bool
|
||||||
user_mod_path string // `v -user_mod_path /Users/user/modules` adds a new lookup path for imported modules
|
lookup_path []string
|
||||||
vlib_path string
|
|
||||||
vpath string
|
|
||||||
x64 bool
|
|
||||||
output_cross_c bool
|
output_cross_c bool
|
||||||
prealloc bool
|
prealloc bool
|
||||||
v2 bool
|
|
||||||
vroot string
|
vroot string
|
||||||
out_name string
|
out_name string
|
||||||
path string // Path to file/folder to compile
|
path string // Path to file/folder to compile
|
||||||
|
@ -75,3 +86,29 @@ pub mut:
|
||||||
|
|
||||||
mod string
|
mod string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn backend_from_string(s string) ?Backend {
|
||||||
|
match s {
|
||||||
|
'c' {
|
||||||
|
return .c
|
||||||
|
}
|
||||||
|
'js' {
|
||||||
|
return .js
|
||||||
|
}
|
||||||
|
'experimental', 'v2' {
|
||||||
|
//TODO Remove in the future once it's considered stable :)
|
||||||
|
return .experimental
|
||||||
|
}
|
||||||
|
'x64' {
|
||||||
|
return .x64
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return error('Unknown backend type $s')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[inline]
|
||||||
|
pub fn (v VerboseLevel) is_higher_or_equal(other VerboseLevel) bool {
|
||||||
|
return int(v) >= int(other)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue