A noob builds zig from source

I have tried 3 times in the past 3 months to build zig from source. I have yet to succeed. I have literally zero understanding of the C build tools. I know how to use the following tools:

  • git
  • github
  • zig
  • apt (I am on Debian 12)

My laptop has an Intel i7-8550U (8 cores) @ 4.000GHz and 16 GB of RAM, built in 2018.

Ill update this post as I go.

I am starting from the instructions at Building Zig From Source · ziglang/zig Wiki · GitHub.

Build log

Clone zig git repo (I clicked fork in github).

git clone git@github.com:kj4tmp/zig.git
cd zig

As you can see, I apparently also know how to use ssh, only took like 10 years to learn that one.

mkdir build
cd build
cmake ..
jeff@jeff-debian:~/repos/zig/build$ cmake ..
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring zig version 0.15.0
CMake Error at cmake/Findllvm.cmake:30 (message):
  expected LLVM 20.x but found 14.0.6 using /usr/bin/llvm-config

  expected LLVM 20.x but found 14.0.6 using /bin/llvm-config
Call Stack (most recent call first):
  CMakeLists.txt:135 (find_package)


-- Configuring incomplete, errors occurred!
See also "/home/jeff/repos/zig/build/CMakeFiles/CMakeOutput.log".

First obstacle, I do not have the right version of llvm, which I guess I could have checked first, if I knew how to do that.

I now google how to install llvm20 on debian. Which brings me here:

And there is an auto-install script:

For convenience there is an automatic installation script available that installs LLVM for you.
To install the latest stable version:

bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"


To install a specific version of LLVM:

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh <version number>

To install all apt.llvm.org packages at once:

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh <version number> all
# or
sudo ./llvm.sh all

cd ~/Downloads
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
...
Reading package lists... Done
+ PKG='clang-19 lldb-19 lld-19 clangd-19'
+ [[ 0 -eq 1 ]]
+ apt-get install -y clang-19 lldb-19 lld-19 clangd-19
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
clang-19 is already the newest version (1:19.1.7~++20250114103228+cd708029e0b2-1~exp1~20250114103334.78).
lldb-19 is already the newest version (1:19.1.7~++20250114103228+cd708029e0b2-1~exp1~20250114103334.78).
lld-19 is already the newest version (1:19.1.7~++20250114103228+cd708029e0b2-1~exp1~20250114103334.78).
clangd-19 is already the newest version (1:19.1.7~++20250114103228+cd708029e0b2-1~exp1~20250114103334.78).
...

Looks like it installed llvm 19, not helpful.

cd ~/Downloads
wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh 20
...
Setting up llvm-20-tools (1:20.1.2~++20250402124445+58df0ef89dd6-1~exp1~20250402004600.97) ...
Setting up libclang-cpp20 (1:20.1.2~++20250402124445+58df0ef89dd6-1~exp1~20250402004600.97) ...
...

Cool now I have llvm 20.

cd ~/repos/zig
cd build/
cmake ..
-- Configuring zig version 0.15.0
-- Found llvm: -lLLVM-20;-lrt;-ldl;-lm;/usr/lib/x86_64-linux-gnu/libz3.so;-lz;-lzstd;-lxml2 (Required is at least version "20")
-- Could NOT find clang (missing: CLANG_INCLUDE_DIRS) (Required is at least version "20")
-- Could NOT find lld (missing: LLD_LIBRARIES LLD_INCLUDE_DIRS) (Required is at least version "20")
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
/home/jeff/repos/zig/CLANG_INCLUDE_DIRS
   used as include directory in directory /home/jeff/repos/zig
/home/jeff/repos/zig/LLD_INCLUDE_DIRS
   used as include directory in directory /home/jeff/repos/zig

fml, what even is clang, lld

Looking through the LLVM install instructions again, maybe I need to “install all llvm packages” (wtf else would I want?!)

cd ~/Downloads
sudo ./llvm.sh 20 all
cd ~/repos/zig/build/
cmake ..
-- Configuring zig version 0.15.0
-- Found clang: /usr/lib/llvm-20/lib/libclang-cpp.so.20.1 (Required is at least version "20")
-- Could NOT find lld (missing: LLD_LIBRARIES LLD_INCLUDE_DIRS) (Required is at least version "20")
-- Configuring done
CMake Error: The following variables are used in this project, but they are set to NOTFOUND.
Please set them or make sure they are set and tested correctly in the CMake files:
/home/jeff/repos/zig/LLD_INCLUDE_DIRS
   used as include directory in directory /home/jeff/repos/zig

-- Generating done
CMake Generate step failed.  Build files cannot be regenerated correctly.

Ok I now have clang 20, but not lld.
LLD is “The LLVM Linker”, yet it is not installed?

Well I guess we are now following how to build these tools from source: How to build LLVM, libclang, and liblld from source · ziglang/zig Wiki · GitHub

cd ~/Downloads
git clone --depth 1 --branch release/20.x https://github.com/llvm/llvm-project llvm-project-20
cd llvm-project-20
git checkout release/20.x

mkdir build-release
cd build-release
cmake ../llvm \
  -DCMAKE_INSTALL_PREFIX=$HOME/local/llvm20-assert \
  -DCMAKE_BUILD_TYPE=Release \
  -DLLVM_ENABLE_PROJECTS="lld;clang" \
  -DLLVM_ENABLE_LIBXML2=OFF \
  -DLLVM_ENABLE_TERMINFO=OFF \
  -DLLVM_ENABLE_LIBEDIT=OFF \
  -DLLVM_ENABLE_ASSERTIONS=ON \
  -DLLVM_PARALLEL_LINK_JOBS=1 \
  -G Ninja
ninja install

Ok it is saying its building .cpp stuff… now we wait while my laptop overheats.
Why does it look like its only building one file at a time. Nevermind, every one of my cores is at 100% utilization (htop). Last time I tried to build I gave up because I couldn’t figure out how to make it use all my cores.

Videos watched while this is compiling:

Low Level - this guy writes SAFE code using C? (billions of deployments) 
https://www.youtube.com/watch?v=13jenENwBoE
Low Level - there's no way EA did this...
https://www.youtube.com/watch?v=XByTC_VD2ps
Core Dumped - The Fancy Algorithms That Make Your Computer Feel Smoother 
https://www.youtube.com/watch?v=O2tV9q6784k&t=28s

Maybe LLVM will finish compiling overnight.

Day 2

Looks like my LLVM finished building:

...
-- Installing: /home/jeff/local/llvm20-assert/include/llvm/Config/llvm-config.h
-- Up-to-date: /home/jeff/local/llvm20-assert/include/llvm/TargetParser
-- Installing: /home/jeff/local/llvm20-assert/include/llvm/TargetParser/AArch64TargetParserDef.inc
-- Installing: /home/jeff/local/llvm20-assert/include/llvm/TargetParser/RISCVTargetParserDef.inc
-- Installing: /home/jeff/local/llvm20-assert/include/llvm/TargetParser/ARMTargetParserDef.inc
-- Installing: /home/jeff/local/llvm20-assert/lib/cmake/llvm/LLVMConfigExtensions.cmake
jeff@jeff-debian:~/Downloads/llvm-project-20/build-release$

The instructions tell me to use -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert somewhere, going to have to guess (from my zig experience with -D flags) that I’m supposed to run:

cd ~/repos/zig/build/
cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..

Looks like it succeeded:

jeff@jeff-debian:~/repos/zig/build$ cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..
-- Configuring zig version 0.15.0
-- Found llvm:
...
-- Found lld:
...
jeff@jeff-debian:~/repos/zig/build$ make install
[  5%] Building CXX object CMakeFiles/zigcpp.dir/src/zig_llvm.cpp.o

It failed:

[ 94%] Linking CXX executable zig2
/usr/bin/ld: zigcpp/libzigcpp.a(zig_clang_driver.cpp.o): undefined reference to symbol 'LLVMInitializeXtensaTarget@@LLVM_20.1'
/usr/bin/ld: /usr/lib/llvm-20/lib/libLLVM.so.20.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/zig2.dir/build.make:1138: zig2] Error 1
make[1]: *** [CMakeFiles/Makefile2:170: CMakeFiles/zig2.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
jeff@jeff-debian:~/repos/zig/build$

Maybe this commit is screwed, lets try the latest on master (I have to go back to github and sync my fork first).

git pull
cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..
make install

(I don’t actually know if I need to run cmake again)

It failed again

[ 94%] Linking CXX executable zig2
/usr/bin/ld: zigcpp/libzigcpp.a(zig_clang_driver.cpp.o): undefined reference to symbol 'LLVMInitializeXtensaTarget@@LLVM_20.1'
/usr/bin/ld: /usr/lib/llvm-20/lib/libLLVM.so.20.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/zig2.dir/build.make:1138: zig2] Error 1
make[1]: *** [CMakeFiles/Makefile2:170: CMakeFiles/zig2.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
jeff@jeff-debian:~/repos/zig/build$

Lets go look at the zig github actions to see if their builds are succeeding.
The last green build is at commit 9bbac4288697f056f0cdb0c6ac597e9b1b18ea12. Lets try that one.

git checkout 9bbac4288697f056f0cdb0c6ac597e9b1b18ea12

Git complains to me about detached HEAD. Don’t know the consequences of this even after reading the paragraph it has given me, maybe someday I will understand, not today though.

cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..
make install

It failed again (the same way).

Andrew himself has bestowed wisdom upon me! Time to nuke the build dir and try again (my first failure poisoned by build with references to my system build tools).

cd ~/repos/zig/
rm -rf build/
mkdir build/
cd build/
cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..
make install

We are very close!

[100%] Building stage3
[2/5] steps
└─ [12] zig build-exe zig Debug native
   └─ LLVM Emit Object

The familiar (long-lived) sight of LLVM Emit Object is taunting me!

It worked!

[100%] Building stage3
[100%] Built target stage3
Install the project...
-- Install configuration: "Debug"
jeff@jeff-debian:~/repos/zig/build$ stage3/bin/zig version
0.15.0

I’ve followed the guide on the repo and had a pretty smooth time building from source in the past. It includes instructions for building the required llvm, clang, and lld from source.

You might find useful the following post (but change -19 to -20):

2 Likes

Anyone got an idea how to get past this?

jeff@jeff-debian:~/repos/zig/build$ cmake -DCMAKE_PREFIX_PATH=$HOME/local/llvm20-assert ..
-- Configuring zig version 0.15.0
-- Configuring done
-- Generating done
-- Build files have been written to: /home/jeff/repos/zig/build
jeff@jeff-debian:~/repos/zig/build$ make install
...
[ 94%] Linking CXX executable zig2
/usr/bin/ld: zigcpp/libzigcpp.a(zig_clang_driver.cpp.o): undefined reference to symbol 'LLVMInitializeXtensaTarget@@LLVM_20.1'
/usr/bin/ld: /usr/lib/llvm-20/lib/libLLVM.so.20.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/zig2.dir/build.make:1138: zig2] Error 1
make[1]: *** [CMakeFiles/Makefile2:170: CMakeFiles/zig2.dir/all] Error 2
make: *** [Makefile:136: all] Error 2
jeff@jeff-debian:~/repos/zig/build$

Did I accidentally build LLVM without Xtensa support?

You were very close. You ran into a bug/limitation in CMake where it tried to re-use previous state. So it tried some fucked up combination of system dynamic broken LLVM (the first time you ran cmake) combined with your fresh build from source (the second time you ran cmake).

Solution: nuke your build/ directory, create it again so that it is empty, and then rerun the second cmake command, the one with -DCMAKE_PREFIX_PATH.

What should tip you off to this problem is the existence of /usr/lib/llvm-20/lib/libLLVM.so.20.1 in the error message. Look at that path. That path comes from your system package manager. That’s not what you just compiled from source. What you just compiled from source is in /home/jeff/local/llvm20-assert.

Good news for anyone who struggles with this: after #16270 is complete, neither LLVM nor CMake will be involved in the building from source process, and so a lot fewer things can go wrong.

You might get something from this talk: How To Build Software From Source

9 Likes

Thanks! This got me over the finish line! Now I can make stack traces :slight_smile: