blob: 9cb78c3be333888e2adc9f0aee8732c8b016cc33 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
#!/bin/sh
TARGET_ARCH="$1"
SUDO_APK=abuild-apk
# optional cross build packages
KERNEL_PKG="linux-firmware linux-vanilla"
# get abuild configurables
[ -e /usr/share/abuild/functions.sh ] || (echo "abuild not found" ; exit 1)
CBUILDROOT="$(CTARGET=$TARGET_ARCH . /usr/share/abuild/functions.sh ; echo $CBUILDROOT)"
. /usr/share/abuild/functions.sh
[ -z "$CBUILD_ARCH" ] && die "abuild is too old (use git snapshot from cross-build branch)"
# deduce aports directory
[ -z "$APORTS" ] && APORTS=$(realpath $(dirname $0)/../)
[ -e "$APORTS/main/build-base" ] || die "Unable to deduce aports base checkout"
apkbuildname() {
echo $APORTS/main/$1/APKBUILD
}
msg() {
[ -n "$quiet" ] && return 0
local prompt="$GREEN>>>${NORMAL}"
local name="${BLUE}bootstrap-${TARGET_ARCH}${NORMAL}"
printf "${prompt} ${name}: %s\n" "$1" >&2
}
setup_sysroot() {
[ -e "$CBUILDROOT" ] && return 0
msg "Creating sysroot in $CBUILDROOT"
mkdir -p "$CBUILDROOT/etc/apk/keys"
cp -a /etc/apk/keys/* "$CBUILDROOT/etc/apk/keys"
${SUDO_APK} add --quiet --initdb --arch $TARGET_ARCH --root $CBUILDROOT
}
create_cross_compiler() {
msg "Building cross-compiler"
# Prepare local build environment
apk info --quiet --installed build-base gcc-gnat || ${SUDO_APK} add build-base gcc-gnat
# Build and install cross binutils (--with-sysroot)
CTARGET=$TARGET_ARCH APKBUILD=$(apkbuildname binutils) abuild up2date >& /dev/null
if [ $? -ne 0 ]; then
CTARGET=$TARGET_ARCH APKBUILD=$(apkbuildname binutils) abuild -r || return 1
${SUDO_APK} add --repository "$REPODEST/main" binutils-$TARGET_ARCH || return 1
fi
# Build and install cross GCC
CTARGET=$TARGET_ARCH APKBUILD=$(apkbuildname gcc) abuild up2date >& /dev/null
if [ $? -ne 0 ]; then
# Build bootstrap C-library for target if needed
CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild up2date >& /dev/null
if [ $? -ne 0 ]; then
# musl does not need GCC for headers installation, skipped step.
# CTARGET=$TARGET_ARCH BOOTSTRAP=noheaders abuild
# Hack: Install C-library headers for target sysroot
CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild clean unpack prepare install_sysroot_headers || return 1
# Build minimal cross GCC (--with-newlib --enable-threads=no --disable-bootstrap)
CTARGET=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname gcc) abuild -r || return 1
# Cross build bootstrap C-library for the target
${SUDO_APK} --quiet del gcc-$TARGET_ARCH g++-$TARGET_ARCH gcc-gnat-$TARGET_ARCH
${SUDO_APK} add --repository "$REPODEST/main" gcc-pass2-$TARGET_ARCH || return 1
CHOST=$TARGET_ARCH BOOTSTRAP=nolibc APKBUILD=$(apkbuildname musl) abuild -r || return 1
${SUDO_APK} --quiet del gcc-pass2-$TARGET_ARCH
fi
# Build cross GCC
apk info --quiet --installed --root "$CBUILDROOT" musl-dev || \
${SUDO_APK} --root "$CBUILDROOT" add --repository "$REPODEST/main" musl-dev \
|| return 1
CTARGET=$TARGET_ARCH APKBUILD=$(apkbuildname gcc) abuild -r || return 1
${SUDO_APK} add --repository "$REPODEST/main" gcc-gnat gcc-$TARGET_ARCH g++-$TARGET_ARCH gcc-gnat-$TARGET_ARCH \
|| return 1
fi
}
cross_compile_base() {
msg "Cross building base system"
# remove possible old pass2 gcc, and add implicit host prerequisite packages
apk info --quiet --installed gcc-pass2-$TARGET_ARCH && ${SUDO_APK} del gcc-pass2-$TARGET_ARCH
apk info --quiet --installed gcc-gnat gcc-$TARGET_ARCH g++-$TARGET_ARCH gcc-gnat-$TARGET_ARCH || \
${SUDO_APK} add --repository "$REPODEST/main" gcc-gnat gcc-$TARGET_ARCH g++-$TARGET_ARCH gcc-gnat-$TARGET_ARCH \
|| return 1
apk info --quiet --installed --root "$CBUILDROOT" libgcc musl-dev || \
${SUDO_APK} --root "$CBUILDROOT" add --repository "$REPODEST/main" libgcc musl-dev \
|| return 1
# ordered cross-build
for PKG in fortify-headers linux-headers musl libc-dev \
busybox busybox-initscripts binutils make pkgconf \
zlib openssl libfetch apk-tools \
gmp mpfr3 mpc1 isl cloog gcc \
openrc alpine-conf alpine-baselayout alpine-keys alpine-base build-base \
attr libcap patch sudo acl fakeroot tar \
pax-utils abuild openssh \
ncurses util-linux lvm2 popt xz cryptsetup kmod lddtree mkinitfs \
$KERNEL_PKG ; do
CHOST=$TARGET_ARCH BOOTSTRAP=bootimage APKBUILD=$(apkbuildname $PKG) abuild -r || exit 1
case "$PKG" in
fortify-headers | libc-dev | build-base)
# headers packages which are implicit but mandatory dependency
apk info --quiet --installed --root "$CBUILDROOT" $PKG || \
${SUDO_APK} --update --root "$CBUILDROOT" --repository "$REPODEST/main" add $PKG \
|| return 1
;;
musl | gcc)
# target libraries rebuilt, force upgrade
[ "$(apk upgrade --root "$CBUILDROOT" --repository "$REPODEST/main" --available --simulate | wc -l)" -gt 1 ] &&
${SUDO_APK} upgrade --root "$CBUILDROOT" --repository "$REPODEST/main" --available
;;
esac
done
}
if [ -z "$TARGET_ARCH" ]; then
local program=$(basename $0)
cat <<EOF
usage: $program TARGET_ARCH
This script creates a local cross-compiler, and uses it to
cross-compile an Alpine Linux base system for new architecture.
Steps for introducing new architecture include:
- adding the compiler tripler and arch type to abuild
- adding the arch type detection to apk-tools
- adjusting build rules for packages that are arch aware:
gcc, openssl, linux-headers
- create new kernel config for linux-vanilla
After these steps the initial cross-build can be completed
by running this with the target arch as parameter, e.g.:
./$program aarch64
EOF
return 1
fi
setup_sysroot && create_cross_compiler && cross_compile_base
|