monochromatic

monochromatic blog: http://blog.z3bra.org
git clone git://z3bra.org/monochromatic
Log | Files | Refs

commit 7f2589bdb6500984bbc4717aadf3d189685bdfc5
parent 41e38839b23d8ccea33dd48b439143889effbef9
Author: z3bra <willyatmailoodotorg>
Date:   Sun, 16 Aug 2015 19:53:58 +0200

new post: pcc + musl cross-compiler

Diffstat:
2015/08/cross-compiling-with-pcc-and-musl.txt | 380+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
config.mk | 3++-
index.txt | 1+
3 files changed, 383 insertions(+), 1 deletion(-)

diff --git a/2015/08/cross-compiling-with-pcc-and-musl.txt b/2015/08/cross-compiling-with-pcc-and-musl.txt @@ -0,0 +1,380 @@ +# [cross-compiling with PCC and musl](#) +## &mdash; 16 August, 2015 + +I've recently been playing around with [PCC](http://pcc.ludd.ltu.se/) and +[musl](http://www.musl-libc.org/), and to make the process of compiling +softwares with them easier, I decided to setup a cross-compiler relying on both. + +**TL;DR**: here is the full script. It will create your toolchain in `$HOME/cross/pcc-x86_64` and name the tools `x86_64-linux-musl-*`. + + #!/bin/sh -ex + # + # Couple of useful links: + # + http://pcc.ludd.ltu.se/cross-compiler/ + # + http://wiki.osdev.org/Cross-Compiler_Successful_Builds + # + https://git.framasoft.org/Ypnose/solyste/blob/master/scripts/create-crossenv + # + http://kegel.com/crosstool/ + # + https://github.com/GregorR/musl-cross/tree/master/patches + # + # 0. download and extract sources + # 1. patch everything that require patching + # 2. install linux headers + # 3. build binutils + # 4. build musl + # 5. build pcc with gcc + # 6. add pkg-config wrapper + + # cross compiler environment + MARCH=$(uname -m) + TRIPLE=${TRIPLE:-${MARCH}-linux-musl} + PREFIX=${PREFIX:-${HOME}/cross/pcc-${MARCH}} + BLDDIR=${BLDDIR:-${HOME}/cross/build} + SRCDIR=${SRCDIR:-${HOME}/cross/source} + PATCHD=${PATCHD:-${HOME}/cross/patches} + + # compilation variables + PATH="${PREFIX}/bin:${PATH}" + CFLAGS="-Os -fomit-frame-pointer -pipe" + CXXFLAGS="${CFLAGS}" + CPPFLAGS="${CFLAGS}" + LDFLAGS="-Wl,--as-needed" + MAKEFLAGS="-j8" + + # versions + PCCV=${PCCV:-1.1.0} + BINV=${BINV:-2.25} + MUSLV=${MUSLV:-1.1.10} + KERNV=${KERNV:-4.1.4} + + + # source mirrors + PCCMIRROR=ftp://pcc.ludd.ltu.se/pub/pcc-releases + GNUMIRROR=ftp://ftp.gnu.org/gnu + MUSLMIRROR=http://www.musl-libc.org/releases + LINUXMIRROR=https://www.kernel.org/pub/linux/kernel/v4.x + + # Preparing sources + mkdir -p "${SRCDIR}" "${BLDDIR}" "${PREFIX}" + cd "${SRCDIR}" + + # + # ┏━┓ + # ┃┃┃ + # ┗━┛╹ + # Get all GNU tarballs + grab_sources() { + curl -# "${PCCMIRROR}/pcc-${PCCV}.tgz" | tar xz + curl -# "${PCCMIRROR}/pcc-libs-${PCCV}.tgz" | tar xz + curl -# "${GNUMIRROR}/binutils/binutils-${BINV}.tar.gz" | tar xz + curl -# "${MUSLMIRROR}/musl-${MUSLV}.tar.gz" | tar xz + curl -# "${LINUXMIRROR}/linux-${KERNV}.tar.xz" | tar xJ + } + + # + # ╺┓ + # ┃ + # ╺┻╸╹ + # Patch all source trees. + # This will take all patches in $PATCHD matching the programs + patch_sources() { + for DIR in $(find "${SRCDIR}" -maxdepth 1 -type d); do + cd "${DIR}" + cat "${PATCHD}/$(basename ${DIR})"-*.diff | patch -Np1 + done + } + + # + # ┏━┓ + # ┏━┛ + # ┗━╸╹ + # Get linux headers + install_headers() { + cd "${SRCDIR}/linux-${KERNV}" + make ARCH=${MARCH} headers_check + make ARCH=${MARCH} INSTALL_HDR_PATH=${PREFIX}/${TRIPLE} headers_install + rm -r "${SRCDIR}/linux-${KERNV}" + } + + # + # ┏━┓ + # ╺━┫ + # ┗━┛╹ + # Build binutils and install them to ${PREFIX} + install_binutils() { + mkdir -p "${BLDDIR}/binutils" + cd "${BLDDIR}/binutils" + ${SRCDIR}/binutils-${BINV}/configure --target=${TRIPLE} \ + --prefix=${PREFIX} \ + --with-sysroot=${PREFIX}/${TRIPLE} \ + --disable-nls \ + --disable-shared \ + --disable-multilib + make configure-host + make LDFLAGS="${LDFLAGS} -all-static -static" + make install + rm -rf "${BLDDIR}/binutils" + rm -rf "${SRCDIR}/binutils-${BINV}" + } + + # + # ╻ ╻ + # ┗━┫ + # ╹╹ + # Build the musl libc + install_musl() { + cd "${SRCDIR}/musl-${MUSLV}" + ./configure --prefix=${PREFIX}/${TRIPLE} \ + --target=${TRIPLE} \ + --disable-gcc-wrapper \ + --disable-debug \ + --disable-shared \ + --disable-warning + make LDFLAGS="${LDFLAGS}" + make install + rm -rf "${SRCDIR}/musl-${MUSLV}" + } + + # + # ┏━╸ + # ┗━┓ + # ┗━┛╹ + # Build pcc linked against musl + install_pcc() { + mkdir -p "${BLDDIR}/pcc" + mkdir -p "${BLDDIR}/pcc-libs" + cd "${BLDDIR}/pcc" + ${SRCDIR}/pcc-${PCCV}/configure --target=${TRIPLE} \ + --with-libdir=${PREFIX}/${TRIPLE}/lib \ + --with-incdir=${PREFIX}/${TRIPLE}/include \ + --prefix=${PREFIX} + + make LDFLAGS="${LDFLAGS} -static" \ + PCCLIBDIR=${PREFIX}/${TRIPLE}/pcc/lib \ + PCCINCDIR=${PREFIX}/${TRIPLE}/pcc/include + make PCCLIBDIR=${PREFIX}/${TRIPLE}/pcc/lib \ + PCCINCDIR=${PREFIX}/${TRIPLE}/pcc/include \ + install + rm -rf "${BLDDIR}/pcc" + rm -rf "${SRCDIR}/pcc-${PCCV}" + } + + # + # ┏━┓ + # ┣━┓ + # ┗━┛╹ + # Build pcc libraries against musl + install_pcc_libs() { + cd "${BLDDIR}/pcc-libs" + ${SRCDIR}/pcc-libs-${PCCV}/configure --target=${TRIPLE} \ + --prefix=${PREFIX} + + make PCCLIBDIR=${PREFIX}/${TRIPLE}/pcc/lib \ + PCCINCDIR=${PREFIX}/${TRIPLE}/pcc/include + make PCCLIBDIR=${PREFIX}/${TRIPLE}/pcc/lib \ + PCCINCDIR=${PREFIX}/${TRIPLE}/pcc/include \ + install + rm -rf "${BLDDIR}/pcc-libs" + rm -rf "${SRCDIR}/pcc-libs-${PCCV}" + } + + # + # ┏━┓ + # ┃ + # ╹╹ + # Add pkg-config wrapper + install_pkgconfig() { + cat << EOF > "${PREFIX}/bin/${TRIPLE}-pkg-config" + #!/bin/sh + export PKG_CONFIG_SYSROOT_DIR=${PREFIX}/${TRIPLE} + export PKG_CONFIG_LIBDIR=${PREFIX}/${TRIPLE}/usr/lib/pkgconfig + export PKG_CONFIG_PATH=\$PKG_CONFIG_LIBDIR + + exec pkg-config --static "\$@" + EOF + chmod 755 "${PREFIX}/bin/${TRIPLE}-pkg-config" + } + + grab_sources + patch_sources + install_headers + install_binutils + install_musl + install_pcc + install_pcc_libs + install_pkgconfig + + # clean environment + rm -rf "${SRCDIR}" + rm -rf "${BLDDIR}" + rm -rf "${PREFIX}/share" + rm -f "${PREFIX}/lib/libiberty.a" + + cat << EOF | tee ${PREFIX}/README + TRIPLET : $TRIPLE + PREFIX : $PREFIX + PCC : $PCCV + BINUTILS: $BINV + MUSL : $MUSLV + KERNEL : $KERNV + EOF + +The process is (in theory) pretty simple: + +0. download and extract sources +1. patch everything +2. install linux headers +3. build binutils +4. build musl +5. build pcc/pcc-libs +6. (optionnal) add a pkg-config wrapper + +### 1. grabbing sources + +This part is pretty simple. You just need to choose which version of the +software you want to use. Here is my list at the time of writing: + ++ pcc : 1.1.0 ++ binutils : 2.25 ++ musl : 1.1.10 ++ kernel : 4.1.4 + +You can get the sources by following these links: + +ftp://pcc.ludd.ltu.se/pub/pcc-releases +ftp://ftp.gnu.org/gnu +http://www.musl-libc.org/releases +https://www.kernel.org/pub/linux/kernel/v4.x + +Once you have all your tarballs, extract them somewhere. + +### 2. patch everything + +Everything doesn't need patching, but when you're playing with musl, you'll +quickly realise how heavily softwares rely on the GNU libc. + +GregorR did all the dirty job here, and provide +[patches](https://github.com/GregorR/musl-cross/tree/master/patches) for use +with cross-compilers to work with musl. Check what's in, and grab those you +might need. + +The 1.1.0 version of pcc require some patching too, in order to work flawlessly +with an alternative libc. It *seems* to be fixed in 1.2.0 (DEVEL version), if +you're interrested. They fix the `configure` script to accept musl based +targets, and fix the default library pass of the compiler. + +pcc-1.1.0-musl.diff + + diff -urN a/config.sub b/config.sub + --- a/config.sub 2015-08-11 21:55:34.497619099 +0200 + +++ b/config.sub 2015-08-11 21:56:21.652621262 +0200 + @@ -120,7 +120,7 @@ + # Here we must recognize all the valid KERNEL-OS combinations. + maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` + case $maybe_os in + - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + + nto-qnx* | linux-gnu* | linux-dietlibc | linux-musl | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + @@ -1289,6 +1289,9 @@ + -linux-dietlibc) + os=-linux-dietlibc + ;; + + -linux-musl) + + os=-linux-musl + + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + +pcc-libs-1.1.0-musl.diff + diff -urN a/config.sub b/config.sub + --- a/config.sub 2015-08-11 21:55:34.497619099 +0200 + +++ b/config.sub 2015-08-11 21:56:21.652621262 +0200 + @@ -120,7 +120,7 @@ + # Here we must recognize all the valid KERNEL-OS combinations. + maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` + case $maybe_os in + - nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \ + + nto-qnx* | linux-gnu* | linux-dietlibc | linux-musl | linux-newlib* | linux-uclibc* | \ + uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + @@ -1289,6 +1289,9 @@ + -linux-dietlibc) + os=-linux-dietlibc + ;; + + -linux-musl) + + os=-linux-musl + + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + +pcc-1.1.0-deflibdirs.diff + + diff -urN a/cc/cc/cc.c b/cc/cc/cc.c + --- a/cc/cc/cc.c 2015-08-16 16:00:18.867457413 +0200 + +++ b/cc/cc/cc.c 2015-08-16 16:03:28.963466133 +0200 + @@ -207,9 +207,9 @@ + #endif + #ifndef DEFLIBDIRS /* default library search paths */ + #ifdef MULTIARCH_PATH + -#define DEFLIBDIRS { "/usr/lib/", 0 } + +#define DEFLIBDIRS { LIBDIR, 0 } + #else + -#define DEFLIBDIRS { "/usr/lib/", "/usr/lib/" MULTIARCH_PATH "/", 0 } + +#define DEFLIBDIRS { LIBDIR, LIBDIR MULTIARCH_PATH "/", 0 } + #endif + #endif + #ifndef DEFLIBS /* default libraries included */ + diff -urN a/os/linux/ccconfig.h b/os/linux/ccconfig.h + --- a/os/linux/ccconfig.h 2015-08-16 16:00:18.873457413 +0200 + +++ b/os/linux/ccconfig.h 2015-08-16 16:05:23.446471384 +0200 + @@ -48,9 +48,9 @@ + "-D__amd64", "-D__LP64__", "-D_LP64", NULL, } + #define DYNLINKER { "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2", NULL } + #ifndef MULTIARCH_PATH + -#define DEFLIBDIRS { "/usr/lib64/", 0 } + +#define DEFLIBDIRS { LIBDIR, 0 } + #else + -#define DEFLIBDIRS { "/usr/lib64/", "/usr/lib/" MULTIARCH_PATH "/", 0 } + +#define DEFLIBDIRS { LIBDIR, LIBDIR MULTIARCH_PATH "/", 0 } + #endif + #elif defined(mach_mips) + #define CPPMDADD { "-D__mips__", NULL, } + +### 3,4,5,6. build everything + +For this part, just check the appropriate sections in the original script. You +might want to enable shared libraries, or avoid compiling everything statically, +so tweak it however you want. + +For PCC, the `PCCINCDIR` and `PCCLIBDIR` are important, as they will tell the +compiler where are the PCC libraries. The `--with-incdir` and `--with-libdir` +parameters are used to tell the compiler where to search for default libraries, +so make sure you set them properly. + +### Enjoy! + +You compiler should be ready to go! You can test it by running the following +snippet: + + $ echo 'main(){}' > dummy.c + $ PATH="$HOME/cross/pcc-x86_64/bin:$PATH"; export PATH + $ x86_64-linux-musl-pcc dummy.c + +For the sake of the experience, I also built a gcc cross-compiler using the same +method, and tested both compilers on the [libressl](http://www.libressl.org) +code base. The packages are simply tar.bz2 archives of libressl installed on a +chroot (so there are only the libressl files): + + $ du -h libressl-*.pkg + 8.1M libressl-gcc-2.1.6.pkg + 8.9M libressl-glibc-2.1.6.pkg + 4.4M libressl-pcc-2.1.6.pkg + +Looks like we have a winner! + + +<!-- vim: set ft=markdown ts=4 et tw=80: --> diff --git a/config.mk b/config.mk @@ -27,7 +27,8 @@ PAGES = index.html \ 2015/02/do-you-gopher.html \ 2015/03/under-wendys-dress.html \ 2015/04/the-wrong-sysadmin.html \ - 2015/06/vomiting-colors.html + 2015/06/vomiting-colors.html \ + 2015/08/cross-compiling-with-pcc-and-musl.html FEEDS = rss/feed.xml EXTRA = css img vid data errors favicon.ico diff --git a/index.txt b/index.txt @@ -1,3 +1,4 @@ +* 0x0018 - [cross-compiling with PCC and musl](/2015/08/cross-compiling-with-pcc-and-musl.html) * 0x0017 - [Vomiting colors](/2015/06/vomiting-colors.html) * 0x0016 - [The wrong sysadmin](/2015/04/the-wrong-sysadmin.html) * 0x0015 - [Under Wendy's dress](/2015/03/under-wendys-dress.html)