The Funtoo Linux project has transitioned to "Hobby Mode" and this wiki is now read-only.
Difference between revisions of "User:Invakid404/CLFS"
Invakid404 (talk | contribs) (Musl) |
Invakid404 (talk | contribs) m (Remove random newlines) |
||
Line 222: | Line 222: | ||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
}} | }} | ||
==== musl ==== | ==== musl ==== |
Revision as of 16:43, February 23, 2022
CLFS with musl
This page covers the steps of getting a working CLFS "temporary environment" with musl instead of glibc and latest everything.
Setting up the environment (Chapter 2)
Instead of creating a partition, we'll build everything in a directory in our home. Let's assign it to a variable called `CLFS` and create it:
user $ export CLFS="$HOME/clfs" user $ mkdir -v "${CLFS}" mkdir: created directory '/home/invakid404/clfs'
We'll also need to create three subdirectories in our CLFS directory:
- cross-tools: this is where the cross compiler will go
- tools: this is where the so-called "temporary system" will go
- sources: this is where we'll download and build all packages
user $ mkdir -v "${CLFS}"/cross-tools mkdir: created directory '/home/invakid404/clfs/cross-tools' user $ mkdir -v "${CLFS}"/tools mkdir: created directory '/home/invakid404/clfs/tools' user $ mkdir -v "${CLFS}"/sources mkdir: created directory '/home/invakid404/clfs/sources'
Let's also define some build-related environment variables:
- CLFS_HOST: the target triple of the host machine; modified to contain "cross" to handle the case where we're cross-compiling for the same target
- CLFS_TARGET: the target triple of the target architecture
- CLFS_ARCH: the name of the target architecture; used specifically when installing Linux kernel headers
- CLFS_CFLAGS: extra flags we'll pass to the GCC cross compiler
- MAKEFLAGS: flags we want to pass to GNU make by default
The host variable is straightforward:
user $ export CLFS_HOST=$(echo ${MACHTYPE} | sed -e 's/-[^-]*/-cross/') user $ echo "${CLFS_HOST}" x86_64-cross-linux-gnu
The target, arch, and CFLAGS depend on the target architecture you're going for. Here's a table of all currently tested architectures and their respective build variables:
Architecture | CLFS_TARGET | CLFS_ARCH | CLFS_CFLAGS |
---|---|---|---|
x86_64 | x86_64-unknown-linux-musl | x86_64 | -m64 |
aarch64 | aarch64-unknown-linux-musl | arm64 |
The rest of this page will assume aarch64, but the steps should be analogous for all listed architectures:
user $ export CLFS_TARGET="aarch64-unknown-linux-musl" user $ export CLFS_ARCH="arm64" user $ export CLFS_CFLAGS=""
For the makeflags, we'll tell GNU make to run as many jobs in parallel as we have threads to speed up the compilation:
user $ export MAKEFLAGS="-j$(nproc) -l$(nproc)"
Note that one can put these exports in a file and source them every time one restarts their session to avoid having to setting them manually each and every time. The same applies for all convenience environment variables we'll define later on.
Let's also set our PATH to something more restricted to reduce the influence of the host machine to a minimum. We'll also need to add our cross-tools directory to PATH to be able to use the cross compiler later:
user $ export PATH="${CLFS}/cross-tools/bin:/bin:/usr/bin"
Building the cross compiler (Chapter 3)
To get a cross compiler going, we'll need to do the following steps:
- Install the Linux headers for the target architecture
- Build binutils for the target architecture
- Build a static version of GCC without a standard library
- Build musl with the static version of GCC
- Build GCC again, now with musl as the standard library
Note that the official CLFS guide suggests building things like GMP, MPFR, and MPC separately, but we'll extract those in the GCC source directory and leave it up to the GCC makefile to do the heavy-lifting for us for simplicity. We'll also skip over ISL since it's not required and not too interesting for us at this stage.
Linux headers
First things first, let's fetch the Linux kernel sources. Throughout the rest of this page, we'll be putting the versions of packages in environment variables for convenience like so:
user $ export LINUX_VERSION="5.16.10"
Let's cd into the sources directory and download Linux:
user $ cd "${CLFS}"/sources user $ wget https://cdn.kernel.org/pub/linux/kernel/v$(echo "${LINUX_VERSION}" | cut -d'.' -f1).x/linux-"${LINUX_VERSION}".tar.xz user $ tar xvf linux-"${LINUX_VERSION}".tar.xz
Now, let's install the Linux headers for our target architecture. We'll install those in the tools directory to use in the temporary environment as well:
user $ pushd linux-"${LINUX_VERSION}" user $ make mrproper user $ make ARCH=${CLFS_ARCH} INSTALL_HDR_PATH=${CLFS}/tools headers_install user $ popd
Binutils
Let's fetch and extract the binutils sources:
user $ export BINUTILS_VERSION="2.38" user $ wget https://ftp.gnu.org/gnu/binutils/binutils-"${BINUTILS_VERSION}".tar.xz user $ tar xvf binutils-"${BINUTILS_VERSION}".tar.xz user $ pushd binutils-"${BINUTILS_VERSION}"
Now, let's configure binutils. The options we'll use are explained here. The only deviation we'll make is we'll prepend the prefix and lib path with the CLFS directory (this will be a reoccurring trend in this page since we aren't creating the symlinks in /) and we'll skip over some flags that aren't 100% necessary:
user $ AR=ar AS=as ../binutils-${BINUTILS_VERSION}/configure \ --prefix=${CLFS}/cross-tools \ --host=${CLFS_HOST} \ --target=${CLFS_TARGET} \ --with-sysroot=${CLFS} \ --with-lib-path=${CLFS}/tools/lib \ --disable-nls \ --disable-static \ --enable-64-bit-bfd \ --disable-multilib \ --disable-werror
We're now ready to build and install it:
user $ make user $ make install user $ popd
Static GCC
Now, it's time to build a static GCC, which we'll use to build musl. For this, we'll need to fetch the sources of some GCC dependencies first, namely MPFR, GMP, and MPC:
user $ export MPFR_VERSION="4.1.0" user $ export GMP_VERSION="6.2.1" user $ export MPC_VERSION="1.2.1" user $ wget https://ftp.gnu.org/gnu/mpfr/mpfr-"${MPFR_VERSION}".tar.xz user $ wget https://ftp.gnu.org/gnu/gmp/gmp-"${GMP_VERSION}".tar.xz user $ wget https://ftp.gnu.org/gnu/mpc/mpc-"${MPC_VERSION}".tar.gz
Note that we won't build them separately. Instead, we'll extract them inside the GCC source directory and let the GCC makefile handle that for us. With that out of the way, we should also fetch and extract the GCC sources:
user $ export GCC_VERSION="11.2.0" user $ wget https://ftp.gnu.org/gnu/gcc/gcc-"${GCC_VERSION}"/gcc-"${GCC_VERSION}".tar.xz user $ tar xvf gcc-"${GCC_VERSION}".tar.xz
Now, as mentioned above, we'll move into the GCC source directory and extract its dependencies inside:
user $ pushd gcc-"${GCC_VERSION}" user $ tar xvf ../mpfr-"${MPFR_VERSION}".tar.xz && mv -v mpfr-"${MPFR_VERSION}" mpfr user $ tar xvf ../gmp-"${GMP_VERSION}".tar.xz && mv -v gmp-"${GMP_VERSION}" gmp user $ tar xvf ../mpc-"${MPC_VERSION}".tar.gz && mv mpc-"${MPC_VERSION}" mpc user $ popd
We can get to building now. Let's create a separate directory for the GCC build and move into it:
user $ mkdir gcc-build user $ pushd gcc-build
To configure GCC, we'll do a mixture of what's described in the regular and embedded CLFS books:
user $ AR=ar LDFLAGS="-Wl,-rpath,${CLFS}/cross-tools/lib" \ ../gcc-"${GCC_VERSION}"/configure \ --prefix=${CLFS}/cross-tools \ --build=${CLFS_HOST} \ --host=${CLFS_HOST} \ --target=${CLFS_TARGET} \ --with-sysroot=${CLFS} \ --with-local-prefix=${CLFS}/tools \ --with-native-system-header-dir=/tools/include \ --disable-shared \ --without-headers \ --with-newlib \ --disable-decimal-float \ --disable-libgomp \ --disable-libssp \ --disable-libatomic \ --disable-libitm \ --disable-libsanitizer \ --disable-libquadmath \ --disable-libvtv \ --disable-libcilkrts \ --disable-libstdc++-v3 \ --disable-threads \ --disable-multilib \ --enable-languages=c \ --with-mpfr-include=$(pwd)/../gcc-"${GCC_VERSION}"/mpfr/src \ --with-mpfr-lib=$(pwd)/mpfr/src/.libs
As mentioned in the book, we don't need to build the entirety of GCC at this stage. The following is enough:
user $ make all-gcc all-target-libgcc user $ make install-gcc install-target-libgcc user $ popd
With that, we should now have a somewhat functioning GCC cross compiler!
user $ "${CLFS}"/cross-tools/bin/"${CLFS_TARGET}"-gcc --version aarch64-unknown-linux-musl-gcc (GCC) 11.2.0 Copyright (C) 2021 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
musl
Now that we have a cross compiler, we can use it to build musl. As always, we'll start by fetching and extracting the sources:
user $ export MUSL_VERSION="1.2.2" user $ wget https://musl.libc.org/releases/musl-"${MUSL_VERSION}".tar.gz user $ tar xvf musl-"${MUSL_VERSION}".tar.gz user $ pushd musl-"${MUSL_VERSION}"
Configuring musl is pretty straightforward. We'll do it pretty much exactly like in the embedded book.
user $ CC="${CLFS_TARGET}-gcc ${CLFS_CFLAGS}" \ ./configure \ CROSS_COMPILE=${CLFS_TARGET}- \ --prefix=/ \ --target=${CLFS_TARGET}
Note that we're also setting the "CC" environment variable with our cross compiler and the CFLAGS we've defined at the start. Compiling and installing musl is just as straightforward:
user $ make user $ DESTDIR=${CLFS}/tools make install user $ popd