xref: /aosp_15_r20/external/toybox/scripts/mcm-buildall.sh (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1#!/bin/bash
2
3# Script to build all cross and native compilers supported by musl-libc.
4# This isn't directly used by toybox, but is useful for testing.
5
6trap "exit 1" INT
7
8if [ ! -d litecross ]
9then
10  echo Run this script in musl-cross-make directory to make "ccc" directory.
11  echo
12  echo "  "git clone https://github.com/richfelker/musl-cross-make
13  echo "  "cd musl-cross-make
14  echo '  ~/toybox/scripts/mcm-buildall.sh'
15  exit 1
16fi
17
18# List of known targets. The format is TARGET[@RENAME]:EXTRA:CONFIG resulting
19# in a gcc tuple TARGET-linux-muslEXTRA with CONFIG appended to $GCC_CONFIG
20# (and thus the gcc ./configure command line). So i686:: builds i686-linux-musl
21# and sh2eb::fdpic:--with-cpu=mj2 builds sh2eb-linux-muslfdpic adding
22# --with-cpu=mj2 to the gcc ./configure command line. @RENAME (if present)
23# changes the TARGET part of the toolchain prefix names afterwards.
24
25TARGETS=(i686:: aarch64:eabi:
26  armv4l:eabihf:"--with-arch=armv5t --with-float=soft"
27  "armv5l:eabihf:--with-arch=armv5t --with-fpu=vfpv2 --with-float=hard"
28  "armv7l:eabihf:--with-arch=armv7-a --with-fpu=vfpv3-d16 --with-float=hard"
29  "armv7m:eabi:--with-arch=armv7-m --with-mode=thumb --disable-libatomic --enable-default-pie"
30  armv7r:eabihf:"--with-arch=armv7-r --enable-default-pie"
31  i486:: m68k:: microblaze:: mips:: mips64:: mipsel:: or1k:: powerpc::
32  powerpc64:: powerpc64le:: riscv32:: riscv64:: s390x::
33  sh2eb:fdpic:--with-cpu=mj2
34  sh4::--enable-incomplete-targets sh4eb::--enable-incomplete-targets
35  x86_64::--with-mtune=nocona x86_64@x32:x32:
36)
37
38# All toolchains after the first are themselves cross compiled (so they
39# can be statically linked against musl on the host, for binary portability.)
40: ${BOOTSTRAP:=$(uname -m)} ${OUTPUT:="$PWD/ccc"}
41
42# Move the corresponding target to the front so rest of targets get built
43# with full instead of partial -host compiler (missing threads and NLS and such)
44unset TEMP
45for i in $(seq 0 $((${#TARGETS[@]}-1)));
46do
47  [ "${TARGETS[$i]}" == "${TARGETS[$i]#"$BOOTSTRAP:"}" ] && continue
48  TEMP="${TARGETS[$i]}"
49  TARGETS[$i]="$TARGETS[0]"
50  TARGETS[0]="$TEMP"
51  break;
52done
53[ -z "$TEMP" ] && { echo unknown target "$BOOTSTRAP"; exit 1; }
54
55if [ "$1" == clean ]
56then
57  rm -rf ccc host-* *.log # Not gonna rm -rf "$OUTPUT" blindly, could be $HOME
58  make clean
59  exit
60fi
61
62make_toolchain()
63{
64
65  # Set cross compiler path
66  LP="$PATH"
67  if [ "$TYPE" == host ]
68  then
69    OUTPUT="$PWD/host-$TARGET"
70    EXTRASUB=y
71  else
72    if [ "$TYPE" == static ]
73    then
74      HOST=$BOOTSTRAP
75      [ "$TARGET" = "$HOST" ] && LP="$PWD/host-$HOST/bin:$LP" &&
76        GCC_CONFIG="--build=${TARGET%%-*}-donotmatch-linux $GCC_CONFIG"
77      TYPE=cross
78      EXTRASUB=y
79      LP="$OUTPUT/$HOST-cross/bin:$LP"
80    else
81      HOST="$TARGET"
82      export NATIVE=y
83      LP="$OUTPUT/${RENAME:-$TARGET}-cross/bin:$LP"
84      [ -z "$(PATH="$LP" which $TARGET-cc)" ] &&
85         echo "no $TARGET-cc in $LP" && return
86    fi
87    COMMON_CONFIG="CC=\"$HOST-gcc -static --static\" CXX=\"$HOST-g++ -static --static\""
88    export -n HOST
89    OUTPUT="$OUTPUT/${RENAME:-$TARGET}-$TYPE"
90  fi
91
92  # Skip outputs that already exist
93  if [ -e "$OUTPUT.sqf" ] || [ -e "$OUTPUT/bin/$TARGET-cc" ] ||
94     [ -e "$OUTPUT/bin/cc" ]
95  then
96    return
97  fi
98
99  # Change title bar to say what we're currently building
100
101  echo === building $TARGET-$TYPE
102  echo -en "\033]2;$TARGET-$TYPE\007"
103
104  rm -rf build/"$TARGET" "$OUTPUT" &&
105  set -x &&
106  PATH="$LP" make OUTPUT="$OUTPUT" TARGET="$TARGET" \
107    GCC_CONFIG="--disable-nls --disable-libquadmath --disable-decimal-float --disable-multilib --enable-languages=c,c++ $GCC_CONFIG" \
108    COMMON_CONFIG="CFLAGS=\"$CFLAGS -g0 -O2\" CXXFLAGS=\"$CXXFLAGS -g0 -O2\" \
109    LDFLAGS=\"$LDFLAGS -s\" $COMMON_CONFIG" install -j$(nproc) || exit 1
110  set +x
111  echo -e '#ifndef __MUSL__\n#define __MUSL__ 1\n#endif' \
112    >> "$OUTPUT/${EXTRASUB:+$TARGET/}include/features.h"
113
114  if [ ! -z "$RENAME" ] && [ "$TYPE" == cross ]
115  then
116    CONTEXT="output/$RENAME-cross/bin"
117    for i in "$CONTEXT/$TARGET-"*
118    do
119      X="$(echo $i | sed "s@.*/$TARGET-\([^-]*\)@\1@")"
120      ln -sf "$TARGET-$X" "$CONTEXT/$RENAME-$X"
121    done
122  fi
123
124  # Prevent cross compiler reusing dynamically linked host build files for
125  # $BOOTSTRAP arch
126  [ -z "$TYPE" ] && {
127    [ -e musl-git-master ] && mv musl-git-master keep-this-dir
128    make clean
129    [ -e keep-this-dir ] && mv keep-this-dir musl-git-master
130  }
131
132  if [ "$TYPE" == native ]
133  then
134    # gcc looks in "../usr/include" but not "/bin/../include" (relative to the
135    # executable). That means /usr/bin/gcc looks in /usr/usr/include, so that's
136    # not a fix either. So add a NOP symlink as a workaround for The Crazy.
137    ln -s . "$OUTPUT/usr" || exit 1
138    [ ! -z "$(which mksquashfs 2>/dev/null)" ] &&
139      mksquashfs "$OUTPUT" "$OUTPUT.sqf" -all-root &&
140      [ -z "$CLEANUP" ] && rm -rf "$OUTPUT"
141  fi
142}
143
144split_tuple()
145{
146  PART1=${1/:*/}
147  PART3=${1/*:/}
148  PART2=${1:$((${#PART1}+1)):$((${#1}-${#PART3}-${#PART1}-2))}
149
150  # Do we need to rename this toolchain after building it?
151  RENAME=${PART1/*@/}
152  [ "$RENAME" == "$PART1" ] && RENAME=
153  PART1=${PART1/@*/}
154  TARGET=${PART1}-linux-musl${PART2}
155}
156
157# Expand compressed target into binutils/gcc "tuple" and call make_toolchain
158make_tuple()
159{
160  split_tuple "$@"
161
162  [ -z "$NOCLEAN" ] && rm -rf build
163
164  for TYPE in "${@:2}"
165  do
166    TYPE=$TYPE TARGET=$TARGET GCC_CONFIG="$PART3" RENAME="$RENAME" \
167      make_toolchain 2>&1 | tee "$OUTPUT"/log/${RENAME:-$PART1}-${TYPE}.log
168  done
169}
170
171patch_mcm()
172{
173  # musl-cross-make commit fe915821b652 has been current for a year and a half,
174  # and doesn't even use the latest musl release by default, so fix it up.
175
176  # Select newer package versions and don't use dodgy mirrors
177  sed -i 's/mirror//;s/\(LINUX_VER =\).*/\1 6.8/;s/\(GCC_VER =\).*/\1 11.2.0/' \
178    Makefile &&
179  echo 'c9ab5b95c0b8e9e41290d3fc53b4e5cb2e8abb75  linux-6.8.tar.xz' > \
180    hashes/linux-6.8.tar.xz.sha1 &&
181  # mcm redundantly downloads tarball if hash file has newer timestamp,
182  # and it whack-a-moles how to download kernels by version for some reason.
183  touch -d @1 hashes/linux-6.8.tar.xz.sha1 &&
184  sed -i 's/\(.*linux-\)3\(.*\)v3.x/\16\2v6.x/' Makefile &&
185
186  # nommu toolchains need to vfork()+pipe, and or1k has different kernel arch
187  sed -i -e 's/--enable-fdpic$/& --enable-twoprocess/' \
188      -e '/or1k/!s/^\(TARGET_ARCH_MANGLED = \)\(.*\)/\1$(patsubst or1k,openrisc,\2)/' \
189      litecross/Makefile &&
190
191  # Packages detect nommu via the absence of fork(). Musl provides a broken
192  # fork() on nommu builds that always returns -ENOSYS at runtime. Rip it out.
193  # (Currently only for superh/jcore since no generic #ifdef __FDPIC__ symbol.)
194
195  PP=patches/musl-"$(sed -n 's/MUSL_VER[ \t]*=[ \t]*//p' Makefile)" &&
196  mkdir -p "$PP" &&
197  cat > "$PP"/0001-nommu.patch << 'EOF' &&
198--- a/src/legacy/daemon.c
199+++ b/src/legacy/daemon.c
200@@ -17,3 +17,3 @@
201
202-	switch(fork()) {
203+	switch(vfork()) {
204 	case 0: break;
205@@ -25,3 +25,3 @@
206
207-	switch(fork()) {
208+	switch(vfork()) {
209 	case 0: break;
210--- a/src/misc/forkpty.c
211+++ b/src/misc/forkpty.c
212@@ -8,2 +8,3 @@
213
214+#ifndef __SH_FDPIC__
215 int forkpty(int *pm, char *name, const struct termios *tio, const struct winsize *ws)
216@@ -57,1 +58,2 @@
217 }
218+#endif
219--- a/src/misc/wordexp.c
220+++ b/src/misc/wordexp.c
221@@ -25,2 +25,3 @@
222
223+#ifndef __SH_FDPIC__
224 static int do_wordexp(const char *s, wordexp_t *we, int flags)
225@@ -177,2 +178,3 @@
226 }
227+#endif
228
229--- a/src/process/fork.c
230+++ b/src/process/fork.c
231@@ -7,2 +7,3 @@
232
233+#ifndef __SH_FDPIC__
234 static void dummy(int x)
235@@ -37,1 +38,2 @@
236 }
237+#endif
238--- a/Makefile
239+++ b/Makefile
240@@ -100,3 +100,3 @@
241 	cp $< $@
242-	sed -n -e s/__NR_/SYS_/p < $< >> $@
243+	sed -e s/__NR_/SYS_/ < $< >> $@
244
245--- a/arch/sh/bits/syscall.h.in
246+++ b/arch/sh/bits/syscall.h.in
247@@ -2,3 +2,5 @@
248 #define __NR_exit                   1
249+#ifndef __SH_FDPIC__
250 #define __NR_fork                   2
251+#endif
252 #define __NR_read                   3
253EOF
254
255  # I won't sign the FSF's copyright assignment
256  tee $(for i in patches/gcc-*; do echo $i/099-vfork.patch; done) > /dev/null << 'EOF'
257--- gcc-8.3.0/fixincludes/procopen.c	2005-08-14 19:50:43.000000000 -0500
258+++ gcc-bak/fixincludes/procopen.c	2020-02-06 23:27:15.408071708 -0600
259@@ -116,3 +116,3 @@
260    */
261-  ch_id = fork ();
262+  ch_id = vfork ();
263   switch (ch_id)
264EOF
265
266  # Fix a gcc bug that breaks x86-64 build in gcc 11.2.0,
267  # from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100017#c20
268
269  PP=patches/gcc-"$(sed -n 's/GCC_VER[ \t]*=[ \t]*//p' Makefile)" &&
270  mkdir -p "$PP" &&
271  cat > "$PP"/0006-fixinc.patch << 'EOF' &&
272diff -ruN gcc-11.2.0.orig/configure gcc-11.2.0/configure
273--- gcc-11.2.0.orig/configure	2021-07-28 01:55:06.628278148 -0500
274+++ gcc-11.2.0/configure	2023-11-17 03:07:53.819283027 -0600
275@@ -16478,7 +16478,7 @@
276 fi
277
278
279-RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
280+RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET -nostdinc++"
281
282 { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to find the target ar" >&5
283 $as_echo_n "checking where to find the target ar... " >&6; }
284diff -ruN gcc-11.2.0.orig/configure.ac gcc-11.2.0/configure.ac
285--- gcc-11.2.0.orig/configure.ac	2021-07-28 01:55:06.628278148 -0500
286+++ gcc-11.2.0/configure.ac	2023-11-17 03:08:05.975282593 -0600
287@@ -3520,7 +3520,7 @@
288 ACX_CHECK_INSTALLED_TARGET_TOOL(WINDRES_FOR_TARGET, windres)
289 ACX_CHECK_INSTALLED_TARGET_TOOL(WINDMC_FOR_TARGET, windmc)
290
291-RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
292+RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET -nostdinc++"
293
294 GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
295 GCC_TARGET_TOOL(as, AS_FOR_TARGET, AS, [gas/as-new])
296EOF
297
298  # So the && chain above is easier to extend
299  true
300}
301
302patch_mcm || exit 1
303mkdir -p "$OUTPUT"/log
304
305# Make bootstrap compiler (no $TYPE, dynamically linked against host libc)
306# We build the rest of the cross compilers with this so they're linked against
307# musl-libc, because glibc doesn't fully support static linking and dynamic
308# binaries aren't really portable between distributions
309make_tuple "${TARGETS[0]}" host 2>&1 | tee -a "$OUTPUT/log/$BOOTSTRAP"-host.log
310split_tuple "${TARGETS[0]}"
311BOOTSTRAP="$TARGET"
312
313if [ $# -gt 0 ]
314then
315  for i in "${TARGETS[0]}" "$@"
316  do
317    make_tuple "$i" static native
318  done
319else
320  # Here's the list of cross compilers supported by this build script.
321
322  # First target builds a proper version of the $BOOTSTRAP compiler above,
323  # which is used to build the rest (in alphabetical order)
324  for i in $(seq 0 $((${#TARGETS[@]}-1)))
325  do
326    make_tuple "${TARGETS[$i]}" static native
327  done
328fi
329