zig icon indicating copy to clipboard operation
zig copied to clipboard

zig build from source error in MacOS

Open i11010520 opened this issue 1 year ago • 21 comments

Zig Version

zig master, the latest commit: f2bf6c1b11702179329a4693cea429d550f519e1

Steps to Reproduce and Observed Behavior

PATH> zig/build: cmake .. -DZIG_STATIC_LLVM=on -DZIG_STATIC_ZLIB=on -DCMAKE_PREFIX_PATH="$(brew --prefix llvm@18);$(brew --prefix zstd);" make ERROR ld: library not found for -lcurses

then, brew install ncurses cmake .. -DZIG_STATIC_LLVM=on -DZIG_STATIC_ZLIB=on -DCMAKE_PREFIX_PATH="$(brew --prefix llvm@18);$(brew --prefix zstd);$(brew --prefix ncurses);" make ERROR ld: library not found for -lzstd

Furthermore, -DZIG_STATIC_ZLIB is required or else there will be ERROR: ld: library not found for -lz

Expected Behavior

zig build OK.

i11010520 avatar Jul 26 '24 09:07 i11010520

then if I STATIC link all zlib, zstd, and curses: cmake .. -DZIG_STATIC_LLVM=on -DZIG_STATIC_ZLIB=on -DZIG_STATIC_ZSTD=on -DZIG_STATIC_CURSES=on -DCMAKE_PREFIX_PATH="$(brew --prefix llvm@18);$(brew --prefix zlib);$(brew --prefix zstd);$(brew --prefix ncurses);$(brew --prefix libxml2);" ERROR throws ld: library not found for -lxml2

i11010520 avatar Jul 26 '24 12:07 i11010520

Maybe the errors originate from devbox shell environment. I'll keep checking. Close it for the moment.

i11010520 avatar Jul 27 '24 08:07 i11010520

I'm having library not found for -lzstd I have zstd installed by brew and passing $(brew --prefix zstd) as well. There is clearly some problem on Mac.

RokibulUddin avatar Jul 29 '24 10:07 RokibulUddin

I found the following instructions: There seems to be a problem with homebrew llvm and zstd. The short way: Do this (only once):ln -s /opt/homebrew/opt/zstd/lib/libzstd.a /opt/homebrew/opt/llvm/lib/libzstd.a Then, to build: load zig: gh repo clone ziglang/zig Make build directory: cd zig; mkdir build; cd build Prepare build: cmake .. -DZIG_STATIC_LLVM=on -DZIG_NO_LIB=ON -DCMAKE_BUILD_TYPE=Release Build and install: make -j22; make install # Change -jn according to your machine Expect "some" warnings while building...

Check: cd stage3/bin Check binary: ./zig version Check existence of lib: ./zig env

For me, this did not work with gcc, only with clang.

mofrisch avatar Jul 29 '24 13:07 mofrisch

It is obviously as easy as just putting the link. Afterwards a standard build works.

mofrisch avatar Jul 29 '24 17:07 mofrisch

Just ran into this as well on a fresh arm mac install. I had to add -DZIG_STATIC_ZLIB=ON -DZIG_STATIC_ZSTD=ON to the cmake command

cryptocode avatar Jul 31 '24 09:07 cryptocode

My working build command is cmake .. -DZIG_STATIC_LLVM=on -DZIG_STATIC_ZSTD=on -DZIG_NO_LIB=on -DCMAKE_BUILD_TYPE=Release -GNinja

But I've no idea why does it still work without -DCMAKE_PREFIX_PATH.

i11010520 avatar Aug 02 '24 01:08 i11010520

Looks like adding -DZIG_STATIC_ZLIB=ON -DZIG_STATIC_ZSTD=ON help build latest master (ca012e5b69) for me too, full command:

cmake .. -DZIG_STATIC_LLVM=ON -DCMAKE_SYSTEM_PREFIX_PATH="$(brew --prefix zstd);$(brew --prefix llvm@18)" -DCMAKE_BUILD_TYPE=Release -DZIG_STATIC_ZLIB=ON -DZIG_STATIC_ZSTD=ON

kpy3 avatar Aug 08 '24 15:08 kpy3

I tried this latest invocation, and am still getting a CMake failure, the relevant part being:

    /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc  -arch arm64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk -mmacosx-version-min=12.6 -Wl,-search_paths_first -Wl,-headerpad_max_install_names -L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib -lunwind-L/opt/homebrew/opt/llvm/lib -L/usr/local/opt/zstd/lib  CMakeFiles/cmTC_5a369.dir/testCCompiler.c.o -o cmTC_5a369
    ld: library not found for -lunwind-L/opt/homebrew/opt/llvm/lib
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

