ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.79k stars 2.54k forks source link

glibc undefined symbol: fcntl64 when using zig cc as a drop-in compiler #5882

Closed creationix closed 2 years ago

creationix commented 4 years ago

I'm trying to build a small test application with libuv embedded. I want to use zig cc because the caching system makes it much faster. The following command works for clang and gcc, but not zig cc.

zig cc -o main main.c libuv/src/fs-poll.c libuv/src/idna.c libuv/src/inet.c libuv/src/random.c libuv/src/strscpy.c libuv/src/threadpool.c libuv/src/timer.c libuv/src/uv-common.c libuv/src/uv-data-getter-setters.c libuv/src/version.c libuv/src/unix/async.c libuv/src/unix/core.c libuv/src/unix/dl.c libuv/src/unix/fs.c libuv/src/unix/getaddrinfo.c libuv/src/unix/getnameinfo.c libuv/src/unix/loop-watcher.c libuv/src/unix/loop.c libuv/src/unix/pipe.c libuv/src/unix/poll.c libuv/src/unix/process.c libuv/src/unix/random-devurandom.c libuv/src/unix/signal.c libuv/src/unix/stream.c libuv/src/unix/tcp.c libuv/src/unix/thread.c libuv/src/unix/tty.c libuv/src/unix/udp.c libuv/src/unix/proctitle.c libuv/src/unix/linux-core.c libuv/src/unix/linux-inotify.c libuv/src/unix/linux-syscalls.c libuv/src/unix/procfs-exepath.c libuv/src/unix/random-getrandom.c libuv/src/unix/random-sysctl-linux.c -pthread -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -D_POSIX_C_SOURCE=200112 -Os -ldl -lrt  -Ilibuv/include -Ilibuv/src
Compile C Objects [36/36] random-sysctl-linux.c...lld: error: undefined symbol: fcntl64
>>> referenced by core.c
>>>               zig-cache/o/a98yrC-16nzaiLvm0YSsj7Kr64jgWlKyw30Ca_aTuY8lBx8HcWfjUWLmNzWOQ59K/core.o:(uv__nonblock_fcntl)
>>> referenced by core.c
>>>               zig-cache/o/a98yrC-16nzaiLvm0YSsj7Kr64jgWlKyw30Ca_aTuY8lBx8HcWfjUWLmNzWOQ59K/core.o:(uv__nonblock_fcntl)
>>> referenced by core.c
>>>               zig-cache/o/a98yrC-16nzaiLvm0YSsj7Kr64jgWlKyw30Ca_aTuY8lBx8HcWfjUWLmNzWOQ59K/core.o:(uv__cloexec_fcntl)
>>> referenced by core.c
>>>               zig-cache/o/a98yrC-16nzaiLvm0YSsj7Kr64jgWlKyw30Ca_aTuY8lBx8HcWfjUWLmNzWOQ59K/core.o:(uv__cloexec_fcntl)
>>> referenced by pipe.c
>>>               zig-cache/o/Gp2nxP14BgUu9fMnuMMJ4gryoTCPAocIoqmgTAVdptPg5_FP1QjIdJRHfMpqm3ls/pipe.o:(uv_pipe_open)
>>> referenced by process.c
>>>               zig-cache/o/Z2n-GR8LD-1fXu4uIs37LmdvcK0K1mfCZ4iNwE1idOtrGfUhw6eXoJ8i5oMbsgSg/process.o:(uv__process_child_init)
>>> did you mean: fcntl64
>>> defined in: /home/tim/.cache/zig/stage1/h/pVSItZEIxIXx_ZQQwt9SLNNbPH8xxZp1plbirUK6SOmyZ4FTf2EOP08onozfGP03/libc.so.6.0.0

Is there something special I need to pass in for this to build?

creationix commented 4 years ago

In particular, I'm confused by lld: error: undefined symbol: fcntl64 and then did you mean: fcntl64

andrewrk commented 4 years ago

Hmm that is indeed confusing. I think the next step towards troubleshooting this would be to hop into one of the LLVM chat rooms and ask LLD developers if they know why this could happen.

andrewrk commented 4 years ago

One work around would be to try musl libc instead of glibc: -target native-native-musl

squeek502 commented 4 years ago

This is the same problem I was running into here https://github.com/luvit/luvi/issues/231#issuecomment-604227535:

Now I'm running into a problem with mismatched glibc versions (zig cc is compiling against a newer one than my system glibc; specifically it's trying to use fnctl64 which my glibc doesn't have). Zig has the ability to target specific glibc versions (e.g. -target native-native-gnu.2.23) but I'm not sure it affects zig cc.

and https://github.com/luvit/luvi/issues/231#issuecomment-608640080.

