交叉编译器,目标平台:Alpine

出自Alpine Linux
此材料已过时...

这篇文档写于切换到 musl 之前,所以很可能完全无法工作 (讨论)

此页面解释了如何在 ArchLinux (x86 和 x86_64) 上设置以 Alpine 为目标的交叉编译器。只有少数情况下您会想要这样做。我必须这样做是因为我想将 GHC 移植到 Alpine,而要做到这一点,您需要从一些已编译的 GHC 二进制文件开始。这意味着需要从某些二进制文件已经可用的系统进行交叉编译。

我使用 Buildroot 来设置我的交叉编译器。这些说明针对 Buildroot 2013.05 和 Alpine 2.6.0,两者均于 2013 年 5 月发布。此 Buildroot 安装的特定版本(如我配置的那样)是

  • 内核头文件 v3.9.2
  • uClibc v0.9.33.2
  • binutils v2.23.2
  • gcc v4.7.3
  • gmp v5.1.1
  • mpc v1.0.1
  • mpfr v3.1.2 (Alpine 当前使用 mpfr3-3.1.1)
  • m4 v1.4.16
  • autoconf v2.68 (Alpine 当前使用 autoconf-2.69)
  • automake v1.11.6 (Alpine 当前使用 automake-1.13.1)
  • libiconv v1.14 (Alpine 当前使用 1.12)
  • libtool v2.2.10 (Alpine 当前使用 libtool-2.4.2)
  • ncurses v5.9
  • libffi v3.0.13

Buildroot 还安装了 BusyBox v1.12.0,但我忽略了它。

下面的说明还描述了如何在 Buildroot 工具之上安装交叉编译 LLVM 和 Clang v3.2。这可能对某些目的有用。