For the record:

$ ls /opt/homebrew/opt/llvm/lib/libunwind

/opt/homebrew/opt/llvm/lib/libunwind.1.0.dylib  /opt/homebrew/opt/llvm/lib/libunwind.a
/opt/homebrew/opt/llvm/lib/libunwind.1.dylib    /opt/homebrew/opt/llvm/lib/libunwind.dylib

I was able to build Zig about three weeks ago, so whatever this is, it's recent.

mnemnion avatar Aug 09 '24 00:08 mnemnion

There is a space missing between -lunwind and -L/opt/homebrew/opt/llvm/lib. You could look at the invocation of the command.

mofrisch avatar Aug 09 '24 14:08 mofrisch

That's a good catch.

In trying to troubleshoot this, I did a diff of ./CMakeLists.txt to see if I could spot the commit which introduced this error, and y'know, that might be the culprit.

diff --git a/CMakeLists.txt b/CMakeLists.txt
index f99e59e41f..6bd5f24a97 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -945,6 +945,11 @@ set(ZIG_BUILD_ARGS
   -Dno-langref
 )

+option(ZIG_EXTRA_BUILD_ARGS "Extra zig build args")
+if(ZIG_EXTRA_BUILD_ARGS)
+  list(APPEND ZIG_BUILD_ARGS ${ZIG_EXTRA_BUILD_ARGS})
+endif()
+
 if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
   list(APPEND ZIG_BUILD_ARGS -Doptimize=Debug)
 elseif("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")

Except that deleting that from the file doesn't fix the build, so ah well, probably not. But it does look related, just eyeballing it.

As another observation, I ended up symlinking /usr/local/opt/zstd/lib, because the $(brew --prefix zstd) part of the build string, which produces /opt/homebrew/opt/zstd, does nothing, CMake tries to use the /opt/local location anyway. As random symlinks go, it's fairly harmless, but as it didn't fix the build anyway, I'd just as soon remove it.

mnemnion avatar Aug 09 '24 15:08 mnemnion

I suppose it has nothing to do with the repository, since I can build it fine. Maybe something got muddled up in your local copy. I would try to remove the build directory and to create again. And, though not absolutely necessary, I would recommend using clang 18, not the one from your XCode install. Then: cd build cmake .. -DZIG_STATIC_LLVM=ON -DCMAKE_BUILD_TYPE=Release make If this doesn't work, it might be an option to clone the repository again.

mofrisch avatar Aug 09 '24 16:08 mofrisch

@mofrisch have you, yourself, done a build from a clean repo clone?

If not, it's at least equally likely that your local state is preserving something which is no longer available from a clean build.

Because I have tried it from a fresh clone, and it didn't work. I didn't use the exact invocation you listed there, but rather, the one from the Wiki. I suppose I could try again with that specific cmake invocation, and see what happens.

mnemnion avatar Aug 09 '24 17:08 mnemnion

No, that specific cmake invocation doesn't work from a fresh repository also.

I'm not opposed to figuring out how to use clang 18 to build Zig, but I don't think it will fix the problem in the build script. Which is the string -lunwind-L/opt/homebrew/opt/llvm/lib, since that's just wrong, and a different version of clang isn't going to parse it any differently.

mnemnion avatar Aug 09 '24 17:08 mnemnion

See here. After brew install llvm clang obey this:

To use the bundled libc++ please add the following LDFLAGS: LDFLAGS="-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib -lunwind"

llvm is keg-only, which means it was not symlinked into /opt/homebrew, because macOS already provides this software and installing another version in parallel can cause all kinds of trouble.

If you need to have llvm first in your PATH, run: echo 'export PATH="/opt/homebrew/opt/llvm/bin:$PATH"' >> ~/.zshrc

For compilers to find llvm you may need to set: export LDFLAGS="-L/opt/homebrew/opt/llvm/lib" export CPPFLAGS="-I/opt/homebrew/opt/llvm/include"

mofrisch avatar Aug 09 '24 18:08 mofrisch

To use the bundled libc++ please add the following LDFLAGS: LDFLAGS="-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib -lunwind"

I'm glad you mentioned this, because it turned out that the typo was, in fact, in LDFLAGs. To my chagrin, this almost surely happened from hitting Cmd-S out of muscle memory, while editing the .zshrc. Which in vim, doesn't save your file, it deletes one character. A space in this case.

I'm trying the build now, and since I have managed it before, the outlook is good. Thanks for the prompt!

mnemnion avatar Aug 09 '24 20:08 mnemnion

Yep, that went fine.