Targeting musl should work unless you need dynamic loading (https://github.com/luvit/luvi/issues/231#issuecomment-606512367).

creationix commented 4 years ago

@squeek502 yep, you're right that I missed your comment in the luvi repo. This is the exact same issue! I guess it's something in libuv that's causing the problem since I don't have luajit at all in this project.

I tried -target native-native-musl and I get the same error though. Let me push my code and see if I'm doing it right...

creationix commented 4 years ago

https://github.com/creationix/polluv/blob/9ccc3c952ffb18b09148f22e8346acc9667b1097/Makefile#L2-L29

marler8997 commented 4 years ago

Just a thought, maybe fcntl64 is versioned? I was recently working with libefivar and they version their symbols using -Wl,--version-script=FILE, not sure exactly how versioning symbols works but could be a potential explanation for this error.

daurnimator commented 4 years ago

As in #6036, could you try using a newer glibc version as part of your target?

aniljava commented 4 years ago

Using c library triggers this errors, either as built.zig or in build-exe

/ws/projects/zig/sqlite :: # zig build
Build Dependencies... lld: error: /usr/lib/libsqlite3.so: undefined reference to fcntl64

/ws/projects/zig/sqlite :: # ldd --version
ldd (Ubuntu GLIBC 2.31-0ubuntu9) 2.31

exe.linkSystemLibrary("c");

/ws/projects/zig/sqlite :: # zig build-exe src/main.zig  -lsqlite3 -lc
Build Dependencies... lld: error: /usr/lib/libsqlite3.so: undefined reference to fcntl64

main.zig

const std = @import("std");
const sqlite = @cImport(@cInclude("sqlite3.h"));

pub fn main() anyerror!void {
    var db: ?*sqlite.sqlite3 = undefined;

}

addition to init-exe generated build.zig

const exe = b.addExecutable("sqlite", "src/main.zig");

exe.linkSystemLibrary("c");
exe.linkSystemLibrary("sqlite3");
zhaozg commented 3 years ago

cross build libuv for linux on macos, failed with

[100%] Linking C executable luvi
ld.lld: error: undefined symbol: fcntl64
>>> referenced by amalgamation.c
>>>               CMakeFiles/luvi.dir/custom/sqlitext/amalgamation.c.o:(aSyscall)
>>> referenced by core.c
>>>               core.c.o:(uv__nonblock_fcntl) in archive luv.dir/deps/libuv/libuv_a.a
>>> referenced by core.c
>>>               core.c.o:(uv__nonblock_fcntl) in archive luv.dir/deps/libuv/libuv_a.a
>>> referenced 5 more times
>>> did you mean: fcntl64@GLIBC_2.28
>>> defined in: /Users/zhaozg/.cache/zig/o/2723a939ae2a5ffa91d29e2389d18ffc/libc.so.6
error: LLDReportedFailure
make[6]: *** [luvi] Error 1
make[5]: *** [CMakeFiles/luvi.dir/all] Error 2
make[4]: *** [all] Error 2
make[3]: *** [luvi-prefix/src/luvi-stamp/luvi-build] Error 2
make[2]: *** [CMakeFiles/luvi.dir/all] Error 2
make[1]: *** [all] Error 2
make: *** [luvi] Error 2
zhaozg commented 3 years ago

After read how-to-force-linkage-to-older-libc-fcntl-instead-of-fcntl64, I found an alternative way to build libuv with zig cc.

make a fcntl.map file

GLIBC_2.2.5 {
   fcntl;
};

And update luv/deps/libuv/src/unix/internal.h, and add a line asm (".symver fcntl64, fcntl@GLIBC_2.2.5"); before #endif /* UV_UNIX_INTERNAL_H_ */

use CC="zig cc -target x86_64-linux-gnu.2.17 -Wl,--version-script,path_of_fcntl.map" ~or "CC="zig cc -target aarch64-linux-gnu.2.17 -Wl,--version-script,path_of_fcntl.map"`~ to build libuv.

If x86_64-linux-gnu version below 2.17, maybe need more glibc api map, and I have not test that.

aarch64-linux-gnu not pass, because has no fcntl@GLIBC_2.2.5

harryhaaren commented 3 years ago

I've just bumped into this issue too, when compiling a native C project that extensively uses linker scripts for both visibility and versioning of symbols. A quick web search brings me to this issue, root cause was the undefined symbol: fcntl64, and suggests did you mean fcntl64@GLIB_2.28 (from the Zig musl build cache for this architecture).

nektro commented 3 years ago

can confirm this works if you add -target native-native-gnu.2.28 since fcntl64 was removed in glibc 2.29+

the main.c I used can be found here https://nikhilm.github.io/uvbook/basics.html#hello-world

$ zig version
0.8.0-dev.2591+4b69bd61e

$ uname -a
Linux Meghans-PBP 5.7.0-2-pinebookpro-arm64 #1 SMP PREEMPT Sat Apr 24 11:16:25 UTC 2021 aarch64 GNU/Linux

$ zigmod fetch
fetch: libuv: git: https://github.com/libuv/libuv

$ zig build -Dtarget=native-native-gnu.2.28

$ ./zig-out/bin/zig-libuv 
Now quitting.

edit: zig.mod: https://clbin.com/ITDC2 build.zig: https://zigbin.io/0a334f

motiejus commented 3 years ago

I have the same problem building sqlite3 amalgamation (3.36.0) for glibc 2.27 or older:

~/sqlite-amalgamation-3360000 $ zig cc --target=x86_64-linux-gnu.2.24 shell.c sqlite3.c -lpthread -ldl -lm -o sqlite.2.24
ld.lld: error: undefined symbol: fcntl64
>>> referenced by sqlite3.c
>>>               /home/motiejus/.cache/zig/o/b0eefed440b6d330af020a2a209205de/sqlite3.o:(aSyscall)
>>> did you mean: fcntl64@GLIBC_2.28
>>> defined in: /home/motiejus/.cache/zig/o/d7adab72898642dac7322f4d250dbd1a/libc.so.6

I cannot use older glibc version, because some production hosts run 2.24; I also cannot use the musl target, because some applications expose NSS symbols, thus must be linked against glibc (vaguely mentioned in https://eng.uber.com/hadoop-container-blog/).

Suggestion by @zhaozg (above) works! But ... is there a way to pass the asm line in a cflag directive instead of patching the source? In our case, sqlite is a dependency of a dependency, so even creating a patch is non-trivial to begin with, let alone maintain it during upgrades.

motiejus commented 3 years ago

Following @zhaozg 's suggestion I found a slightly different approach that does not require changing the source files:

fcntl.h

#ifdef __ASSEMBLER__
.symver fcntl64, fcntl@GLIBC_2.2.5
#else
__asm__(".symver fcntl64, fcntl@GLIBC_2.2.5");
#endif

fcntl.map

GLIBC_2.2.5 {
   fcntl;
};

Compile command:

zig cc --target=x86_64-linux-gnu.2.24 shell.c sqlite3.c -lpthread -ldl -lm -Wl,--version-script,fcntl.map -include fcntl.h -o sqlite.2.24
motiejus commented 3 years ago

I created https://github.com/ziglang/zig/issues/9485, which captures the problem with a very small C file.

ratfactor commented 3 years ago

Also ran into this compiling https://github.com/vrischmann/zig-sqlite with the included SQLite 3.35.5 amalgam.

Both target suggestions above worked for me:

zig build run -Dtarget=native-native-musl

and

zig build -Dtarget=native-native-gnu.2.28

The error (might help someone else searching for this issue):

ld.lld: error: undefined symbol: fcntl64
>>> referenced by sqlite3.c
>>>               /home/dave/sync/proj/zig/shoebox6/zig-cache/o/4089122d496bd76a6e71a1ea3f7f7ee6/sqlite3.o:(aSyscall)
>>> did you mean: fcntl64@GLIBC_2.28
>>> defined in: /home/dave/.cache/zig/o/7fec61c5e150add8cc9a2bc712cfb30a/libc.so.6
error: LLDReportedFailure
bradclawsie commented 3 years ago

I stumbled upon this issue while trying to use the sqlite library. To add to the stopgap solutions provided above, here are some snippets for build.zig:

let's say there is a library state.zig written with sqlite support...to build:

const state_lib = b.addStaticLibrary("state", "lib/state.zig");
state_lib.setBuildMode(mode);
deps.addAllTo(state_lib);
state_lib.setTarget(std.build.Target{ .glibc_version = std.build.Target.SemVer{ .major = 2, .minor = 28 } });
state_lib.install();
var state_pkg = std.build.Pkg{ .name = state_lib.name, .path = std.build.FileSource{ .path = state_lib.root_src.?.path }, .dependencies = state_lib.packages.items };

and for tests:

var state_tests = b.addTest("lib/state.zig");
state_tests.setBuildMode(mode);
deps.addAllTo(state_tests);
state_tests.setTarget(std.build.Target{ .glibc_version = std.build.Target.SemVer{ .major = 2, .minor = 28 } });
state_tests.addPackage(state_pkg);

maybe these snippets help someone until a more automatic solution arrives...

andrewrk commented 2 years ago

Closing as a duplicate of #9485 since that one has a minimal reproduction test case.

motiejus commented 1 year ago

Note to followers of this issue: fcntl64 and a few more functions got resolved in #15101. Try compiling your stuff now. :)

chee-z1 commented 1 year ago

I had the same problem using raylib.

"C:\Program Files\zig\zig.exe" run C:/Users/userName/IdeaProjects/new_/main.zig
error: lld-link: undefined symbol: InitWindow
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:18
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: SetTargetFPS
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:19
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: CloseWindow
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:20
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: WindowShouldClose
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:21
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: BeginDrawing
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:22
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: ClearBackground
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:24
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: DrawText
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:25
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)
error: lld-link: undefined symbol: EndDrawing
    note: referenced by C:\Users\userName\IdeaProjects\new_\main.zig:23
    note:               C:\Users\userName\AppData\Local\zig\o\f59599752f0cead73359b7fdc6eb46c9\main.exe.obj:(main.main)