ziglang / zig

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

zig build-lib does not allow linking to a C program #14416

Open perillo opened 1 year ago

perillo commented 1 year ago

In the Zig Language Reference there are two example of linking a Zig library to a C program in the "Exporting a C Library" and "Mixing Object Files" sections. Both examples fail.

These are the issues I found:

Thanks.

kassane commented 1 year ago

In the Zig Language Reference there are two example of linking a Zig library to a C program in the "Exporting a C Library" and "Mixing Object Files" sections. Both examples fail.

These are the issues I found:

Static linking using a C compiler fails

Using the mathtest.zig example

zig build-lib -femit-h mathtest.zig

gcc -o test -static -I $(zig env | jq -r .lib_dir) test.c -L . -lmathtest
./test
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o): in function `debug.readElfDebugInfo':
/home/manlio/.local/share/sdk/zig/master/lib/std/debug.zig:939: undefined reference to `__zig_probe_stack'
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o): in function `fs.Dir.openFile':
/home/manlio/.local/share/sdk/zig/master/lib/std/fs.zig:1099: undefined reference to `__zig_probe_stack'
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o): in function `debug.printLineFromFileAnyOs__anon_5459':
/home/manlio/.local/share/sdk/zig/master/lib/std/debug.zig:1164: undefined reference to `__zig_probe_stack'
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o): in function `dwarf.DwarfInfo.getLineNumberInfo':
/home/manlio/.local/share/sdk/zig/master/lib/std/dwarf.zig:1090: undefined reference to `__zig_probe_stack'
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o): in function `debug.panicExtra__anon_5748':
/home/manlio/.local/share/sdk/zig/master/lib/std/debug.zig:297: undefined reference to `__zig_probe_stack'
/usr/bin/ld: ./libmathtest.a(./libmathtest.a.o):/home/manlio/.local/share/sdk/zig/master/lib/std/debug.zig:297: more undefined references to `__zig_probe_stack' follow
collect2: error: ld returned 1 exit status

You have built the library in debug mode. If you build in releaseFast or small mode the error will not occur, or add -fcompiler-rt in build-lib. https://github.com/ziglang/zig/issues/6817#issuecomment-736129115

perillo commented 1 year ago

You have built the library in debug mode. If you build in releaseFast or small mode the error will not occur, or add -fcompiler-rt in build-lib. #6817 (comment)

Thanks.

kubkon commented 1 year ago

Fixed in https://github.com/ziglang/zig/pull/14644

kubkon commented 1 year ago

Scratch my last comment. This issue goes away if you explicitly pass -fcompiler-rt. Whether this should be automatic I'll leave to @andrewrk, so reopening.

perillo commented 1 year ago

Scratch my last comment. This issue goes away if you explicitly pass -fcompiler-rt. Whether this should be automatic I'll leave to @andrewrk, so reopening.

I converted the 3 different issues into separate tasks.

I'm not sure about the last task, since the (currently disabled) test-gen-h test suite expects clean C code: https://github.com/ziglang/zig/blob/master/test/gen_h.zig. A problem with this approach is name collision.

owend commented 1 year ago

Hello! With the latest versions of zig on MacOS (I tried version 0.10 and 0.11 and 0.12 and compiled from main/HEAD) this example now segfaults. Instead of opening a new bug I thought I would just add it here.

zig build-lib -femit-h mathtest.zig

➞  zig build-lib -femit-h  mathtest.zig
AST Lowering [519] target/aarch64.zig... thread 604505 panic: reached unreachable code
/Projects/zig/lib/std/debug.zig:342:14: 0x109fa4c7c in assert (zig)
    if (!ok) unreachable; // assertion failure
/Projects/zig/src/Module.zig:5343:19: 0x10a08705c in allocateNewDecl (zig)
            assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len);
/Projects/zig/src/Module.zig:3912:51: 0x10a22b0fc in semaFile (zig)
    const new_decl_index = try mod.allocateNewDecl(new_namespace_index, 0, null);
/Projects/zig/src/Module.zig:3888:24: 0x10a22ae81 in semaPkg (zig)
    return mod.semaFile(file);
/Projects/zig/src/Compilation.zig:3323:27: 0x10a25b19d in processOneJob (zig)
            module.semaPkg(pkg) catch |err| switch (err) {
/Projects/zig/src/Compilation.zig:3151:30: 0x10a0cddfe in performAllTheWork (zig)
            try processOneJob(comp, work_item, main_progress_node);
/Projects/zig/src/Compilation.zig:2058:31: 0x10a0c9929 in update (zig)
    try comp.performAllTheWork(main_progress_node);
/Projects/zig/src/main.zig:4098:24: 0x10a0fa161 in updateModule (zig)
        try comp.update(main_progress_node);

I added a debug print statement right before this block where the assertion is shown in Module.zig

        if (@intFromEnum(decl_index) >= mod_emit_h.allocated_emit_h.len) {
            try mod_emit_h.allocated_emit_h.append(gpa, .{});
            assert(@intFromEnum(decl_index) == mod_emit_h.allocated_emit_h.len);
        }

allocated_emit_h = segmented_list.SegmentedList(Module.EmitH,0) decl_index = Module.Decl.Index(0) allocated_emit_h.len = 0

It looks like the situation is (pseudo-code)

if 0 >= 0
    list.append
    assert 0 == 1

If the append succeeds, the assert always fails.

owend commented 3 months ago

Every once in a while I re-test this, and now the error message has changed:

thread 17539456 panic: regressed compiler feature: emit-h should hook into updateExports, not decl analysis, which is too early to know about @export calls

It looks like this check was added here: https://github.com/ziglang/zig/commit/00da182e68