What I'm getting from this thread is that the build instructions for MacOS + Homebrew just aren't complete. I don't think it's a case where what's on the Wiki is explicitly intended to work as written, as in, there's something in the build script which needs to be changed so that those exact instructions will work.

Rather, it appears that there's just a bit more to it, which could be added to the Wiki. Looking back at the help thread on Discord which let me build it the first time, it's a consistent list with things brought up in this thread:

  • Need to install llvm: brew install llvm.
  • LLVM is "keg-only", so you need to add some lines to LDFLAGS:
-L/opt/homebrew/opt/llvm/lib/c++ -L/opt/homebrew/opt/llvm/lib -lunwind -L/opt/homebrew/opt/llvm/lib -L/usr/local/opt/zstd/lib
  • And CPPFLAGS:
-I/opt/homebrew/opt/llvm/include -I/usr/local/opt/zstd/include
  • There's something weird going on with zstd, this one might be fixable in the build script but if not, and in the meantime:
ln -s /opt/homebrew/opt/zstd/lib/libzstd.a /opt/homebrew/opt/llvm/lib/libzstd.a
  • After that, it's just the build script that's on the Wiki already.
mkdir build
cd build
cmake .. -DZIG_STATIC_LLVM=ON -DCMAKE_PREFIX_PATH="$(brew --prefix llvm@18);$(brew --prefix zstd)"
make install

I wanted to get it all in one place as a draft, so others can sanity check this. Is anything else necessary? That's all I remember doing but I didn't take detailed notes or anything. Are some of these steps optional?

I'm particularly wondering if there's a way to eliminate the symlink, everything else here is perfectly reasonable but that feels like a kludge to me.

Once we get those questions sorted out, the missing steps can just be added to the Wiki, and we can close this issue.

mnemnion avatar Aug 09 '24 22:08 mnemnion

😀 Makes absolute sense. For me, it works without --DCMAKE_PREFIX_PATH. @mnemnion Could you check on your system? Should add -DCMAKE_BUILD_TYPE=Release anyway, because default will be a debug build.

I suppose, that zstd is missing is a brew llvm thing, I will try with a source build of llvm later.

mofrisch avatar Aug 10 '24 11:08 mofrisch

Right now, on apple platform, we have to invoke cmake with -DCMAKE_PREFIX_PATH to find some needed libs. This could be automated in CMakeLists.txt.

With these changes the following will work, which will probably be what the user expects:

mkdir build
cd build
cmake ..
make

CMakeLists.txt

Add:

if(APPLE)
  execute_process(
        COMMAND brew --prefix       # get the brew prefix
        RESULT_VARIABLE NO_BREW     # if it is 0, brew is installed
        OUTPUT_VARIABLE BREW_PREFIX
        OUTPUT_STRIP_TRAILING_WHITESPACE
    ) 
    if(NOT NO_BREW)
      list(APPEND CMAKE_PREFIX_PATH "${BREW_PREFIX}")               # add the brew prefix to the cmake prefix path
      list(APPEND CMAKE_PREFIX_PATH "${BREW_PREFIX}/opt/ncurses")   # add the ncurses path to the cmake prefix path
      list(APPEND CMAKE_PREFIX_PATH "${BREW_PREFIX}/opt/llvm")      # add the llvm path to the cmake prefix path
    endif()
endif()

The PATHS for ncurses can be removed.

Could someone review this change and if applicable make it a proposal?

mofrisch avatar Aug 11 '24 11:08 mofrisch

It does work without the prefixes for me @mofrisch.

Unfortunately, with this kind of thing, it's tough to find the 'minimal set', because it involves various persistent changes to the user setup. But I distinctly recall the instructions from the Wiki not working without adding those LLDFLAGS and CPPFLAGS.

That wasn't something I got from the Discord, there were install notes which came with brew install llvm about what would be involved in using it with XCode cc tooling.

I should have some time this afternoon, or tomorrow evening, to reset everything as far as I can: un-simlink libzstd, brew uninstall llvm, remove the link flags, trash the Zig repo, and then try the new instructions and see if I can get away with leaving any of it out.

What else, in terms of a clean slate? Making a new user won't make a difference, because all of this is stored in the common parts of the file system. I don't want to trash Zig's global cache, but there should be no harm in moving it, which should have the same effect.

mnemnion avatar Aug 11 '24 14:08 mnemnion

With my approach, I expect, the following has been executed:

brew install llvm
brew install ncurses
brew install zstd

mofrisch avatar Aug 11 '24 20:08 mofrisch

Have switched to nix.

i11010520 avatar Mar 24 '25 23:03 i11010520