From 231cd8d5dd107fee3afdee9af07e76ef69fa0b58 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 21 Apr 2026 15:42:48 +0300 Subject: [PATCH] builder: fix windows cross compilation arm error (fixes #24785) --- vlib/v/builder/cc.v | 46 +++++++++++++++++++++++++++++------ vlib/v/builder/cc_test.v | 17 +++++++++++++ vlib/v/help/build/build-c.txt | 2 ++ vlib/v/pref/default.v | 18 ++++++-------- vlib/v/pref/pref_test.v | 9 +++++++ 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/vlib/v/builder/cc.v b/vlib/v/builder/cc.v index 5184a1bf6..1bd5eb4a8 100644 --- a/vlib/v/builder/cc.v +++ b/vlib/v/builder/cc.v @@ -1565,7 +1565,30 @@ fn (mut b Builder) get_subsystem_flag() string { } } +struct LinuxCrossTarget { + triple string + lib_dir string + dynamic_linker string + linker_emulation string +} + +fn linux_cross_target_for_arch(arch pref.Arch) !LinuxCrossTarget { + if arch != .amd64 { + return error('Linux cross compilation currently supports only `-arch amd64`; the bundled linuxroot sysroot does not provide `${arch}` runtime files.') + } + return LinuxCrossTarget{ + triple: 'x86_64-linux-gnu' + lib_dir: 'x86_64-linux-gnu' + dynamic_linker: '/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2' + linker_emulation: 'elf_x86_64' + } +} + fn (mut b Builder) cc_linux_cross() { + linux_cross_target := linux_cross_target_for_arch(b.pref.arch) or { + verror(err.msg()) + return + } b.setup_ccompiler_options(b.pref.ccompiler) b.build_thirdparty_obj_files() b.setup_output_name() @@ -1575,13 +1598,17 @@ fn (mut b Builder) cc_linux_cross() { } sysroot := os.join_path(os.vmodules_dir(), 'linuxroot') b.ensure_linuxroot_exists(sysroot) - obj_file := b.out_name_c + '.o' + obj_file := if b.pref.build_mode == .build_module { + b.pref.out_name + } else { + b.out_name_c + '.o' + } cflags := b.get_os_cflags() defines, others, libs := cflags.defines_others_libs() mut cc_args := []string{cap: 20} cc_args << '-w' cc_args << '-fPIC' - cc_args << '-target x86_64-linux-gnu' + cc_args << '-target ${linux_cross_target.triple}' cc_args << defines cc_args << '-I ${os.quoted_path('${sysroot}/include')} ' cc_args << others @@ -1604,13 +1631,16 @@ fn (mut b Builder) cc_linux_cross() { verror(cc_res.output) return } + if b.pref.build_mode == .build_module { + return + } // Compile compiler runtime builtins (provides __udivti3 etc. for 128-bit integer // operations used by thirdparty code like mbedtls bignum.c, since the linuxroot // sysroot doesn't include libgcc or compiler-rt). builtins_src := os.join_path(@VEXEROOT, 'thirdparty', 'builtins', 'compiler_builtins.c') - builtins_obj := os.join_path(os.vtmp_dir(), 'compiler_builtins.o') + builtins_obj := os.join_path(os.vtmp_dir(), 'compiler_builtins_${linux_cross_target.lib_dir}.o') if os.exists(builtins_src) { - builtins_cmd := '${b.quote_compiler_name(cc_name)} -w -fPIC -target x86_64-linux-gnu -o ${os.quoted_path(builtins_obj)} -c ${os.quoted_path(builtins_src)}' + builtins_cmd := '${b.quote_compiler_name(cc_name)} -w -fPIC -target ${linux_cross_target.triple} -o ${os.quoted_path(builtins_obj)} -c ${os.quoted_path(builtins_src)}' builtins_res := os.execute(builtins_cmd) if builtins_res.exit_code != 0 { println('Warning: failed to compile compiler builtins for cross compilation.') @@ -1618,16 +1648,16 @@ fn (mut b Builder) cc_linux_cross() { } mut linker_args := [ '-L', - os.quoted_path('${sysroot}/usr/lib/x86_64-linux-gnu/'), + os.quoted_path(os.join_path(sysroot, 'usr', 'lib', linux_cross_target.lib_dir)), '-L', - os.quoted_path('${sysroot}/lib/x86_64-linux-gnu'), + os.quoted_path(os.join_path(sysroot, 'lib', linux_cross_target.lib_dir)), '--sysroot=' + os.quoted_path(sysroot), '-v', '-o', os.quoted_path(out_name), - '-m elf_x86_64', + '-m ${linux_cross_target.linker_emulation}', '-dynamic-linker', - os.quoted_path('/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2'), + os.quoted_path(linux_cross_target.dynamic_linker), os.quoted_path('${sysroot}/crt1.o'), os.quoted_path('${sysroot}/crti.o'), os.quoted_path(obj_file), diff --git a/vlib/v/builder/cc_test.v b/vlib/v/builder/cc_test.v index 762bb8c9e..7a7ca669e 100644 --- a/vlib/v/builder/cc_test.v +++ b/vlib/v/builder/cc_test.v @@ -205,6 +205,23 @@ fn test_sqlite_thirdparty_validation_error_ignores_other_modules() { assert sqlite_thirdparty_validation_error('json.cjson', obj_path, source_path, .cpp) == '' } +fn test_linux_cross_target_for_amd64() { + target := linux_cross_target_for_arch(.amd64) or { panic(err) } + assert target.triple == 'x86_64-linux-gnu' + assert target.lib_dir == 'x86_64-linux-gnu' + assert target.dynamic_linker == '/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2' + assert target.linker_emulation == 'elf_x86_64' +} + +fn test_linux_cross_target_for_arm64_errors() { + if target := linux_cross_target_for_arch(.arm64) { + assert false, 'unexpected target: ${target}' + } else { + assert err.msg().contains('only `-arch amd64`') + assert err.msg().contains('linuxroot') + } +} + fn test_live_termux_linker_args_include_rdynamic_without_debug() { linker_args := builder_linker_args([ '-os', diff --git a/vlib/v/help/build/build-c.txt b/vlib/v/help/build/build-c.txt index ceeb78cfa..f97fc3e73 100644 --- a/vlib/v/help/build/build-c.txt +++ b/vlib/v/help/build/build-c.txt @@ -180,6 +180,8 @@ see also `v help build`. in order to override the default cross compiler, that V will use (`x86_64-w64-mingw32-gcc` for targeting Windows, and `clang` for targeting Linux from other operating systems). + Note: the bundled Linux cross-compilation sysroot currently contains + x86_64 runtime files only, so `-os linux -arch arm64` is not supported yet. -macosx-version-min 11.0 Only relevant on macos. It will be passed as -mmacosx-version-min=11.0 to diff --git a/vlib/v/pref/default.v b/vlib/v/pref/default.v index cdbf589b9..d7608db0c 100644 --- a/vlib/v/pref/default.v +++ b/vlib/v/pref/default.v @@ -75,16 +75,14 @@ fn (mut p Preferences) setup_os_and_arch_when_not_explicitly_set() { p.build_options << '-os ${host_os.lower()}' } - if !p.output_cross_c { - if p.os != host_os { - // TODO: generalise this not only for macos->linux, after considering the consequences for vab/Android: - if host_os == .macos && p.os == .linux { - // Cross compilation from macos -> linux; assume AMD64 as the target architecture for now - if p.arch == ._auto { - p.set_default_arch(.amd64) - } - p.parse_define('use_bundled_libgc') - } + if !p.output_cross_c && p.os != host_os { + if p.os == .linux && p.arch == ._auto { + // The bundled linuxroot sysroot currently only contains x86_64 runtime files. + p.set_default_arch(.amd64) + } + // TODO: generalise this not only for macos->linux, after considering the consequences for vab/Android: + if host_os == .macos && p.os == .linux { + p.parse_define('use_bundled_libgc') } } } diff --git a/vlib/v/pref/pref_test.v b/vlib/v/pref/pref_test.v index 89a8b2982..a1dbd4d14 100644 --- a/vlib/v/pref/pref_test.v +++ b/vlib/v/pref/pref_test.v @@ -164,6 +164,15 @@ fn test_cross_compile_windows_m32_uses_i386_arch_and_compiler() { assert prefs.build_options.contains('-m32') } +fn test_cross_compile_defaults_linux_to_amd64() { + if pref.get_host_os() == .linux { + return + } + target := os.join_path(vroot, 'examples', 'hello_world.v') + prefs, _ := pref.parse_args_and_show_errors([], ['', '-os', 'linux', target], false) + assert prefs.arch == .amd64 +} + fn test_cross_compile_infers_android_arch_from_vcross_compiler_name() { target := os.join_path(vroot, 'examples', 'hello_world.v') old_cross_compiler := os.getenv('VCROSS_COMPILER_NAME') -- 2.39.5