Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear how to compile a static binary #21760

Open
justinas opened this issue Jun 29, 2024 · 3 comments
Open

Unclear how to compile a static binary #21760

justinas opened this issue Jun 29, 2024 · 3 comments
Labels
Bug This tag is applied to issues which reports bugs.

Comments

@justinas
Copy link

justinas commented Jun 29, 2024

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.

@justinas justinas added the Bug This tag is applied to issues which reports bugs. label Jun 29, 2024
@JalonSolov
Copy link
Contributor

v -cflags "-static" hello.v

Results in

$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=5218322b2e2cfe1833e376dff28d3a93ddf4c9be, for GNU/Linux 4.4.0, not stripped

@justinas
Copy link
Author

justinas commented Jun 29, 2024

v -cflags "-static" hello.v

Results in

$ file hello
hello: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=5218322b2e2cfe1833e376dff28d3a93ddf4c9be, for GNU/Linux 4.4.0, not stripped

Cool! It does work on Ubuntu. On NixOS, you need to have glibc.static.

$ nix-shell -p glibc.static vlang
$ v -cflags -static hello.v
$ file ./hello
./hello: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.10.0, not stripped
$ ./hello
hello world

I still think that either this should be made the default, or the necessary flags clearly documented, or the claims about producing static binaries adjusted.

On another note, -cflags will of course have no effect on the native backend, so eventually (once native backend is viable) something like a dedicated -static flag will be necessary anyway.

@JalonSolov
Copy link
Contributor

I doubt it will be made the default, as it increases the file size by quite a bit...

[jalon@7950x ~]$ v hello.v
[jalon@7950x ~]$ ls -l hello
-rwxr-xr-x 1 jalon jalon 701432 Jun 29 15:56 hello
[jalon@7950x ~]$ v -cflags -static hello.v
[jalon@7950x ~]$ ls -l hello
-rwxr-xr-x 1 jalon jalon 1416784 Jun 29 15:56 hello
[jalon@7950x ~]$ 

... over twice as large output.

However, agreed that it could be made more obvious how to achieve statically linked binaries, and that it will also be necessary for a switch that works with the native backend... once that's actually working. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug This tag is applied to issues which reports bugs.
Projects
None yet
Development

No branches or pull requests

2 participants