zig icon indicating copy to clipboard operation
zig copied to clipboard

x86_64-macos incorrectly includes macOS libs/headers when cross compiling to Linux

Open emidoots opened this issue 3 years ago • 5 comments

Zig Version

0.10.0-dev.1107+7deadf430

Steps to Reproduce

src/main.zig:

const c = @cImport({
    @cInclude("X11/Xlib.h");
});
pub fn main() void {
    _ = c.XFree(null);
}

build.zig:

const std = @import("std");

pub fn build(b: *std.build.Builder) void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();

    const exe = b.addExecutable("tmp", "src/main.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.install();
    exe.linkLibC();
    exe.linkSystemLibrary("X11");
}
brew install libx11
zig build -Dtarget=x86_64-linux-gnu --verbose 

May only reproduce on x86 mac.

Expected Behavior

Zig should not attempt to use macOS headers/libraries when cross compiling to Linux.

Actual Behavior

Zig attempts to link a macOS library, and includes headers likely intended for macOS only, when building a binary for Linux:

/usr/local/bin/zig build-exe /Users/slimsag/Desktop/tmp/src/main.zig -lc -lX11 --cache-dir /Users/slimsag/Desktop/tmp/zig-cache --global-cache-dir /Users/slimsag/.cache/zig --name tmp -target x86_64-linux-gnu -mcpu x86_64 -I /usr/local/Cellar/libx11/1.7.3.1/include -I /usr/local/Cellar/libxcb/1.14_2/include -I /usr/local/Cellar/libxau/1.0.9/include -I /usr/local/Cellar/libxdmcp/1.1.3/include -I /usr/local/Cellar/xorgproto/2021.5/include -L /usr/local/Cellar/libx11/1.7.3.1/lib --enable-cache 
ld.lld: error: undefined symbol: XFree
>>> referenced by main.zig:5
>>>               /Users/slimsag/Desktop/tmp/zig-cache/o/01c3b52bbbabfbd0f8208918be0f4f24/tmp.o:(main.0)
>>> did you mean: _XFree
>>> defined in: /usr/local/Cellar/libx11/1.7.3.1/lib/libX11.a
error: LLDReportedFailure
tmp...The following command exited with error code 1:
/usr/local/bin/zig build-exe /Users/slimsag/Desktop/tmp/src/main.zig -lc -lX11 --cache-dir /Users/slimsag/Desktop/tmp/zig-cache --global-cache-dir /Users/slimsag/.cache/zig --name tmp -target x86_64-linux-gnu -mcpu x86_64 -I /usr/local/Cellar/libx11/1.7.3.1/include -I /usr/local/Cellar/libxcb/1.14_2/include -I /usr/local/Cellar/libxau/1.0.9/include -I /usr/local/Cellar/libxdmcp/1.1.3/include -I /usr/local/Cellar/xorgproto/2021.5/include -L /usr/local/Cellar/libx11/1.7.3.1/lib --enable-cache 
error: the following build command failed with exit code 1:
/Users/slimsag/Desktop/tmp/zig-cache/o/2c392a7290db5827809b38e1a5c90300/build /usr/local/bin/zig /Users/slimsag/Desktop/tmp /Users/slimsag/Desktop/tmp/zig-cache /Users/slimsag/.cache/zig -Dtarget=x86_64-linux-gnu --verbose

emidoots avatar Mar 06 '22 03:03 emidoots

I should also note, we have regressed here slightly in 6f42876e74831b7f9cecf5a863634df920c52b98 (although that change is not to blame for the issue here)

x86_64-macos -> x86_64-linux with Mach engine worked prior to that commit, but not after.

The reason is because despite this issue, Zig would previously find the libX11.so provided via a sysroot. However, with that commit and preference for static libs when available, the wrong-OS /usr/local/Cellar/libx11/1.7.3.1/lib/libX11.a is found first and so cross compilation now fails.

emidoots avatar Mar 06 '22 08:03 emidoots

@slimsag I'm a little confused by the title of the issue: it looks to me like the issue is potentially linking in the wrong archive but not the header files? Now back to the linker finding the wrong archive: so you're saying that LLD is finding libX11.a which includes MachO objects, and fails instead of carrying on with the search? If that's the case, this sounds like LLD issue to me as otherwise, how can we tell the linker what to search for when utilising the system libs flags such as -L. -lX11 or something?

kubkon avatar Aug 16 '22 20:08 kubkon

Pay close attention to the zig build-exe invocation:

/usr/local/bin/zig build-exe [...] -I /usr/local/Cellar/libx11/1.7.3.1/include -I /usr/local/Cellar/libxcb/1.14_2/include -I /usr/local/Cellar/libxau/1.0.9/include -I /usr/local/Cellar/libxdmcp/1.1.3/include -I /usr/local/Cellar/xorgproto/2021.5/include -L /usr/local/Cellar/libx11/1.7.3.1/lib [...] 

I don't know for sure, but it seems to me that if you're targeting Linux from a macOS host that including headers -I and libraries -L from the brew cellar path would always be wrong, no? After all, they would be for the host OS/arch, not the target.

emidoots avatar Aug 17 '22 02:08 emidoots

Agreed. Did you check why they end up in your search path when targeting linux then? I am asking since we don't add those automatically in zig, or shouldn't. The only automatic search paths should be those pointing at the SDK and only if not cross-compiling.

kubkon avatar Aug 17 '22 05:08 kubkon

I checked on a recent Zig version, and following the reproduction steps in the issue description I can still reproduce this in a small example:

zig build -Dtarget=x86_64-linux-gnu --verbose /Users/slimsag/Desktop/zig/build/stage3/bin/zig build-exe /Users/slimsag/Desktop/zigissue/src/main.zig -lc -I/opt/homebrew/Cellar/libx11/1.8.1/include -I/opt/homebrew/Cellar/libxcb/1.15/include -I/opt/homebrew/Cellar/libxau/1.0.9/include -I/opt/homebrew/Cellar/libxdmcp/1.1.3/include -I/opt/homebrew/Cellar/xorgproto/2022.2/include -L/opt/homebrew/Cellar/libx11/1.8.1/lib -lX11 --cache-dir /Users/slimsag/Desktop/zigissue/zig-cache --global-cache-dir /Users/slimsag/.cache/zig --name tmp -target x86_64-linux-gnu -mcpu x86_64 --enable-cache

It seems notable to me that this is the zig build-exe invocation: zig build must have constructed this command invocation on it's own, so this must be in the realm of lib/std/build.zig somewhere I imagine.

If I get some extra time, I'll try to identify further. But seems clear this is a bug in zig build

emidoots avatar Aug 25 '22 02:08 emidoots