Skip to content

Unclear how to compile a static binary #21760

@justinas

Description

@justinas

Describe the bug

The V website claims that "You get a single statically linked binary". However, by default the compiler produces a dynamic binary, and there seems to be no way to produce a working static binary.

Reproduction Steps

Compile any code with V. Result is a dynamically linked binary.

Expected Behavior

Expected V to produce a statically linked binary.

Current Behavior

Compiling without any additional flags produces a dynamic binary:

$ cat hello.v
fn main() {
    println("hello world")
}
$ v hello.v
$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped

Compiling with musl-gcc as suggested in #19792 (comment) does not work because pthreads fail to link:

$ v -cc musl-gcc -cg hello.v
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `open_proc_fd':
gc.c:(.text+0x13a7): undefined reference to `__snprintf_chk'
/usr/bin/ld: gc.c:(.text+0x13ba): undefined reference to `__open_2'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_fault_handler':
gc.c:(.text+0x14aa): undefined reference to `__longjmp_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_with_callee_saves_pushed':
gc.c:(.text+0x2f2c): undefined reference to `getcontext'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_printf':
gc.c:(.text+0x420a): undefined reference to `__vsnprintf_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_log_printf':
gc.c:(.text+0x4867): undefined reference to `__vsnprintf_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_err_printf':
gc.c:(.text+0x79f4): undefined reference to `__vsnprintf_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_print_callers':
gc.c:(.text+0x7c54): undefined reference to `__snprintf_chk'
/usr/bin/ld: gc.c:(.text+0x7cef): undefined reference to `__snprintf_chk'
/usr/bin/ld: gc.c:(.text+0x7d36): undefined reference to `__memcpy_chk'
/usr/bin/ld: gc.c:(.text+0x7e64): undefined reference to `__snprintf_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_print_all_errors.part.0':
gc.c:(.text+0x826e): undefined reference to `__memcpy_chk'
/usr/bin/ld: gc.c:(.text+0x828a): undefined reference to `__memset_chk'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(gc.o): in function `GC_init':
gc.c:(.text+0xf53e): undefined reference to `gnu_get_libc_version'
/usr/bin/ld: /home/justinas/vlang-box/compiler/thirdparty/tcc/lib/libgc.a(pthread_start.o): in function `GC_pthread_start_inner':
pthread_start.c:(.text+0x82): undefined reference to `__pthread_register_cancel'
/usr/bin/ld: pthread_start.c:(.text+0xa9): undefined reference to `__pthread_unregister_cancel'
collect2: error: ld returned 1 exit status
builder error:
==================
C error found. It should never happen, when compiling pure V code.
This is a V compiler bug, please report it using `v bug file.v`,
or goto https://github.com/vlang/v/issues/new/choose .
You can also use #help on Discord: https://discord.gg/vlang .

Compiling with -freestanding as suggested by a Stack Overflow answer does produce a static binary, but it also makes V not link the C standard library at all (statically or dynamically). Since basic functionality of V depends on libc, this means that even basic code does not work out of the box in this mode:

$ cat array.v
fn main() {
    mut foo := [1, 2, 3]
    foo.sort()
    println(foo)
}
$ v -freestanding array.v
$ file array
array: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, BuildID[sha1]=19986c1fa887f421581deb1982106b06a5a33ee6, not stripped
$ ./array
V panicsort does not work with -freestanding

Possible Solution

V should either:

  1. Output static binaries by default, since that is the claim on the front page.
  2. Provide a dedicated, well documented flag that would link the resulting binary statically instead of dynamically, e.g. v -static. V shouldn't lose basic functionality when the code is compiled this way.

Additional Information/Context

No response

V version

V 0.4.6 4a7c70c

Environment details (OS name and version, etc.)

$ v doctor
V full version: V 0.4.6 4a7c70c
OS: linux, Linux version 6.6.33 (nixbld@localhost) (gcc (GCC) 13.2.0, GNU ld (GNU Binutils) 2.41) #1-NixOS SMP PREEMPT_DYNAMIC Wed Jun 12 09:13:03 UTC 2024 (chroot)
Processor: 16 cpus, 64bit, little endian, AMD Ryzen 7 PRO 4750U with Radeon Graphics

getwd: /home/justinas/vlang-testcases
vexe: /home/justinas/vlang-box/compiler/v
vexe mtime: 2024-06-28 20:18:31

vroot: OK, value: /home/justinas/vlang-box/compiler
VMODULES: OK, value: /home/justinas/.vmodules
VTMP: OK, value: /tmp/v_1000

Git version: git version 2.43.0
Git vroot status: weekly.2024.26-14-g4a7c70c9 (3 commit(s) behind V master)
.git/config present: true

CC version: cc (Ubuntu 13.2.0-23ubuntu4) 13.2.0
thirdparty/tcc status: thirdparty-linux-amd64 40e5cbb5

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugThis tag is applied to issues which reports bugs.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions