If you have not alreay read the last blog do that first. This blog post assumes you already have a working chroot and bootable system in qemu.
The packages you should have are
- linux, musl, coreutils, diffutils, findutils, grep, sed, dash, ncurses, bash, busybox (init), gawk and readline.
The goal of this blog post is to try and get a working llvm setup or decided if it’s not worth it and go with gcc.
If you just want to test it out you can download this image
# download the disk image
wget https://dakotajkeeler.com/download/disk-002.img.xz
# Extract the image
xz -d disk-002.img.xz
# run the image
qemu-system-x86_64 -cpu host -enable-kvm -m 4G -drive file=disk-002.img,format=raw -nographic -serial mon:stdio
# Run bash instead of sh as the default shell and source /root/.bashrc to setup basic enviroment.
bash
source /root/.bashrc
Testing clang out
# These were later added to the blog post to fix issues but never made it into the disk-002.img
ln -svf clang /usr/bin/cc
ln -svf clang++ /usr/bin/c++
cd /packages/vim-9.1.1166
make clean
./configure
make
# run our vim
src/vim
Setup environment
If you followed the last blog post you should have $HOME/mlfs. Verify that it exist and if so run the following commands to setup your envs.
export MLFS=$HOME/mlfs
export ROOTFS=$HOME/mlfs/rootfs
export MLFS_TGT=x86_64-unknown-linux-musl
Get some packages
cd $MLFS/packages
wget --no-clobber https://ftp.gnu.org/gnu/autoconf/autoconf-2.72.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/automake/automake-1.17.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/make/make-4.4.1.tar.gz
wget --no-clobber https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-21.1.8.tar.gz
wget --no-clobber https://github.com/libffi/libffi/releases/download/v3.4.7/libffi-3.4.7.tar.gz
wget --no-clobber https://download.gnome.org/sources/libxml2/2.14/libxml2-2.14.1.tar.xz
wget --no-clobber https://zlib.net/fossils/zlib-1.3.1.tar.gz
wget --no-clobber https://github.com/facebook/zstd/releases/download/v1.5.7/zstd-1.5.7.tar.gz
wget --no-clobber https://github.com/vim/vim/archive/v9.1.1166/vim-9.1.1166.tar.gz
wget --no-clobber https://www.kernel.org/pub/linux/utils/util-linux/v2.40/util-linux-2.40.4.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/patch/patch-2.7.6.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/m4/m4-1.4.19.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/bison/bison-3.8.2.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/gzip/gzip-1.13.tar.xz
wget --no-clobber https://ftp.gnu.org/gnu/gettext/gettext-0.24.tar.xz
wget --no-clobber https://www.cpan.org/src/5.0/perl-5.40.1.tar.xz
wget --no-clobber https://www.python.org/ftp/python/3.13.2/Python-3.13.2.tar.xz
wget --no-clobber https://www.sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz
wget --no-clobber https://github.com//tukaani-project/xz/releases/download/v5.6.4/xz-5.6.4.tar.xz
wget --no-clobber https://sourceforge.net/projects/libuuid/files/libuuid-1.0.3.tar.gz
git clone https://github.com/chimera-linux/libatomic-chimera.git
wget --no-clobber https://ftp.gnu.org/gnu/tar/tar-1.35.tar.xz
Build environment
Just like before, were going to set some envs. These might be changed locally and then reset.
export CC="clang"
export CXX="clang++"
export CFLAGS="-fPIC -std=gnu99 --sysroot=$ROOTFS -Wno-old-style-definition -I$ROOTFS/usr/include -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -Wno-error=implicit-function-declaration"
export CXXFLAGS="-fPIC"
export LDFLAGS="--sysroot=$ROOTFS -Wl,--dynamic-linker=/lib/ld-musl-x86_64.so.1"
export PKG_CONFIG_SYSROOT_DIR="$ROOTFS"
libff
#prep sourcee
cd $MLFS/packages
tar -xf libffi-3.4.7.tar.gz
cd libffi-3.4.7
./configure --prefix=$ROOTFS/usr \
--build= \
--host=$MLFS_TGT
make
make install
Zlib
#prep sourcee
cd $MLFS/packages
tar -xf zlib-1.3.1.tar.gz
cd zlib-1.3.1
./configure --prefix=$ROOTFS/usr
make
make install
Gettext
Slightly following the wisdom of the LFS book were prebuilding some tools for temp system. That way once were in the chroot we’ll have the proper deps nescerary to rebuild the system.
#prep sourcee
cd $MLFS/packages
tar -xf gettext-0.24.tar.xz
cd gettext-0.24
./configure --prefix=$ROOTFS/usr --disable-shared
make
make install
Bison
#prep sourcee
cd $MLFS/packages
tar -xf bison-3.8.2.tar.xz
cd bison-3.8.2
./configure --prefix=$ROOTFS/usr \
--docdir=$ROOTFS/usr/share/doc/bison-3.8.2
make
make install
Perl
#prep sourcee
cd $MLFS/packages
tar -xf perl-5.40.1.tar.xz
cd perl-5.40.1
localedef -i C -f UTF-8 C.UTF-8
sh Configure -des \
-D prefix=$ROOTFS/usr \
-D vendorprefix=$ROOTFS/usr \
-D useshrplib \
-D privlib=$ROOTFS/usr/lib/perl5/5.40/core_perl \
-D archlib=$ROOTFS/usr/lib/perl5/5.40/core_perl \
-D sitelib=$ROOTFS/usr/lib/perl5/5.40/site_perl \
-D sitearch=$ROOTFS/usr/lib/perl5/5.40/site_perl \
-D vendorlib=$ROOTFS/usr/lib/perl5/5.40/vendor_perl \
-D vendorarch=$ROOTFS/usr/lib/perl5/5.40/vendor_perl
make
make install
Bzip
#prep sourcee
cd $MLFS/packages
tar -xf bzip2-1.0.8.tar.gz
cd bzip2-1.0.8
# Bzip doesn't pick up enviroment variables. You must pass them in.
make CFLAGS="$CFLAGS" CC="$CC" LDFLAGS="$LDFLAGS"
make PREFIX=$ROOTFS/usr install
ln -vfs libbz2.so.1.0.8 $ROOTFS/usr/lib/libbz2.so
for i in $ROOTFS/usr/bin/{bzcat,bunzip2}; do
ln -sfv bzip2 $i
done
# I noticed some of my symlinks still had the absolute path in them. This fixes it.
ln -sfv bzdiff $ROOTFS/usr/bin/bzcmp
ln -sfv bzgrep $ROOTFS/usr/bin/bzegrep
ln -sfv bzgrep $ROOTFS/usr/bin/bzfgrep
ln -sfv bzmore $ROOTFS/usr/bin/bzless
Xz
#prep sourcee
cd $MLFS/packages
tar -xf xz-5.6.4.tar.xz
cd xz-5.6.4
./configure --prefix=$ROOTFS/usr \
--host=$MLFS_TGT \
--build=
make
make install
zstd
#prep sourcee
cd $MLFS/packages
tar -xf zstd-1.5.7.tar.gz
cd zstd-1.5.7
make prefix=$ROOTFS/usr
make prefix=$ROOTFS/usr install
libuuid
Ideally I shouldn’t be using this library because of how old it is and the fact it’s not being maintined. However, this was what it took to get python to build for me.
#prep sourcee
cd $MLFS/packages
tar -xf libuuid-1.0.3.tar.gz
cd libuuid-1.0.3
./configure --prefix=$ROOTFS/usr \
--host=$MLFS_TGT \
--build=
make
make install
Util-Linux
#prep sourcee
cd $MLFS/packages
tar -xf util-linux-2.40.4.tar.xz
cd util-linux-2.40.4
mkdir -vp $ROOTFS/var/lib/hwclock
mkdir -vp $ROOTFS/usr/share/doc/util-linux-2.40.4
./configure --libdir=$ROOTFS/usr/lib \
--runstatedir=$ROOTFS/run \
--prefix=$ROOTFS \
--disable-chfn-chsh \
--host=$MLFS_TGT \
--disable-login \
--disable-nologin \
--disable-su \
--disable-setpriv \
--disable-runuser \
--disable-pylibmount \
--disable-static \
--disable-liblastlog2 \
--without-python \
--without-udev \
ADJTIME_PATH=/var/lib/hwclock/adjtime
make
make install
Libxml2
#prep sourcee
cd $MLFS/packages
tar -xf libxml2-2.14.1.tar.xz
cd libxml2-2.14.1
./configure --prefix=$ROOTFS/usr \
--build= \
--host=$MLFS_TGT \
--without-python
make
make install
gzip
#prep sourcee
cd $MLFS/packages
tar -xf gzip-1.13.tar.xz
cd gzip-1.13
./configure --prefix=$ROOTFS/usr --host=$MLFS_TGT
make
make install
tar
#prep sourcee
cd $MLFS/packages
tar -xf tar-1.35.tar.xz
cd tar-1.35
./configure --prefix=$ROOTFS/usr \
--build= \
--host=x86_64-linux-musl
make
make install
Libatomic-chimera
All of llvm/clang require libatomic.so.1 to exist by extentin of relying on libc++.so.1 and it doesn’t. So I’m going to see if I can hack it with this.
#prep sourcee
cd $MLFS/packages
cd libatomic-chimera
make PREFIX=$ROOTFS/
make PREFIX=$ROOTFS/ install
make
#prep sourcee
cd $MLFS/packages
tar -xf make-4.4.1.tar.gz
cd make-4.4.1
./configure --prefix=$ROOTFS/usr \
--build= \
--host=x86_64-linux-musl
make
make install
autoconf
#prep sourcee
cd $MLFS/packages
tar -xf autoconf-2.72.tar.xz
cd autoconf-2.72
./configure --prefix=$ROOTFS/usr \
--build= \
--host=x86_64-linux-musl
make
make install
automake
#prep sourcee
cd $MLFS/packages
tar -xf automake-1.17.tar.xz
cd automake-1.17
./configure --prefix=$ROOTFS/usr \
--build= \
--host=x86_64-linux-musl
make
make install
llvm-runtimes
Before we can attempt to out right build LLVM we first need our c++ runtimes.
#prep sourcee
cd $MLFS/packages
tar -xf llvmorg-21.1.8.tar.gz
cd llvm-project-llvmorg-21.1.8
mkdir -p build-runtimes && cd build-runtimes
cmake -G "Unix Makefiles" ../runtimes \
-DLLVM_ENABLE_RUNTIMES="compiler-rt;libunwind;libcxxabi;libcxx" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_TARGETS_TO_BUILD="host" \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_ASM_COMPILER=clang \
-DCMAKE_C_COMPILER_TARGET="$MLFS_TGT" \
-DCMAKE_CXX_COMPILER_TARGET="$MLFS_TGT" \
-DCMAKE_SYSROOT="$ROOTFS" \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
-DCMAKE_INSTALL_PREFIX=$ROOTFS/usr \
-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON \
-DLIBCXX_USE_COMPILER_RT=ON \
-DLIBCXXABI_USE_COMPILER_RT=ON \
-DLIBCXXABI_USE_LLVM_UNWINDER=ON \
-DLIBUNWIND_USE_COMPILER_RT=ON \
-DCOMPILER_RT_USE_BUILTINS_LIBRARY=ON \
-DLLVM_INCLUDE_TESTS=OFF \
-DCMAKE_CXX_FLAGS="--target=$MLFS_TGT -nostdinc++ -nostdlib++" \
-DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-DCOMPILER_RT_BUILD_XRAY=OFF \
-DCOMPILER_RT_BUILD_PROFILE=OFF \
-DCOMPILER_RT_BUILD_MEMPROF=OFF \
-DCOMPILER_RT_BUILD_LIBFUZZER=OFF \
-DCOMPILER_RT_BUILD_ORC=OFF \
-DLIBCXX_ENABLE_LOCALIZATION=ON \
-DLIBCXXABI_HAS_CXA_THREAD_ATEXIT_IMPL=OFF \
-DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \
-DLLVM_DEFAULT_TARGET_TRIPLE=$MLFS_TGT \
-DLIBCXX_HAS_MUSL_LIBC=ON \
-DCOMPILER_RT_BUILD_BUILTINS=ON \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON
make
make install
Testing our new c++ environment
If you cannot get this to work. Do not procced! Having a working c++ enviroment is an absolute must to continue with the project.
cat > hello.cpp <<'EOF'
#include <iostream>
#include <vector>
int main() {
std::vector<int> v{1,2,3};
std::cout << "hello libc++: " << v.size() << "\n";
return 0;
}
EOF
clang++ --target="$MLFS_TGT" --sysroot="$ROOTFS" \
-nostdinc++ \
-isystem "$ROOTFS/usr/include/$MLFS_TGT/c++/v1" \
-isystem "$ROOTFS/usr/include/c++/v1" \
-stdlib=libc++ \
-L"$ROOTFS/usr/lib/$MLFS_TGT" -lc++ -lc++abi -lunwind \
-rtlib=compiler-rt \
-unwindlib=libunwind \
-fuse-ld=lld \
hello.cpp -o hello-libcxx
file hello-libcxx
readelf -d hello-libcxx | grep NEEDED
clang++ --target="$MLFS_TGT" --sysroot="$ROOTFS" \
-nostdinc++ \
-isystem "$ROOTFS/usr/include/$MLFS_TGT/c++/v1" \
-isystem "$ROOTFS/usr/include/c++/v1" \
-stdlib=libc++ \
-L"$ROOTFS/usr/lib/$MLFS_TGT" \
-rtlib=compiler-rt \
-unwindlib=libunwind \
-fuse-ld=lld \
-static \
-Wl,--start-group -lc++ -lc++abi -lunwind -lclang_rt.builtins -Wl,--end-group \
hello.cpp -o hello-libcxx-static
ldd hello-libcxx-static
“host” build of llvm
These tools need to be able to run on the host system during the cross build of our llvm/clang. Which depending on libc/archeticture there is no guarentee that they would run if you didn’t build them against the host system.
unset CFLAGS CXXFLAGS LDFLAGS CC CXX AR RANLIB LD
export CC=clang
export CXX=clang++
cd $MLFS/packages/llvm-project-llvmorg-21.1.8
mkdir -p build-host && cd build-host
cmake -G "Unix Makefiles" "../llvm" \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DLLVM_TARGETS_TO_BUILD="X86;AVR" \
-DLLVM_ENABLE_LIBATOMIC=OFF
make -j llvm-tblgen clang-tblgen llvm-min-tblgen
set some c++ envs
This ensures that the system can find all the right libraries and header files.
export CC="clang"
export CXX="clang++"
export LD="ld.lld"
export CFLAGS="-fPIC -std=gnu99 --sysroot=$ROOTFS -Wno-old-style-definition -I$ROOTFS/usr/include -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -Wno-error=implicit-function-declaration"
export CXXFLAGS="--target=$MLFS_TGT --sysroot=$ROOTFS \
-nostdinc++ \
-isystem $ROOTFS/usr/include/$MLFS_TGT/c++/v1 \
-isystem $ROOTFS/usr/include/c++/v1 \
-stdlib=libc++ \
-Wno-unused-command-line-argument \
-fPIC"
export LDFLAGS="-fuse-ld=lld \
-rtlib=compiler-rt \
-unwindlib=libunwind \
-stdlib=libc++ \
-L$ROOTFS/usr/lib/$MLFS_TGT \
-lc++ -lc++abi -lunwind \
--sysroot=$ROOTFS \
-Wl,--dynamic-linker=/lib/ld-musl-x86_64.so.1"
LLVM/Clang
#prep sourcee
cd $MLFS/packages/llvm-project-llvmorg-21.1.8
mkdir -vp build
cd build
# These are the only two platforms I care about. It took almost a couple hours building to build
# platforms I have zero interest in targetting.
# -DLLVM_TARGETS_TO_BUILD="X86;AVR"
cmake -G "Unix Makefiles" "../llvm" \
-DCMAKE_BUILD_TYPE=Release \
-DLLVM_TARGETS_TO_BUILD="host" \
-DCMAKE_TRY_COMPILE_TARGET_TYPE=STATIC_LIBRARY \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_ASM_COMPILER=clang \
-DCMAKE_C_COMPILER_TARGET="$MLFS_TGT" \
-DCMAKE_CXX_COMPILER_TARGET="$MLFS_TGT" \
-DCMAKE_SYSROOT="$ROOTFS" \
-DCMAKE_INSTALL_PREFIX=$ROOTFS/usr \
-DLLVM_ENABLE_PROJECTS="clang;lld" \
-DLLVM_USE_HOST_TOOLS=ON \
-DLLVM_TABLEGEN="$PWD/../build-host/bin/llvm-tblgen" \
-DCLANG_TABLEGEN="$PWD/../build-host/bin/clang-tblgen" \
-DLLVM_INCLUDE_TESTS=OFF \
-DLLVM_INCLUDE_BENCHMARKS=OFF \
-DLLVM_INCLUDE_EXAMPLES=OFF \
-DCLANG_DEFAULT_CXX_STDLIB=libc++ \
-DCLANG_DEFAULT_RTLIB=compiler-rt \
-DCLANG_DEFAULT_UNWINDLIB=libunwind \
-DLLVM_INSTALL_BINUTILS_SYMLINKS=ON \
-DHAVE_MALLINFO=0 \
-DHAVE_MALLINFO2=0 \
-DHAVE_DECL_ARC4RANDOM=0 \
-DHAVE_BACKTRACE=0 \
-DLLVM_ENABLE_BACKTRACES=OFF \
-DLLVM_ENABLE_UNWIND_TABLES=OFF \
-DLLVM_ENABLE_LIBATOMIC=OFF
make -j
make install
Python
Since we are cross compiling python we need to add the –with-build-python and –disable-ipv6. The first option will require a python version realitivly close to the version you are building. – On slackware I had to build Python 3.13 to be able to do this.
We have to build this after LLVM so that it doesn’t try to run this. Because it’s not statically built so I will fail on the host system. I know what you’re going to say though. Just build it statically, I already have several hours into getting to build and run and how it will react when building llvm when I already got that process largly sorted out is a headache I don’t want today.
The build error out about these values So I hard code them to make them work. ac_cv_file__dev_ptmx=yes
ac_cv_file__dev_null=yes
ac_cv_file__dev_ptc=yes \
#prep sourcee
cd $MLFS/packages
tar -xf Python-3.13.2.tar.xz
cd Python-3.13.2
ac_cv_file__dev_ptmx=yes \
ac_cv_file__dev_null=yes \
ac_cv_file__dev_ptc=yes \
./configure --prefix=$ROOTFS/usr \
--enable-shared \
--without-ensurepip \
--host=$MLFS_TGT \
--build= \
--with-build-python \
--disable-ipv6
make
make install
Chroot into the system
We need to copy over the packages were going to build first in the system
If you don’t delete $ROOTFS/packages you must make a larger disk.img before copying the $ROOTFS over.
mkdir -vp $ROOTFS/packages/
cp -apvr $MLFS/packages/vim-9.1.1166.tar.gz $ROOTFS/packages/
# IF it errors out with not such file: Did you skip the first blog post?
cp -apvr $MLFS/packages/ncurses-6.5.tar.gz $ROOTFS/packages/
sudo chroot $ROOTFS
Musl dynamic linker
We then need to do some work to make our programs work. Musl dynamic linker searchs the path in the /etc/ld-musl-x86_64.path If itt isn’t in there it won’t be loaded.
# Allow the dynamic loader to find our libstdc++ and related stuff
echo "/usr/lib/x86_64-unknown-linux-musl" >> /etc/ld-musl-x86_64.path
echo "/usr/lib" >> /etc/ld-musl-x86_64.path
echo "/lib" >> /etc/ld-musl-x86_64.path
# We need to symlink our ld.lld to ld
ln -sf ld.lld /usr/bin/ld
Test clang
Now that we’re in the chroot we need to make sure we can compile simple programs. In the LFS book they create a symlink cc that points to the system compiler.
ln -svf clang /usr/bin/cc
ln -svf clang++ /usr/bin/c++
I ran into some problems with getting a simple hello.c program to compile. Bellow are the steps to fixing it.
clang hello.c
ld: error: cannot open crtbeginS.o: No such file or directory ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a: No such file or directory ld: error: unable to find library -lunwind ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a: No such file or directory ld: error: unable to find library -lunwind ld: error: cannot open crtendS.o: No such file or directory
# To fix this I created a global clang config file that sets some basic things like target and tell
# to use compiler-rt and libunwind
echo "--target=x86_64-unknown-linux-musl \
--sysroot=/ \
-rtlib=compiler-rt \
-unwindlib=libunwind \
-stdlib=libc++" > /usr/bin/clang.cfg
ld: error: cannot open crtbeginS.o: No such file or directory ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-musl/libclang_rt.builtins.a: No such file or directory ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-musl/libclang_rt.builtins.a: No such file or directory ld: error: cannot open crtendS.o: No such file or directory
clang is looking for these files in a directory that does exist So I create it and symlink in the file it needs
mkdir -p /usr/lib/clang/21/lib/x86_64-unknown-linux-musl
ln -sv /usr/lib/x86_64-unknown-linux-musl/libclang_rt.builtins.a \
/usr/lib/clang/21/lib/x86_64-unknown-linux-musl/
ld: error: cannot open crtbeginS.o: No such file or directory ld: error: cannot open crtendS.o: No such file or directory clang: error: linker command failed with exit code 1 (use -v to see invocation)
These files exist but have clang_rt. appended in front. So I created two sets of symlinks. One for each file in the directory they exist in. And another in the directory clang is looking for them in.
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtbegin.o \
/usr/lib/x86_64-unknown-linux-musl/crtbeginS.o
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtend.o \
/usr/lib/x86_64-unknown-linux-musl/crtendS.o
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtbegin.o \
/usr/lib/clang/21/lib/x86_64-unknown-linux-musl/crtbeginS.o
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtend.o \
/usr/lib/clang/21/lib/x86_64-unknown-linux-musl/crtendS.o
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtbegin.o \
/usr/lib/x86_64-unknown-linux-musl/crtbeginT.o
ln -sv /usr/lib/x86_64-unknown-linux-musl/clang_rt.crtend.o \
/usr/lib/x86_64-unknown-linux-musl/crtend.o
After this building the simple c program worked! But not the hello.cpp….
clang++ hello.cpp In file included from hello.cpp:1: In file included from /usr/bin/../include/c++/v1/iostream:39: /usr/bin/../include/c++/v1/__config:13:10: fatal error: ‘__config_site’ file not found 13 | #include <__config_site> | ^~~~~~~~~~~~~~~ 1 error generated.
ln -sv /usr/include/x86_64-unknown-linux-musl/c++/v1/__config_site \
/usr/include/c++/v1/__config_site
clang++ hello.cpp ld: error: cannot open crtbeginS.o: No such file or directory ld: error: unable to find library -lc++ ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a: No such file or directory ld: error: unable to find library -lunwind ld: error: cannot open /usr/lib/clang/21/lib/x86_64-unknown-linux-gnu/libclang_rt.builtins.a: No such file or directory ld: error: unable to find library -lunwind ld: error: cannot open crtendS.o: No such file or directory clang++: error: linker command failed with exit code 1 (use -v to see invo
echo "--target=x86_64-unknown-linux-musl \
-rtlib=compiler-rt \
-unwindlib=libunwind \
-stdlib=libc++ \
-L/usr/lib/x86_64-unknown-linux-musl" > /usr/bin/clang++.cfg
Now hello.cpp bellow should also build. – I’m leaving these errors in here because my work around seems very hacky. That way if anybody has any better ideas or see a mistake I’ve made that would elimate these problems I would love to know.
cat > hello.cpp <<'EOF'
#include <iostream>
#include <vector>
int main() {
std::vector<int> v{1,2,3};
std::cout << "hello libc++: " << v.size() << "\n";
return 0;
}
EOF
cat > hello.c <<'EOF'
#include <stdio.h>
int main() {
printf("Hello world!\n");
return 0;
}
EOF
Ncurses
Now that we got c++ support working we need to rebuild ncurses for it.
#prep sourcee
cd /packages
tar -xf ncurses-6.5.tar.gz
cd ncurses-6.5
mkdir -p build
pushd build
../configure --prefix=/usr \
--without-gpm
make -C include
make -C progs/../include
make -C progs tic
popd
./configure --prefix=/usr \
--with-shared \
--with-normal \
--without-debug \
--without-ada \
--without-tests \
--disable-stripping \
--without-gpm \
--enable-widec \
--enable-pc-files \
--with-pkg-config-libdir=/usr/lib/pkgconfig \
AWK=gawk
make && make install
Vim
Vim is a classic text editor found almost everywhere which is why I included it here. In a future series exploring the capablities of zig I’ll probably swap this out with flow.
#prep sourcee
cd /packages
tar -xf vim-9.1.1166.tar.gz
cd vim-9.1.1166
./configure --prefix=/usr
make
make install
Cleanup
This is the end of the temp system. We need to cleanup any archive files and docs. As the next blog post will be rebuilding the whole system inside of a chroot from scratch
rm -rf /usr/share/{info,man,doc}/*
find /usr/{lib,libexec} -name \*.la -delete
################################## EXIT THE CHROOT! ##################################
Assembling the Disk Image
cd $MLFS
# Create a 10GB image to give room to play around
dd if=/dev/zero of=disk.img bs=1M count=10240
sudo mkfs.ext4 disk.img
mkdir -pv mntimg
sudo mount disk.img mntimg
sudo rsync -av --delete $ROOTFS/ mntimg/
sudo mkdir -vp mntimg/boot/extlinux
# Copy Syslinux modules - Arch Linux
sudo cp -vr /usr/lib/syslinux/bios/*.c32 mntimg/boot/extlinux/
# Copy Syslinux modules - Slackware
sudo cp -vr /usr/share/syslinux/*.c32 mntimg/boot/extlinux/
# If unsure, find them
find / -name "*.c32" 2>/dev/null
cat >> extlinux.conf << 'EOF'
DEFAULT linux
LABEL linux
KERNEL /boot/bzImage
APPEND root=/dev/sda rw init=/usr/sbin/init console=ttyS0
TEXT HELP
Boot the minimal playground kernel with your static rootfs.
ENDTEXT
EOF
sudo cp -apvr extlinux.conf mntimg/boot/extlinux/extlinux.conf
sudo extlinux -i mntimg/boot/extlinux
sync
sudo umount mntimg
Booting in QEMU
qemu-system-x86_64 -cpu host -enable-kvm -m 4G -drive file=disk.img,format=raw -nographic -serial mon:stdio
bash
source /root/.bashrc
Conclusion
With this we now have a fully working clang inside our chroot. The next step on this journy is to rebuild the entire system against the new compiler! (That includes the compiler) For this will be following the order in the next post of LFS 12.3. (I know 12.4..) The excpetions will be we’ll be using dinit, and not building gcc, gnu-binutils, or glibc as part of the base image. we’ll be using dinit as our init system, which will be covered in part 4
I strongly reconmend making a backup of your rootfs in case of breakages.
I’m sure there are bugs in this, that I’ll hopefully find in time. If you find one let me know and I’ll update the blog post to relect with credit to it’s source.
Sincerely, a concrete worker. May the peace and grace of our Lord be with you.