From 735046a3d4e5cee71ebccad9d7af4a1b8a55a6a6 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Tue, 11 Feb 2025 10:08:25 +0200 Subject: [PATCH] v.builder: cleanup quoted path handling (followup to #23686) (#23688) --- vlib/v/builder/cbuilder/parallel_cc.v | 22 ++++- vlib/v/builder/cc.v | 114 +++++++++++++++++--------- vlib/v/builder/compile.v | 2 +- vlib/v/builder/msvc_windows.v | 2 +- 4 files changed, 99 insertions(+), 41 deletions(-) diff --git a/vlib/v/builder/cbuilder/parallel_cc.v b/vlib/v/builder/cbuilder/parallel_cc.v index 401bf7d75a..9c5fc5756e 100644 --- a/vlib/v/builder/cbuilder/parallel_cc.v +++ b/vlib/v/builder/cbuilder/parallel_cc.v @@ -107,8 +107,26 @@ fn parallel_cc(mut b builder.Builder, result c.GenOutput) ! { return error_with_code('failed parallel C compilation', failed) } - obj_files := fnames.map(it.replace('.c', '.o')).join(' ') - link_cmd := '${cc} ${scompile_args_for_linker} -o ${os.quoted_path(b.pref.out_name)} ${tmp_dir}/out_0.o ${obj_files} ${tmp_dir}/out_x.o ${slinker_args} ${cc_ldflags}' + mut ofiles := []string{} + for f in fnames { + fo := f.replace('.c', '.o') + ofiles << os.quoted_path(fo) + } + obj_files := ofiles.join(' ') + + alink := [ + cc, + scompile_args_for_linker, + '-o', + os.quoted_path(b.pref.out_name), + os.quoted_path('${tmp_dir}/out_0.o'), + obj_files, + os.quoted_path('${tmp_dir}/out_x.o'), + slinker_args, + cc_ldflags, + ] + link_cmd := alink.join(' ') + sw_link := time.new_stopwatch() link_res := os.execute(link_cmd) eprint_result_time(sw_link, 'link_cmd', link_cmd, link_res) diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 9dda7fd140..802e05a23b 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -380,7 +380,7 @@ fn (mut v Builder) setup_ccompiler_options(ccompiler string) { } // The C file we are compiling if !v.pref.parallel_cc { // parallel_cc uses its own split up c files - ccoptions.source_args << '"${v.out_name_c}"' + ccoptions.source_args << v.tcc_quoted_path(v.out_name_c) } // Min macos version is mandatory I think? if v.pref.os == .macos { @@ -573,7 +573,11 @@ fn (mut v Builder) thirdparty_object_args(ccoptions CcompilerOptions, middle []s // all << ccoptions.env_ldflags // all << ccoptions.ldflags if cross_compiling_from_macos_to_linux { - all << '-I${os.quoted_path(sysroot)}/include' // add the system include/ folder after everything else, so that local folders like thirdparty/mbedtls have a chance to supply their own headers + // add the system include/ folder after everything else, + // so that local folders like thirdparty/mbedtls have a + // chance to supply their own headers + all << '-I' + all << os.quoted_path('${sysroot}/include') } return all } @@ -603,20 +607,28 @@ fn (mut v Builder) setup_output_name() { // println(v.ast.imports) } if os.is_dir(v.pref.out_name) { - verror("'${v.pref.out_name}' is a directory") + verror('${os.quoted_path(v.pref.out_name)} is a directory') } if !v.pref.parallel_cc { // parallel_cc sets its own `-o out_n.o` - v.ccoptions.o_args << '-o "${v.pref.out_name}"' + v.ccoptions.o_args << '-o ${v.tcc_quoted_path(v.pref.out_name)}' } } +pub fn (mut v Builder) tcc_quoted_path(p string) string { + if v.ccoptions.cc == .tcc && !v.pref.no_rsp { + // tcc has a bug, that prevents it from being able to parse names quoted with ' in .rsp files :-| + return '"${p}"' + } + return os.quoted_path(p) +} + pub fn (mut v Builder) cc() { if os.executable().contains('vfmt') { return } if v.pref.is_verbose { - println('builder.cc() pref.out_name="${v.pref.out_name}"') + println('builder.cc() pref.out_name=${os.quoted_path(v.pref.out_name)}') } if v.pref.only_check_syntax { if v.pref.is_verbose { @@ -642,7 +654,7 @@ pub fn (mut v Builder) cc() { ends_with_js := v.pref.out_name.ends_with('.js') if ends_with_c || ends_with_js { v.pref.skip_running = true - msg_mv := 'os.mv_by_cp ${v.out_name_c} => ${v.pref.out_name}' + msg_mv := 'os.mv_by_cp ${os.quoted_path(v.out_name_c)} => ${os.quoted_path(v.pref.out_name)}' util.timing_start(msg_mv) // v.out_name_c may be on a different partition than v.out_name os.mv_by_cp(v.out_name_c, v.pref.out_name) or { panic(err) } @@ -851,7 +863,7 @@ fn (mut b Builder) ensure_linuxroot_exists(sysroot string) { } if !os.is_dir(sysroot) { println('Downloading files for Linux cross compilation (~77MB) ...') - os.system('git clone ${crossrepo_url} ${sysroot}') + os.system('git clone "${crossrepo_url}" ${os.quoted_path(sysroot)}') if !os.exists(sysroot_git_config_path) { verror('Failed to clone `${crossrepo_url}` to `${sysroot}`') } @@ -868,7 +880,7 @@ fn (mut b Builder) ensure_freebsdroot_exists(sysroot string) { } if !os.is_dir(sysroot) { println('Downloading files for FreeBSD cross compilation (~458MB) ...') - os.system('git clone ${crossrepo_url} ${sysroot}') + os.system('git clone "${crossrepo_url}" ${os.quoted_path(sysroot)}') if !os.exists(sysroot_git_config_path) { verror('Failed to clone `${crossrepo_url}` to `${sysroot}`') } @@ -899,13 +911,12 @@ fn (mut b Builder) cc_linux_cross() { mut cc_args := []string{cap: 20} cc_args << '-w' cc_args << '-fPIC' - cc_args << '-c' cc_args << '-target x86_64-linux-gnu' cc_args << defines - cc_args << '-I ${sysroot}/include ' + cc_args << '-I ${os.quoted_path('${sysroot}/include')} ' cc_args << others - cc_args << '-o "${obj_file}"' - cc_args << '-c "${b.out_name_c}"' + cc_args << '-o ${os.quoted_path(obj_file)}' + cc_args << '-c ${os.quoted_path(b.out_name_c)}' cc_args << libs b.dump_c_options(cc_args) mut cc_name := 'cc' @@ -924,11 +935,29 @@ fn (mut b Builder) cc_linux_cross() { verror(cc_res.output) return } - mut linker_args := ['-L${sysroot}/usr/lib/x86_64-linux-gnu/', - '-L${sysroot}/lib/x86_64-linux-gnu', '--sysroot=${sysroot}', '-v', '-o ${out_name}', - '-m elf_x86_64', '-dynamic-linker /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2', - '${sysroot}/crt1.o ${sysroot}/crti.o ${obj_file}', '-lc', '-lcrypto', '-lssl', '-lpthread', - '${sysroot}/crtn.o', '-lm', '-ldl'] + mut linker_args := [ + '-L', + os.quoted_path('${sysroot}/usr/lib/x86_64-linux-gnu/'), + '-L', + os.quoted_path('${sysroot}/lib/x86_64-linux-gnu'), + '--sysroot=' + os.quoted_path(sysroot), + '-v', + '-o', + os.quoted_path(out_name), + '-m elf_x86_64', + '-dynamic-linker', + os.quoted_path('/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2'), + os.quoted_path('${sysroot}/crt1.o'), + os.quoted_path('${sysroot}/crti.o'), + os.quoted_path(obj_file), + '-lc', + '-lcrypto', + '-lssl', + '-lpthread', + os.quoted_path('${sysroot}/crtn.o'), + '-lm', + '-ldl', + ] linker_args << cflags.c_options_only_object_files() // -ldl b.dump_c_options(linker_args) @@ -937,8 +966,6 @@ fn (mut b Builder) cc_linux_cross() { ldlld = 'ld.lld.exe' } linker_cmd := '${b.quote_compiler_name(ldlld)} ' + linker_args.join(' ') - // s = s.replace('SYSROOT', sysroot) // TODO: $ inter bug - // s = s.replace('-o hi', '-o ' + c.pref.out_name) if b.pref.show_cc { println(linker_cmd) } @@ -967,14 +994,17 @@ fn (mut b Builder) cc_freebsd_cross() { mut cc_args := []string{cap: 20} cc_args << '-w' cc_args << '-fPIC' - cc_args << '-c' cc_args << '-target x86_64-unknown-freebsd14.0' // TODO custom freebsd versions cc_args << defines - cc_args << '-I ${sysroot}/include ' - cc_args << '-I ${sysroot}/usr/include ' + cc_args << '-I' + cc_args << os.quoted_path('${sysroot}/include') + cc_args << '-I' + cc_args << os.quoted_path('${sysroot}/usr/include') cc_args << others - cc_args << '-o "${obj_file}"' - cc_args << '-c "${b.out_name_c}"' + cc_args << '-o' + cc_args << os.quoted_path(obj_file) + cc_args << '-c' + cc_args << os.quoted_path(b.out_name_c) cc_args << libs b.dump_c_options(cc_args) mut cc_name := b.pref.vcross_compiler_name() @@ -993,10 +1023,22 @@ fn (mut b Builder) cc_freebsd_cross() { verror(cc_res.output) return } - mut linker_args := ['-L${sysroot}/lib/', '-L${sysroot}/usr/lib/', '--sysroot=${sysroot}', '-v', - '-o ${out_name}', '-m elf_x86_64', '-dynamic-linker /libexec/ld-elf.so.1', - '${sysroot}/usr/lib/crt1.o ${sysroot}/usr/lib/crti.o ${obj_file}', - '${sysroot}/usr/lib/crtn.o'] + mut linker_args := [ + '-L', + os.quoted_path('${sysroot}/lib/'), + '-L', + os.quoted_path('${sysroot}/usr/lib/'), + '--sysroot=' + os.quoted_path(sysroot), + '-v', + '-o', + os.quoted_path(out_name), + '-m elf_x86_64', + '-dynamic-linker /libexec/ld-elf.so.1', + os.quoted_path('${sysroot}/usr/lib/crt1.o'), + os.quoted_path('${sysroot}/usr/lib/crti.o'), + os.quoted_path(obj_file), + os.quoted_path('${sysroot}/usr/lib/crtn.o'), + ] linker_args << '-lc' // needed for fwrite, strlen etc linker_args << '-lexecinfo' // needed for backtrace linker_args << cflags.c_options_only_object_files() // support custom module defined linker flags @@ -1006,8 +1048,6 @@ fn (mut b Builder) cc_freebsd_cross() { // mut ldlld := '${sysroot}/ld.lld' mut ldlld := b.pref.vcross_linker_name() linker_cmd := '${b.quote_compiler_name(ldlld)} ' + linker_args.join(' ') - // s = s.replace('SYSROOT', sysroot) // TODO: $ inter bug - // s = s.replace('-o hi', '-o ' + c.pref.out_name) if b.pref.show_cc { println(linker_cmd) } @@ -1065,13 +1105,13 @@ fn (mut c Builder) cc_windows_cross() { } mut libs := []string{} if false && c.pref.build_mode == .default_mode { - builtin_o := '"${pref.default_module_path}/vlib/builtin.o"' - libs << builtin_o + builtin_o := '${pref.default_module_path}/vlib/builtin.o' + libs << os.quoted_path(builtin_o) if !os.exists(builtin_o) { verror('${builtin_o} not found') } for imp in c.table.imports { - libs << '"${pref.default_module_path}/vlib/${imp}.o"' + libs << os.quoted_path('${pref.default_module_path}/vlib/${imp}.o') } } // add the thirdparty .o files, produced by all the #flag directives: @@ -1143,10 +1183,10 @@ fn (mut v Builder) build_thirdparty_obj_file(mod string, path string, moduleflag cpp_file = true } opath := v.pref.cache_manager.mod_postfix_with_key2cpath(mod, '.o', obj_path) - mut rebuild_reason_message := '${obj_path} not found, building it in ${opath} ...' + mut rebuild_reason_message := '${os.quoted_path(obj_path)} not found, building it in ${os.quoted_path(opath)} ...' if os.exists(opath) { if os.exists(cfile) && os.file_last_mod_unix(opath) < os.file_last_mod_unix(cfile) { - rebuild_reason_message = '${opath} is older than ${cfile}, rebuilding ...' + rebuild_reason_message = '${os.quoted_path(opath)} is older than ${os.quoted_path(cfile)}, rebuilding ...' } else { return } @@ -1169,8 +1209,8 @@ fn (mut v Builder) build_thirdparty_obj_file(mod string, path string, moduleflag mut all_options := []string{} all_options << v.pref.third_party_option all_options << moduleflags.c_options_before_target() - all_options << '-o ${os.quoted_path(opath)}' - all_options << '-c ${os.quoted_path(cfile)}' + all_options << '-o ${v.tcc_quoted_path(opath)}' + all_options << '-c ${v.tcc_quoted_path(cfile)}' cc_options := v.thirdparty_object_args(v.ccoptions, all_options, cpp_file).join(' ') // If the third party object file requires a CPP file compilation, switch to a CPP compiler diff --git a/vlib/v/builder/compile.v b/vlib/v/builder/compile.v index 52bac1ebc8..8d08ae208f 100644 --- a/vlib/v/builder/compile.v +++ b/vlib/v/builder/compile.v @@ -139,7 +139,7 @@ fn (mut b Builder) run_compiled_executable_and_exit() { } mut ret := 0 if b.pref.use_os_system_to_run { - command_to_run := run_file + ' ' + run_args.join(' ') + command_to_run := os.quoted_path(run_file) + ' ' + run_args.join(' ') ret = os.system(command_to_run) // eprintln('> ret: ${ret:5} | command_to_run: ${command_to_run}') } else { diff --git a/vlib/v/builder/msvc_windows.v b/vlib/v/builder/msvc_windows.v index 3473c17878..09496f8da4 100644 --- a/vlib/v/builder/msvc_windows.v +++ b/vlib/v/builder/msvc_windows.v @@ -338,7 +338,7 @@ pub fn (mut v Builder) cc_msvc() { a << real_libs.join(' ') a << '/link' a << '/nologo' // NOTE: /NOLOGO is explicitly not recognised! - a << '/OUT:"${v.pref.out_name}"' + a << '/OUT:${os.quoted_path(v.pref.out_name)}' a << r.library_paths() if !all_cflags.contains('/DEBUG') { // only use /DEBUG, if the user *did not* provide its own: