Skip to content

zig 0.14.0: re-enable static llvm for macos only #210173

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

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Formula/z/zig.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,13 @@ def install
else Hardware.oldest_cpu
end

args = ["-DZIG_SHARED_LLVM=ON"]
# Workaround for https://github.com/Homebrew/homebrew-core/issues/210073
# Suggested by https://github.com/Homebrew/homebrew-core/pull/210107#issuecomment-2706566289
if OS.linux?
args = ["-DZIG_SHARED_LLVM=ON"]
elsif OS.mac?
args = ["-DZIG_STATIC_LLVM=ON"]
Copy link
Member

@carlocab carlocab Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This likely just silences the warnings, and doesn't fix the underlying issue. Note that we still have dynamic linkage to LLD:

==> brew linkage --cached zig
System libraries:
  /usr/lib/libSystem.B.dylib
  /usr/lib/libxml2.2.dylib
  /usr/lib/libz.1.dylib
Homebrew libraries:
  /opt/homebrew/opt/lld/lib/liblldCOFF.dylib (lld)
  /opt/homebrew/opt/lld/lib/liblldCommon.dylib (lld)
  /opt/homebrew/opt/lld/lib/liblldELF.dylib (lld)
  /opt/homebrew/opt/lld/lib/liblldMachO.dylib (lld)
  /opt/homebrew/opt/lld/lib/liblldMinGW.dylib (lld)
  /opt/homebrew/opt/lld/lib/liblldWasm.dylib (lld)
  /opt/homebrew/opt/z3/lib/libz3.4.14.dylib (z3)
  /opt/homebrew/opt/zstd/lib/libzstd.1.dylib (zstd)

And LLD itself links dynamically to libLLVM and libc++:

❯ brew linkage lld
System libraries:
  /usr/lib/libSystem.B.dylib
  /usr/lib/libc++.1.dylib
  /usr/lib/libz.1.dylib
Homebrew libraries:
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldCOFF.dylib (lld)
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldCommon.dylib (lld)
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldELF.dylib (lld)
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldMachO.dylib (lld)
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldMinGW.dylib (lld)
  /opt/homebrew/Cellar/lld/19.1.7/lib/liblldWasm.dylib (lld)
  /opt/homebrew/opt/llvm/lib/libLLVM.dylib (llvm)
  /opt/homebrew/opt/zstd/lib/libzstd.1.dylib (zstd)

So the problem of loading possibly conflicting versions of libc++ remains. To add to that, this also introduces the possibility of loading conflicting versions of libLLVM. One version is the one that is statically linked, and the other is the one loaded by LLD.

The only real fix here is to allow zig itself to link dynamically to the system libc++ instead of forcing linkage to a bundled static version.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, but as I have already specified this is only a workaround and, from some research I have done, this would seem to be a long-standing problem and not yet solved or at least made known to zig itself (https://ziggit.dev/t/linking-stage3-zig-dynamically-with-system-libc/5726).

I have also seen how Macports solves this problem and they too have implemented the same workaround:

# We need to link LLVM statically until a way is found to force zig to link the system libc++ dynamically.
configure.args-append -DZIG_STATIC_LLVM=ON

(https://github.com/macports/macports-ports/blob/master/lang/zig/Portfile)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would seem to be a long-standing problem and not yet solved or at least made known to zig itself

Can you report it to Zig then and see what their opinion is on the fix?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand the temptation to blindly follow what MacPorts does here, but their workaround is not applicable for us.

MacPorts almost certainly does not ship shared libraries for LLD, and so Zig can only link with the static versions. That makes using ZIG_STATIC_LLVM somewhat safe, because the static libraries will not load a different libLLVM or libc++.

However, we do not ship the LLD static libraries, and only ship the shared ones. As a consequence, using ZIG_STATIC_LLVM here will still result in your loading two different versions of libc++ (and possibly two different versions of libLLVM). This is not safe, and is exactly what the warning you're currently seeing is about.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would seem to be a long-standing problem and not yet solved or at least made known to zig itself

Can you report it to Zig then and see what their opinion is on the fix?

@SMillerDev I just reported to zig: ziglang/zig#23189.
Let's hope to get an answer as soon as possible but I don't think there will be a definitive answer given these discussions:
ziglang/zig#23127
ziglang/zig#20450

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's why, in general, we aren't putting a ton of energy into solving build system problems that we only have because of these dependencies that are going away ~soon.

Just want to add that I don't endorse this statement. Zig 0.14.0 has these build dependencies so of course we provide support for building Zig 0.14.0 from source with these dependencies.

Copy link
Member

@cho-m cho-m Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggesting to use the system-provided libc++. My suggestion is to use system-provided libc++ for Zig

When I looked into this, build.zig didn't allow linking to system libc++ on macOS (ziglang/zig#20450 (comment)).

mod.link_libcpp = true (and mod.linkSystemLibrary("c++", .{});) link the bundled libc++.a, which is visible in logs when building with -DZIG_EXTRA_BUILD_ARGS=--verbose;--verbose-link, e.g. (with some flags collapsed into "..." for readability)

zig ld -dynamic ... /private/tmp/zig-20250310-85901-s26rpz/zig-0.14.0/.brew_home/.cache/zig/o/cca824b2aab7464b1756af7de768c750/libc++abi.a /private/tmp/zig-20250310-85901-s26rpz/zig-0.14.0/.brew_home/.cache/zig/o/99e1bde16b10b2d011b5699a7950446d/libc++.a -lSystem /private/tmp/zig-20250310-85901-s26rpz/zig-0.14.0/.brew_home/.cache/zig/o/97f38acba6b985c89ced83ebbb2c47bc/libcompiler_rt.a

A quick hack I tried was patching mod.link_libcpp = true with something like test/link/macho.zig1 but this won't be correct if LLVM was linked to another libc++:

const sdk = std.zig.system.darwin.getSdk(b.allocator, target) orelse @panic("TODO");
mod.addObjectFile(.{ .cwd_relative = b.pathJoin(&.{ sdk, "/usr/lib/libc++.tbd" }) });
zig ld -dynamic ... -l /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/libc++.tbd -F /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks -lSystem /private/tmp/zig-20250310-87312-6ve6bc/zig-0.14.0/.brew_home/.cache/zig/o/517cf93ff71df00c42dced7336ddd8e2/libcompiler_rt.a
❯ otool -L /opt/homebrew/opt/zig/bin/zig | grep libc
	/opt/homebrew/opt/llvm/lib/libclang-cpp.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 1800.105.0)
❯ zig version
0.14.0

Footnotes

  1. https://github.com/ziglang/zig/blob/master/test/link/macho.zig#L886

Copy link
Member

@carlocab carlocab Mar 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My suggestion is to use system-provided libc++ for Zig, LLD, Clang, and LLVM.

We'd love to do that, and that's exactly what we've been trying to do in the first place. Unfortunately there does not appear to be a way to tell Zig to use the system-provided libc++ without hacking up the source.

See also ziglang/zig#23189.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please take this patch from @mikdusan for a spin with shared LLVM/LLD: ziglang/zig#23264

Would be nice if someone could also ping the relevant folks from MacPorts.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks; have opened #211129. Have also left a link to ziglang/zig#23264 at ziglang/zig#20450 and macports/macports-ports#24430 for the MacPorts folks.

end
args << "-DZIG_TARGET_MCPU=#{cpu}" if build.bottle?

system "cmake", "-S", ".", "-B", "build", *args, *std_cmake_args
Expand Down
Loading