So you want to cross compile a glibc system from a musl system?
I won't pretend to know all the answers, but the hardest part is correctly
bootstrapping a new toolchain to later build the new system with. Say we are building
a toolchain with target NEW_HOST="i686-nu-linux-gnu" into an isolated SYSROOT="/nu".
First, extract the source code and create out of tree build directories because yes I've run into
weird problems specifically when cross compiling gcc with new libc if building from the source directory.
Don't forget you need to extract gmp, mpc, and mpfr and manually place them into the gcc source dir.
The following configuration was tested with gcc-15.2, glibc-2.42, binutils-2.45
There are two phases at this stage, lets call them phase0 and phase1.
phase0 is where we are using the current host system compiler, in my case it looks like this.
INITIAL_PATH=$PATH
...
phase0_env() { <<<<<<<<<
export CPP="x86_64-pc-linux-gnu-cpp"
export CC="x86_64-pc-linux-gnu-gcc"
export CXXCPP="x86_64-pc-linux-gnu-cpp"
export CXX="x86_64-pc-linux-gnu-gxx"
export NM="x86_64-pc-linux-gnu-nm"
export AR="x86_64-pc-linux-gnu-ar"
export AS="x86_64-pc-linux-gnu-as"
export LD="x86_64-pc-linux-gnu-ld"
export RANLIB="x86_64-pc-linux-gnu-ranlib"
export OBJCOPY="x86_64-pc-linux-gnu-objcopy"
export PATH="$INITIAL_PATH:$SYSROOT/bin" <<<<<<<<<
}
1) linux headers:
make ARCH=x86 INSTALL_HDR_PATH=/nu headers_install
Then I move /nu/usr/include to /nu/include because /usr is not needed in a new clean sysroot.
in practice we could symlink /usr to /nu if really required.
2) binutils:
configure
--prefix=$SYSROOT
--target=$NEW_HOST
--program-prefix=$NEW_HOST-
--with-lib-path=$SYSROOT/lib
--enable-static
--disable-shared
--disable-gprofng
--disable-lto
--disable-nls
if make fails because of a missing makeinfo you can fix it with
sed -i "s|MAKEINFO = .*makeinfo$|MAKEINFO = /bin/true|" Makefile
After it installs, create symlinks to the binaries with the program-prefix.
ln -sv $NEW_HOST-strings $SYSROOT/bin/strings
ln -sv $NEW_HOST-objcopy $SYSROOT/bin/objcopy
ln -sv $NEW_HOST-elfedit $SYSROOT/bin/elfedit
ln -sv $NEW_HOST-addr2line $SYSROOT/bin/addr2line
ln -sv $NEW_HOST-strip $SYSROOT/bin/strip
ln -sv $NEW_HOST-c++filt $SYSROOT/bin/c++filt
ln -sv $NEW_HOST-objdump $SYSROOT/bin/objdump
ln -sv $NEW_HOST-nm $SYSROOT/bin/nm
ln -sv $NEW_HOST-size $SYSROOT/bin/size
ln -sv $NEW_HOST-readelf $SYSROOT/bin/readelf
ln -sv $NEW_HOST-gprof $SYSROOT/bin/gprof
ln -sv $NEW_HOST-ar $SYSROOT/bin/ar
ln -sv $NEW_HOST-ld $SYSROOT/bin/ld
ln -sv $NEW_HOST-ranlib $SYSROOT/bin/ranlib
ln -sv $NEW_HOST-as $SYSROOT/bin/as
3) gcc:
configure
--with-sysroot=
--without-headers
--with-newlib
--target=$NEW_HOST
--prefix=$SYSROOT
--program-prefix=$NEW_HOST-
--with-gxx-include-dir=$SYSROOT/include/c++
--with-native-system-header-dir=$SYSROOT/include
--with-local-prefix=$SYSROOT
--enable-languages=c,c++
--enable-static
--disable-shared
--disable-bootstrap
--disable-libssp
--disable-libvtv
--disable-libsanitizer
--disable-gcov
--disable-multilib
--disable-libquadmath
--disable-libgomp
--disable-plugin
--disable-libmpx
--disable-libitm
--disable-threads
--disable-libatomic
--disable-lto
--disable-libstdcxx
--disable-libstdcxx-pch
--disable-libstdcxx-threads
--disable-nls
Create symlinks for program-prefix binaries
ln -sv $NEW_HOST-cc $SYSROOT/bin/cc
ln -sv $NEW_HOST-gcc $SYSROOT/bin/gcc
ln -sv $NEW_HOST-g++ $SYSROOT/bin/g++
ln -sv $NEW_HOST-c++ $SYSROOT/bin/c++
ln -sv $NEW_HOST-cpp $SYSROOT/bin/cpp
Now we are on to phase1, which starts using the new gcc and binutils
phase1_env() { <<<<<<<<<
export CPP="i686-nu-linux-gnu-cpp"
export CC="i686-nu-linux-gnu-gcc"
export CXXCPP="i686-nu-linux-gnu-cpp"
export CXX="i686-nu-linux-gnu-gxx"
export NM="i686-nu-linux-gnu-nm"
export AR="i686-nu-linux-gnu-ar"
export AS="i686-nu-linux-gnu-as"
export LD="i686-nu-linux-gnu-ld"
export RANLIB="i686-nu-linux-gnu-ranlib"
export OBJCOPY="i686-nu-linux-gnu-objcopy"
export PATH="$SYSROOT/bin:$INITIAL_PATH" <<<<<<<<<
}
4) glibc:
configure
--prefix=$SYSROOT
--disable-werror
--target=$NEW_HOST
--with-headers=$SYSROOT/include
5) binutils:
configure
--prefix=$SYSROOT
--target=$NEW_HOST
--program-prefix=$NEW_HOST-
--with-lib-path=$SYSROOT/lib
--with-sysroot=
--enable-static
--disable-shared
--disable-gprofng
--disable-lto
--disable-multilib
--disable-nls
6) libstdc++:
gcc/libstdc++-v3/configure
--with-sysroot=
--prefix=$SYSROOT
--target=$NEW_HOST
--with-native-system-header-dir=$SYSROOT/include
--with-gxx-include-dir=$SYSROOT/include/c++
--with-local-prefix=$SYSROOT
--enable-static
--disable-shared
--disable-multilib
--disable-nls
7) gcc:
configure
--with-sysroot=
--prefix=$SYSROOT
--build=$NEW_HOST
--host=$NEW_HOST
--target=$NEW_HOST
--with-gxx-include-dir=$SYSROOT/include/c++
--with-native-system-header-dir=$SYSROOT/include
--with-local-prefix=$SYSROOT
--enable-languages=c,c++
--enable-static
--disable-shared
--disable-bootstrap
--disable-libssp
--disable-libvtv
--disable-libsanitizer
--disable-gcov
--disable-multilib
--disable-libgomp
--disable-plugin
--disable-libmpx
--disable-libitm
--enable-threads=posix
--disable-lto
--disable-nls
Now you can build the rest of the temporary toolchain as needed. You want to keep it isolated
from the host system when finally building the new system, so you need to build coreutils, bash, awk, make,
etc, etc, etc. GNU toolchain additionally requires m4, autoconf, automake, perl, texinfo, bison, python, and flex.
You can either chroot, boot directly into it, or load into a sandbox, container, or VM.
A critical file needed by GNU toolchain is $SYSROOT/include/gnu/stubs-32.h, or stubs-64.h depending on your target.
If those files are missing, gcc will not be able to replicate itself and leave you with a broken system. AFAICT
multilib is not needed and I am not sure it's worth the trouble, but if you want multilib you will need both
32 and 64 bit versions.
This toolchain is only temporary, but some misconfiguration here can trickle down to the new system, so
just because it compiles does not mean it's correct! Always test it out before continuing to the real system.
There are some options I listed here that may or may not be required, I will update this if/when I find the time.