tnew post: pcc + musl cross-compiler - monochromatic - monochromatic blog: http://blog.z3bra.org
(HTM) git clone git://z3bra.org/monochromatic
(DIR) Log
(DIR) Files
(DIR) Refs
---
(DIR) commit 7f2589bdb6500984bbc4717aadf3d189685bdfc5
(DIR) parent 41e38839b23d8ccea33dd48b439143889effbef9
(HTM) Author: z3bra <willyatmailoodotorg>
Date: Sun, 16 Aug 2015 19:53:58 +0200
new post: pcc + musl cross-compiler
Diffstat:
A 2015/08/cross-compiling-with-pcc-a… | 380 ++++++++++++++++++++++++++++++
M config.mk | 3 ++-
M index.txt | 1 +
3 files changed, 383 insertions(+), 1 deletion(-)
---
(DIR) diff --git a/2015/08/cross-compiling-with-pcc-and-musl.txt b/2015/08/cross-compiling-with-pcc-and-musl.txt
t@@ -0,0 +1,380 @@
+# [cross-compiling with PCC and musl](#)
+## — 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: -->
(DIR) diff --git a/config.mk b/config.mk
t@@ -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
(DIR) diff --git a/index.txt b/index.txt
t@@ -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)