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