如果您想使用这些说明作为基础,对更新版本的 Buildroot 或以更新版本的 Alpine 为目标做同样的事情,请务必检查添加到 Alpine ports 树的补丁,特别是 gcc 或 uClibc,在 2.6.0 之后。

  1. 在 Arch 系统上,安装以下软件包

    pacman -S less man-db man-pages licenses procps-ng psmisc sysfsutils \ base-devel openssh cpio elfutils gperf rsync unzip vim wget zip

  2. 在 Arch 系统上,执行以下操作

    mkdir ~/python2-path ln -s /usr/bin/python2 ~/python2-path/python export PATH=$HOME/python2-path:$PATH

  3. 在 Arch 系统上,准备构建交叉编译器的源代码和补丁。

    mkdir -p $HOME/sources/patches && cd $HOME/sources get_from_aports() ( local APORTS_URL=https://git.alpinelinux.org/aports/plain mkdir -p $1 cd $1 || return 1 if [ -n "$3" ]; then wget -N -O $(printf '%02d-%s' $3 ${2##*/}) $APORTS_URL/main/$2 else wget -N $APORTS_URL/main/$2 fi ) get_from_gist() ( local GIST_URL=https://gist.github.com/dubiousjim/5603159/raw mkdir -p $1 cd $1 || return 1 if [ -n "$3" ]; then wget -N -O $(printf '%02d-%s' $3 ${2##*/}) $GIST_URL/$2 else wget -N $GIST_URL/$2 fi ) get_from_aports patches/binutils/2.23.2 binutils/binutils-ld-fix-static-linking.patch get_from_aports patches/gcc/4.7.3 gcc/pt_gnu_eh_frame.patch 1 get_from_aports patches/gcc/4.7.3 gcc/uclibc-getipinfo.patch 2 get_from_aports patches/gcc/4.7.3 gcc/gcc-4.7-dynamic-linker.patch 3 get_from_aports patches/gcc/4.7.3 gcc/gcc-4.6-pr32219.patch 4 get_from_aports patches/gcc/4.7.3 gcc/gcc-pure64.patch 5 sed -i -e 's/\$(ESP_NOPIE_CFLAGS) //' patches/gcc/4.7.3/03-gcc-4.7-dynamic-linker.patch get_from_aports patches/gmp/5.1.1 gmp5/gmp-4.1.4-noexecstack.patch # work around rpath issue get_from_gist patches/libiconv/1.14 libiconv-configure.patch get_from_aports patches/uClibc/0.9.33.2 libc0.9.32/APKBUILD source=$( cd patches/uClibc/0.9.33.2 && . APKBUILD && echo $source ) j=1 for i in $source; do case $i in *.patch) get_from_aports patches/uClibc/0.9.33.2 libc0.9.32/$i $((j++)) esac done # finally, set abi version and remove unsupported warnings c flag get_from_gist patches/uClibc/0.9.33.2 uclibc-Rules.mak.patch $j case `uname -m` in x86_64) ARCH=x86_64; H=$ARCH T=$ARCH;; i?86) ARCH=x86 H=i686 T=i486;; *) echo Unknown architecture;; esac get_from_aports . libc0.9.32/uclibcconfig.$ARCH echo '# USE_OLD_VFPRINTF is not set' >> uclibcconfig.$ARCH BUILDROOTVER=2013.05-rc2 wget -N https://buildroot.uclibc.org/downloads/buildroot-$BUILDROOTVER.tar.bz2 get_from_gist . config.$ARCH get_from_gist . buildroot-makes.patch


  4. 现在,编译 buildroot

    cd && tar -xjf sources/buildroot-$BUILDROOTVER.tar.bz2 cd buildroot-$BUILDROOTVER && patch -p1 -i ../sources/buildroot-makes.patch BUILDROOT=$HOME/buildroot-$ARCH mkdir $BUILDROOT && cd $BUILDROOT && cp ../sources/config.$ARCH .config make O=$PWD -C ../buildroot-$BUILDROOTVER 2>&1 | tee build.log

  5. 如果编译成功,那么

    export PATH=$PATH:$BUILDROOT/host/usr/bin

  6. (可选) 下载并编译 LLVM 和 clang。(这需要 #1915 中的补丁,该补丁尚未进入 aports 树。)

    cd $HOME/sources wget -N https://llvm.net.cn/releases/3.2/llvm-3.2.src.tar.gz wget -N https://llvm.net.cn/releases/3.2/clang-3.2.src.tar.gz get_from_aports . llvm/llvm-3.2-alpine-linux.patch cd && tar -xzf sources/llvm-3.2.src.tar.gz && tar -xzf sources/clang-3.2.src.tar.gz && cd llvm-3.2.src rm -rf tools/clang && mv ../clang-3.2.src tools/clang patch -p1 < ../sources/llvm-3.2-alpine-linux.patch cd && mkdir llvm-build.$ARCH && cd llvm-build.$ARCH ../llvm-3.2.src/configure --prefix=$BUILDROOT/host/usr \ --build=$H-pc-linux-gnu --host=$H-pc-linux-gnu --target=$T-buildroot-linux-uclibc \ --with-gcc-toolchain=$BUILDROOT/host/usr --with-default-sysroot=$BUILDROOT/staging \ --enable-jit --enable-pic --enable-assertions --enable-optimized --enable-shared --disable-docs \ --enable-targets=x86,x86_64 | tee build.log { make && make install; } 2>&1 | tee -a build.log

现在在 Arch 系统上,您可以这样做

echo 'int main(void) {return 0;}' > test.c i486-buildroot-linux-uclibc-gcc -o test test.c

或者您可以使用 i486-buildroot-linux-uclibc-clang 代替。

生成的二进制文件不会在 Arch 系统上运行(或者从 Arch chroot 内启动的 shell 中运行,如果 Arch 系统在 Alpine 系统内的 chroot 上,就像我的情况一样)。但它将在 Alpine 系统上运行(或者从 Arch chroot 之外启动的 shell 中运行)。