projects/aports·blob master · refs

177 lines · 6.0 KiB

1#!/bin/sh
2
3set -e
4
5abuild_opts="-r"
6if [ "$1" = "-k" ] || [ "$1" = "--keep" ]; then
7 abuild_opts="$abuild_opts -k"
8 shift
9fi
10
11CTARGET="$1"
12CHOST="$CBUILD"
13CARCH="$CBUILD_ARCH"
14SUDO_APK=abuild-apk
15
16shift
17
18# optional cross build packages
19#: ${KERNEL_PKG=linux-firmware linux-lts}
20#: ${OPENSSH=openssh}
21#: ${LUA_APORTS=ncurses readline lua5.5 lua-cjson lua-filesystem lua-optarg lua-aports}
22#: ${MKINITFS=libcap-ng ncurses readline sqlite util-linux libaio lvm2 popt xz json-c argon2 cryptsetup kmod lddtree mkinitfs}
23# Some languages that need to be cross compiled, for java and others we do not yet have an automated process
24: ${GO=community/go}
25: ${LLVM_DEPS=libffi brotli libev c-ares cunit nghttp2 nghttp3 libidn2 libunistring libpsl curl libssh2 libxml2}
26: ${RUST=llvm22 rust}
27#: ${GHC=community/llvm15 community/ghc}
28#: ${COMPILER_PKG=$GO $LLVM_DEPS $RUST $GHC}
29
30if [ -z "$CTARGET" ]; then
31 program=$(basename $0)
32 cat <<EOF
33usage: $program CTARGET_ARCH
34
35This script creates a local cross-compiler, and uses it to
36cross-compile an Alpine Linux base system for new architecture.
37
38Steps for introducing new architecture include:
39- optional: joining the #alpine-ports channel on oftc
40- adding the compiler triplet and arch type to abuild
41- adjusting build rules for packages that are arch aware:
42 gcc, openssl, linux-headers, musl
43- create new kernel config for linux-lts
44- optionally reserve an architecture name in apk-tools
45
46After these steps the initial cross-build can be completed
47by running this with the target arch as parameter, e.g.:
48 ./$program aarch64
49
50The cross-compiler generated by this script is not intended
51nor supported for any use other than building the base system
52and other packages in the bootstrap path.
53
54EOF
55 return 1
56fi
57
58# get abuild configurables
59sharedir=${ABUILD_SHAREDIR:-/usr/share/abuild}
60[ -e "$sharedir"/functions.sh ] || (echo "abuild not found" ; exit 1)
61. "$sharedir"/functions.sh
62[ -z "$CBUILD_ARCH" ] && die "abuild is too old (use 2.29.0 or later)"
63[ -z "$CBUILDROOT" ] && die "CBUILDROOT not set for $CTARGET_ARCH"
64export CBUILD CBUILD_ARCH CHOST CARCH CTARGET CTARGET_ARCH
65
66# deduce aports directory
67[ -z "$APORTS" ] && APORTS=$(realpath $(dirname $0)/../)
68[ -e "$APORTS/main/build-base" ] || die "Unable to deduce aports base checkout"
69
70apkbuildname() {
71 local repo="${1%%/*}"
72 local pkg="${1##*/}"
73 [ "$repo" = "$1" ] && repo="main"
74 echo $APORTS/$repo/$pkg/APKBUILD
75}
76
77msg() {
78 [ -n "$quiet" ] && return 0
79 local prompt="$GREEN>>>${NORMAL}"
80 local name="${BLUE}bootstrap-${CTARGET_ARCH}${NORMAL}"
81 printf "${prompt} ${name}: %s\n" "$1" >&2
82}
83
84if [ ! -d "$CBUILDROOT" ]; then
85 msg "Creating sysroot in $CBUILDROOT"
86 mkdir -p "$CBUILDROOT/etc/apk/keys"
87 # /etc/apk/keys and ~/.abuild/ can contain files with the same names.
88 # if that is the case, cp will abort copying and fail. Then on the next
89 # run of the bootstrap script, 1) the keys are not in the sysroot and
90 # 2) the apk database is not initialized the sysroot
91 # Thus it's unusable at that point and needs to be deleted manually.
92 cp -a /etc/apk/keys/* "$CBUILDROOT/etc/apk/keys"
93 cp -a ~/.abuild/*.pub "$CBUILDROOT/etc/apk/keys"
94 if [ "$BOOTSTRAP_USR_MERGED" = "1" ]; then
95 mkdir -p "$CBUILDROOT"/usr/lib "$CBUILDROOT"/usr/bin "$CBUILDROOT"/usr/sbin
96 ln -s usr/bin usr/sbin usr/lib "$CBUILDROOT"/
97 fi
98 ${SUDO_APK} add --quiet --initdb --arch $CTARGET_ARCH --root $CBUILDROOT
99fi
100
101msg "Building cross-compiler"
102
103# Build and install cross binutils (--with-sysroot)
104BOOTSTRAP=nobase APKBUILD=$(apkbuildname binutils) abuild $abuild_opts
105
106if ! CHOST=$CTARGET CARCH=$CTARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild up2date 2>/dev/null; then
107 # C-library headers for target
108 CHOST=$CTARGET CARCH=$CTARGET_ARCH BOOTSTRAP=nocc APKBUILD=$(apkbuildname musl) abuild $abuild_opts
109
110 # Minimal cross GCC
111 EXTRADEPENDS_HOST="musl-dev" \
112 BOOTSTRAP=nolibc APKBUILD=$(apkbuildname gcc) abuild $abuild_opts
113
114 # Cross build bootstrap C-library for the target
115 EXTRADEPENDS_BUILD="gcc-pass2-$CTARGET_ARCH" \
116 CHOST=$CTARGET CARCH=$CTARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild $abuild_opts
117fi
118
119# Build libucontext without docs and pkgconfig file as a dependency for gcc-gdc
120EXTRADEPENDS_BUILD="gcc-pass2-$CTARGET_ARCH" \
121EXTRADEPENDS_TARGET="musl-dev" \
122CHOST=$CTARGET CARCH=$CTARGET_ARCH BOOTSTRAP=nobase APKBUILD=$(apkbuildname libucontext) abuild $abuild_opts
123
124# Full cross GCC
125EXTRADEPENDS_TARGET="musl-dev libucontext-dev" \
126BOOTSTRAP=nobase APKBUILD=$(apkbuildname gcc) abuild $abuild_opts
127
128# Cross build-base
129BOOTSTRAP=nobase APKBUILD=$(apkbuildname build-base) abuild $abuild_opts
130
131msg "Cross building base system"
132
133# Implicit dependencies for early targets
134export EXTRADEPENDS_TARGET="libgcc libstdc++ musl-dev"
135
136# On a few architectures like riscv64 we need to account for
137# gcc requiring -latomic to be set explicitly if a C[++]11 program
138# uses atomics (e.g. #include <atomic>):
139# https://github.com/riscv/riscv-gnu-toolchain/issues/183#issuecomment-253721765
140# The reason gcc itself is needed is because .so is in that package,
141# not in libatomic.
142if [ "$CTARGET_ARCH" = "riscv64" ]; then
143 NEEDS_LIBATOMIC="yes"
144fi
145
146if [ $# -eq 0 ]; then
147 set -- fortify-headers linux-headers musl zlib pkgconf gmp mpfr4 \
148 mpc1 isl26 libucontext zstd binutils gcc make file patch openssl \
149 busybox build-base ca-certificates libmd bsd-compat-headers libbsd \
150 apk-tools libcap openrc alpine-conf alpine-baselayout alpine-keys \
151 alpine-base attr acl fakeroot tar pax-utils lzip abuild \
152 $OPENSSH \
153 $MKINITFS \
154 $COMPILER_PKG \
155 $KERNEL_PKG \
156 $LUA_APORTS
157fi
158
159for PKG; do
160 CHOST=$CTARGET CARCH=$CTARGET_ARCH BOOTSTRAP=bootimage APKBUILD=$(apkbuildname $PKG) abuild $abuild_opts
161
162 case "$PKG" in
163 fortify-headers)
164 # Additional implicit dependencies once built
165 EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET $PKG"
166 ;;
167 gcc)
168 if [ "$NEEDS_LIBATOMIC" = "yes" ]; then
169 EXTRADEPENDS_TARGET="$EXTRADEPENDS_TARGET $PKG"
170 fi
171 ;;
172 build-base)
173 # After build-base, that alone is sufficient dependency in the target
174 EXTRADEPENDS_TARGET="busybox $PKG"
175 ;;
176 esac
177done