From dc00f0d65a2ee7049d386d7c3e98e540dbc243b9 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 30 Apr 2026 03:07:28 +0300 Subject: [PATCH] builder: fix TCC compiler integration for parallel compilation (#27033) --- vlib/v/builder/cbuilder/parallel_cc.v | 22 ++++++++++++++++------ vlib/v/gen/c/cgen.v | 8 ++------ vlib/v/gen/c/cheaders.v | 6 +++++- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/vlib/v/builder/cbuilder/parallel_cc.v b/vlib/v/builder/cbuilder/parallel_cc.v index 6d200839a..c6a2ff4f2 100644 --- a/vlib/v/builder/cbuilder/parallel_cc.v +++ b/vlib/v/builder/cbuilder/parallel_cc.v @@ -80,11 +80,18 @@ fn parallel_cc(mut b builder.Builder, result c.GenOutput) ! { mut compile_args := b.get_compile_args() mut linker_args := b.get_linker_args() if b.ccoptions.cc == .tcc { - tcc_root := os.join_path(@VEXEROOT, 'thirdparty', 'tcc') - if os.is_dir(tcc_root) { - tcc_base_arg := '-B${b.tcc_quoted_path(tcc_root)}' - compile_args << tcc_base_arg - linker_args << tcc_base_arg + // vlang/tcc has its system headers under `${vroot}/thirdparty/tcc/lib/tcc/include/` + // and its runtime objects (libtcc1.a, bt-*.o) under `${vroot}/thirdparty/tcc/lib/tcc/`. + // `-B` controls tcc's include search (`${B}/include`) and `-L` adds a library search path, + // so pass absolute paths for both. This lets tcc find them regardless of the cwd from + // which v was invoked, without affecting how user-supplied relative flags are resolved. + tcc_install_dir := os.join_path(@VEXEROOT, 'thirdparty', 'tcc', 'lib', 'tcc') + if os.is_dir(tcc_install_dir) { + tcc_b_arg := '-B${b.tcc_quoted_path(tcc_install_dir)}' + tcc_l_arg := '-L${b.tcc_quoted_path(tcc_install_dir)}' + compile_args << tcc_b_arg + linker_args << tcc_b_arg + linker_args << tcc_l_arg } } scompile_args := compile_args.join(' ') @@ -138,7 +145,10 @@ fn parallel_cc(mut b builder.Builder, result c.GenOutput) ! { sw_link := time.new_stopwatch() link_res := os.execute(link_cmd) eprint_result_time(sw_link, 'link_cmd', link_cmd, link_res) - if link_res.exit_code != 0 { + // tcc reports duplicate symbol errors via stderr and an executable still gets emitted with exit code 0, + // so detect that pattern and treat it as a link failure too. + link_failed_with_tcc_dup := b.ccoptions.cc == .tcc && link_res.output.contains('defined twice') + if link_res.exit_code != 0 || link_failed_with_tcc_dup { return error_with_code('failed to link after parallel C compilation', 1) } } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 0d0234782..f2f3cc46f 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -13031,9 +13031,7 @@ fn (mut g Gen) panic_debug_info(pos token.Pos) (int, string, string, string) { // when available, or emits `imessage` through a C error otherwise. pub fn get_guarded_include_text(iname string, imessage string) string { res := ' - |#if defined(__TINYC__) - |#include ${iname} - |#elif defined(__has_include) + |#if defined(__has_include) |#if __has_include(${iname}) |#include ${iname} |#else @@ -13050,9 +13048,7 @@ pub fn get_guarded_include_text(iname string, imessage string) string { // the best available integer types header, or emits `imessage` otherwise. pub fn get_inttypes_or_stdint_include_text(imessage string) string { res := ' - |#if defined(__TINYC__) - |#include - |#elif defined(__has_include) + |#if defined(__has_include) |#if __has_include() |#include |#elif __has_include() diff --git a/vlib/v/gen/c/cheaders.v b/vlib/v/gen/c/cheaders.v index 99f1d3f8a..e565dadce 100644 --- a/vlib/v/gen/c/cheaders.v +++ b/vlib/v/gen/c/cheaders.v @@ -214,7 +214,11 @@ const c_common_macros = ' #endif #else #define VV_EXP extern - #define VV_LOC static + #ifdef _VPARALLELCC + #define VV_LOC + #else + #define VV_LOC static + #endif #endif #endif #ifdef __cplusplus -- 2.39.5