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](#)
       +## &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: -->
 (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)