From 065ce39577bd0c5aa04b433173cb420c40e3095a Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 12 Oct 2019 13:54:01 +0300 Subject: [PATCH] compiler: -g and -debug should always add -g at least in the C compiler by default * compiler: -g and -debug should always add -g at least in the C compiler by default. * Set first the C backend debug_options, so that the optimization_options can override them later. * Implement cleaner named is_debug, is_vlines, is_keep_c and is_cache options (i.e. -g/-cg, -keep_c, -cache v flags). * Check and reset file/line numbers in the generated main program, only if v.pref.is_vlines is true. --- compiler/cc.v | 25 +++++++++++++------------ compiler/fn.v | 2 +- compiler/live.v | 9 ++------- compiler/main.v | 40 ++++++++++++++++++++++++++-------------- compiler/msvc.v | 4 ++-- compiler/parser.v | 2 +- compiler/vhelp.v | 23 ++++++++++++++++------- 7 files changed, 61 insertions(+), 44 deletions(-) diff --git a/compiler/cc.v b/compiler/cc.v index 21f4a1e301..b2f7935736 100644 --- a/compiler/cc.v +++ b/compiler/cc.v @@ -77,29 +77,30 @@ fn (v mut V) cc() { println('Building ${v.out_name}...') } - mut debug_options := '' + debug_mode := v.pref.is_debug + mut debug_options := '-g' mut optimization_options := '-O2' if v.pref.ccompiler.contains('clang') { - if v.pref.is_debuggable { + if debug_mode { debug_options = '-g -O0' } optimization_options = '-O3 -flto' } if v.pref.ccompiler.contains('gcc') { - if v.pref.is_debug { + if debug_mode { debug_options = '-g3' } optimization_options = '-O3 -fno-strict-aliasing -flto' } - + + if debug_mode { + a << debug_options + } if v.pref.is_prod { a << optimization_options } - else { - a << debug_options - } - - if v.pref.is_debuggable && os.user_os() != 'windows'{ + + if debug_mode && os.user_os() != 'windows'{ a << ' -rdynamic ' // needed for nicer symbolic backtraces } @@ -115,7 +116,7 @@ fn (v mut V) cc() { if v.pref.build_mode == .build_module { a << '-c' } - else if v.pref.is_debug { + else if v.pref.is_cache { vexe := os.executable() builtin_o_path := '$v_modules_path${os.PathSeparator}cache${os.PathSeparator}vlib${os.PathSeparator}builtin.o' if os.file_exists(builtin_o_path) { @@ -225,7 +226,7 @@ fn (v mut V) cc() { partial_output := res.output.limit(200).trim_right('\r\n') print(partial_output) if res.output.len > partial_output.len { - println('...\n(Use `v -debug` to print the entire error message)\n') + println('...\n(Use `v -g` to print the entire error message)\n') }else{ println('') } @@ -261,7 +262,7 @@ fn (v mut V) cc() { println('linux cross compilation done. resulting binary: "$v.out_name"') } */ - if !v.pref.is_debug && v.out_name_c != 'v.c' { + if !v.pref.is_keep_c && v.out_name_c != 'v.c' { os.rm(v.out_name_c) } if v.pref.compress { diff --git a/compiler/fn.v b/compiler/fn.v index 1c535146b3..dbad25c7c5 100644 --- a/compiler/fn.v +++ b/compiler/fn.v @@ -807,7 +807,7 @@ fn (p mut Parser) fn_call_args(f mut Fn) &Fn { p.check(.rpar) return f } - // add debug information to panic when -debug arg is passed + // add debug information to panic when -g arg is passed if p.v.pref.is_debug && f.name == 'panic' && !p.is_js { mod_name := p.mod.replace('_dot_', '.') fn_name := p.cur_fn.name.replace('${p.mod}__', '') diff --git a/compiler/live.v b/compiler/live.v index 95abeb1413..fcb6339829 100644 --- a/compiler/live.v +++ b/compiler/live.v @@ -82,13 +82,8 @@ fn (v &V) generate_hot_reload_code() { msvc = '-os msvc' } - mut debug := '' - - if v.pref.is_debug { - debug = '-debug' - } - - cmd_compile_shared_library := '$vexe $msvc $debug -o $file_base -shared $file' + so_debug_flag := if v.pref.is_debug { '-g' } else { '' } + cmd_compile_shared_library := '$vexe $msvc $so_debug_flag -o $file_base -shared $file' if v.pref.show_c_cmd { println(cmd_compile_shared_library) } diff --git a/compiler/main.v b/compiler/main.v index cb3fe32def..a041285b3e 100644 --- a/compiler/main.v +++ b/compiler/main.v @@ -91,8 +91,14 @@ mut: 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 - is_debuggable bool - is_debug bool // keep compiled C files + + 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_keep_c bool // -keep_c , tell v to leave the generated .tmp.c alone (since by default v will delete them after c backend finishes) + // NB: passing -cg instead of -g will set is_vlines to false and is_g to true, thus making v generate cleaner C files, + // which are sometimes easier to debug / inspect manually than the .tmp.c files by plain -g (when/if v line number generation breaks). + 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 no_auto_free bool // `v -nofree` disable automatic `free()` insertion for better performance in some applications (e.g. compilers) cflags string // Additional options which will be passed to the C compiler. @@ -460,14 +466,16 @@ fn (v mut V) generate_main() { mut cgen := v.cgen $if js { return } - ///// After this point, the v files are compiled. - ///// The rest is auto generated code, which will not have - ///// different .v source file/line numbers. - lines_so_far := cgen.lines.join('\n').count('\n') + 5 - cgen.genln('') - cgen.genln('////////////////// Reset the file/line numbers //////////') - cgen.lines << '#line $lines_so_far "${cescaped_path(os.realpath(cgen.out_path))}"' - cgen.genln('') + if v.pref.is_vlines { + ///// After this point, the v files are compiled. + ///// The rest is auto generated code, which will not have + ///// different .v source file/line numbers. + lines_so_far := cgen.lines.join('\n').count('\n') + 5 + cgen.genln('') + cgen.genln('////////////////// Reset the file/line numbers //////////') + cgen.lines << '#line $lines_so_far "${cescaped_path(os.realpath(cgen.out_path))}"' + cgen.genln('') + } // Make sure the main function exists // Obviously we don't need it in libraries @@ -612,7 +620,7 @@ fn (v mut V) add_v_files_to_compile() { mut builtin_files := v.get_builtin_files() // Builtin cache exists? Use it. builtin_vh := '$v_modules_path${os.PathSeparator}vlib${os.PathSeparator}builtin.vh' - if v.pref.is_debug && os.file_exists(builtin_vh) { + if v.pref.is_cache && os.file_exists(builtin_vh) { v.cached_mods << 'builtin' builtin_files = [builtin_vh] } @@ -656,7 +664,7 @@ fn (v mut V) add_v_files_to_compile() { if v.pref.build_mode != .build_module && !mod.contains('vweb') { mod_path := mod.replace('.', os.PathSeparator) vh_path := '$v_modules_path${os.PathSeparator}vlib${os.PathSeparator}${mod_path}.vh' - if v.pref.is_debug && os.file_exists(vh_path) { + if v.pref.is_cache && os.file_exists(vh_path) { println('using cached module `$mod`: $vh_path') v.cached_mods << mod v.files << vh_path @@ -941,8 +949,12 @@ fn new_v(args[]string) &V { is_so: '-shared' in args is_prod: '-prod' in args is_verbose: '-verbose' in args || '--verbose' in args - is_debuggable: '-g' in args - is_debug: '-debug' in args || '-g' 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_cache: '-cache' in args + is_stats: '-stats' in args obfuscate: obfuscate is_prof: '-prof' in args diff --git a/compiler/msvc.v b/compiler/msvc.v index b4591d00ee..f4693cbfa8 100644 --- a/compiler/msvc.v +++ b/compiler/msvc.v @@ -213,7 +213,7 @@ fn find_msvc() ?MsvcResult { pub fn (v mut V) cc_msvc() { r := find_msvc() or { // TODO: code reuse - if !v.pref.is_debug && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' { + if !v.pref.is_keep_c && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' { os.rm(v.out_name_c) } verror('Cannot find MSVC on this OS') @@ -358,7 +358,7 @@ pub fn (v mut V) cc_msvc() { // println(res) // println('C OUTPUT:') - if !v.pref.is_debug && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' { + if !v.pref.is_keep_c && v.out_name_c != 'v.c' && v.out_name_c != 'v_macos.c' { os.rm(v.out_name_c) } diff --git a/compiler/parser.v b/compiler/parser.v index a9c2ad96cd..9a1cd41697 100644 --- a/compiler/parser.v +++ b/compiler/parser.v @@ -103,7 +103,7 @@ fn (v mut V) new_parser_from_string(text string, id string) Parser { fn (v mut V) reset_cgen_file_line_parameters(){ v.cgen.line = 0 v.cgen.file = '' - v.cgen.line_directives = v.pref.is_debuggable + v.cgen.line_directives = v.pref.is_vlines } fn (v mut V) new_parser_from_file(path string) Parser { diff --git a/compiler/vhelp.v b/compiler/vhelp.v index de4a7f1fab..9d0940effe 100644 --- a/compiler/vhelp.v +++ b/compiler/vhelp.v @@ -39,19 +39,28 @@ Options/commands: -os Produce an executable for the selected OS. OS can be linux, mac, windows, msvc. Use msvc if you want to use the MSVC compiler on Windows. + -shared Build a shared library. + -stats Show additional stats when compiling/running tests. Try `v -stats test .` + + -cache Turn on usage of the precompiled module cache. + It very significantly speeds up secondary compilations. + + -obf Obfuscate the resulting binary. + - Shorthand for `v runrepl`. + +Options for debugging/troubleshooting v programs: + -g Generate debugging information in the backtraces. Add *V* line numbers to the generated executable. + -cg Same as -g, but add *C* line numbers to the generated executable instead of *V* line numbers. + -keep_c Do NOT remove the generated .tmp.c files after compilation. + It is useful when using debuggers like gdb/visual studio, when given after -g / -cg . + -show_c_cmd Print the full C compilation command and how much time it took. -cc Specify which C compiler you want to use as a C backend. The C backend compiler should be able to handle C99 compatible C code. Common C compilers are gcc, clang, tcc, icc, cl... -cflags Pass additional C flags to the C backend compiler. Example: -cflags `sdl2-config --cflags` - -debug Keep the generated C file for debugging in program.tmp.c even after compilation. - -shared Build a shared library. - -stats Show additional stats when compiling/running tests. Try `v -stats test .` - -g Show v line numbers in backtraces. Implies -debug. - -obf Obfuscate the resulting binary. - -show_c_cmd Print the full C compilation command and how much time it took. - - Shorthand for `v runrepl`. +Commands: up Update V. Run `v up` at least once per day, since V development is rapid and features/bugfixes are added constantly. run Build and execute the V program in file.v. You can add arguments for the V program *after* the file name. build Compile a module into an object file.