cookutils annotate cross @ rev 419

cross: better x86_64 support and create prebuilt toolchain (again)
author Christophe Lincoln <pankso@slitaz.org>
date Tue May 15 00:32:46 2012 +0200 (2012-05-15)
parents 4753a4a48547
children 9c322a61167d
rev   line source
pankso@361 1 #!/bin/sh
pankso@361 2 #
pankso@361 3 # Cross - Help build a cross toolchain on SliTaz.
pankso@361 4 #
pankso@361 5 # Copyright 2012 (C) SliTaz GNU/Linux - BSD License
pankso@361 6 # Author: Christophe Lincoln <pankso@slitaz.org>
pankso@361 7 #
pankso@361 8 . /lib/libtaz.sh
pankso@370 9
pankso@370 10 [ -f "/etc/slitaz/cross.conf" ] && . /etc/slitaz/cross.conf
pankso@370 11 [ -f "cross.conf" ] && . ./cross.conf
pankso@361 12
pankso@374 13 # Handle --config=/path/to/cross.conf
pankso@374 14 [ "$config" ] && . $config
pankso@412 15 source=$WORK/source
pankso@412 16 logdir=$WORK/log
pankso@412 17 install=$WORK/install
pankso@374 18
pankso@361 19 # Help and usage.
pankso@361 20 usage() {
pankso@361 21 cat << EOT
pankso@361 22
pankso@361 23 Usage: $(basename $0) command --option
pankso@361 24
pankso@361 25 Commands:
pankso@361 26 howto Man alike and howto
paul@382 27 info Display cross-tools info
pankso@361 28 testsuite Execute a small testsuite
pankso@361 29 check-env Check build host tools
pankso@361 30 download Download necessary sources
pankso@361 31 show-log Show a compile log
pankso@361 32 binutils Compile Binutils
pankso@361 33 gcc-static Compile GCC static
pankso@361 34 linux-headers Install Kernel headers
pankso@361 35 glibc Compile GNU Glibc
pankso@361 36 gcc-final Compile final GCC
pankso@361 37 busybox Cross compile Busybox
pankso@361 38 compile Compile everything at once
pankso@419 39 clean Clean-up build environment
pankso@419 40 clean-tools Clean: $PREFIX
pankso@419 41 gen-prebuilt Create an prebuilt toolchain archive
pankso@361 42
pankso@361 43 EOT
pankso@361 44 }
pankso@361 45
pankso@361 46 # Make sure we have all directories.
pankso@361 47 init_compile() {
pankso@361 48 export LC_ALL=POSIX LANG=POSIX
pankso@403 49 [ "$SYSROOT" ] || export PATH=$PATH:$PREFIX/bin
pankso@400 50 export CROSS_COMPILE=${TARGET}-
pankso@361 51 mkdir -p $source $logdir $install
pankso@361 52 cd $source
pankso@361 53 }
pankso@361 54
pankso@361 55 # Get source if not yet in $SRC.
pankso@361 56 download_src() {
pankso@361 57 mkdir -p $SRC && cd $SRC
pankso@361 58 [ -f "binutils-$BINUTILS_VERSION.tar.bz2" ] || wget $BINUTILS_WGET
pankso@361 59 [ -f "linux-$LINUX_VERSION.tar.bz2" ] || wget $LINUX_WGET
pankso@361 60 [ -f "glibc-$GLIBC_VERSION.tar.bz2" ] || wget $GLIBC_WGET
pankso@361 61 [ -f "gcc-$GCC_VERSION.tar.bz2" ] || wget $GCC_WGET
pankso@361 62 [ -f "busybox-$BUSYBOX_VERSION.tar.bz2" ] || wget $BUSYBOX_WGET
pankso@361 63 }
pankso@361 64
pankso@403 65 # Use sysroot or not ?
pankso@403 66 check_sysroot() {
pankso@403 67 if [ "$SYSROOT" ]; then
pankso@403 68 PREFIX=/usr
pankso@403 69 HDR_PATH=$SYSROOT/usr
pankso@403 70 sysroot="--with-sysroot=$SYSROOT"
pankso@411 71 echo "Configure : $sysroot"
pankso@403 72 else
pankso@403 73 HDR_PATH=$PREFIX
pankso@403 74 fi
pankso@403 75 }
pankso@403 76
pankso@361 77 # 1. Binutils
pankso@361 78 binutils() {
pankso@408 79 init_compile
pankso@411 80 rm -rf binutils-$BINUTILS_VERSION
pankso@361 81 echo "Extracting: binutils-$BINUTILS_VERSION.tar.bz2"
pankso@361 82 tar xjf $SRC/binutils-$BINUTILS_VERSION.tar.bz2
pankso@400 83 : ${BINUTILS_ARGS=--enable-shared}
pankso@411 84 echo "Configure : $BINUTILS_ARGS"
pankso@403 85 check_sysroot
pankso@361 86 cd binutils-$BINUTILS_VERSION
pankso@361 87 ./configure \
pankso@361 88 --prefix=$PREFIX \
pankso@361 89 --target=$TARGET \
pankso@361 90 --enable-targets=$BUILD_SYSTEM \
pankso@403 91 $BINUTILS_ARGS $sysroot
pankso@361 92 make || exit 1
pankso@361 93 make install
pankso@412 94 #echo "cross: binutils compiled on: $(date)"
pankso@361 95 }
pankso@361 96
pankso@403 97 # 2. GCC static (first pass)
pankso@361 98 gcc_static() {
pankso@408 99 init_compile
pankso@361 100 echo "Extracting: gcc-$GCC_VERSION.tar.bz2"
pankso@361 101 tar xjf $SRC/gcc-$GCC_VERSION.tar.bz2
pankso@411 102 echo "Configure : $GCC_STATIC_ARGS"
pankso@403 103 check_sysroot
pankso@403 104 # Arch fixes and work around
pankso@403 105 case "$ARCH" in
pankso@403 106 x86_64)
pankso@403 107 # GCC wants Glib headers in cross environment (not tested
pankso@403 108 # with sysroot) Should we install glibc-headers before ?
pankso@403 109 [ "$SYSROOT" ] || \
pankso@409 110 ln -s /usr/include $PREFIX/$TARGET/include ;;
pankso@403 111 esac
pankso@361 112 rm -rf gcc-static
pankso@361 113 mkdir gcc-static && cd gcc-static
pankso@361 114 ../gcc-$GCC_VERSION/configure \
pankso@361 115 --prefix=$PREFIX \
pankso@374 116 --libexec=$PREFIX/lib \
pankso@361 117 --target=$TARGET \
pankso@361 118 --disable-shared \
pankso@361 119 --disable-threads \
pankso@361 120 --without-headers \
pankso@361 121 --with-newlib \
pankso@403 122 $GCC_STATIC_ARGS $sysroot
pankso@361 123 make all-gcc all-target-libgcc || exit 1
pankso@361 124 make install-gcc install-target-libgcc
pankso@361 125 cd $PREFIX/lib/gcc/$TARGET/$GCC_VERSION
paul@382 126 echo "Creating symlink for static libgcc: libgcc_eh.a"
pankso@366 127 rm -f libgcc_eh.a && ln -s libgcc.a libgcc_eh.a
pankso@361 128 }
pankso@361 129
pankso@403 130 # 3. Kernel headers use static GCC
pankso@403 131 linux_headers() {
pankso@408 132 init_compile
pankso@403 133 echo "Extracting: linux-$LINUX_VERSION.tar.bz2"
pankso@403 134 tar xjf $SRC/linux-$LINUX_VERSION.tar.bz2
pankso@403 135 check_sysroot
pankso@403 136 cd linux-$LINUX_VERSION
pankso@403 137 make mrproper
pankso@403 138 make ARCH=$ARCH headers_check
pankso@403 139 make ARCH=$ARCH headers_install \
pankso@403 140 INSTALL_HDR_PATH=$HDR_PATH
pankso@403 141 }
pankso@403 142
pankso@361 143 # 4. GNU Glibc
pankso@361 144 glibc() {
pankso@408 145 init_compile
pankso@361 146 echo "Extracting: glibc-$GLIBC_VERSION.tar.bz2"
pankso@361 147 tar xjf $SRC/glibc-$GLIBC_VERSION.tar.bz2
pankso@411 148 echo "Configure : $GLIBC_ARGS"
pankso@361 149 [ "$continue" ] || rm -rf glibc-build
pankso@400 150 # Some arch may need glibc-ports and custom CFLAGS
pankso@403 151 case "$ARCH" in
pankso@361 152 arm)
pankso@401 153 #export CFLAGS="-march=armv6 -mtune=generic -g -O2"
pankso@362 154 [ -f "$SRC/glibc-ports-$GLIBC_VERSION.tar.bz2" ] || wget \
pankso@362 155 http://ftp.gnu.org/gnu/libc/glibc-ports-$GLIBC_VERSION.tar.bz2 \
pankso@362 156 -O $SRC/glibc-ports-$GLIBC_VERSION.tar.bz2 || exit 1
pankso@361 157 echo "Extracting: glibc-ports-$GLIBC_VERSION.tar.bz2"
pankso@361 158 rm -rf glibc-$GLIBC_VERSION/ports
pankso@361 159 tar xjf $SRC/glibc-ports-$GLIBC_VERSION.tar.bz2
pankso@361 160 mv glibc-ports-$GLIBC_VERSION glibc-$GLIBC_VERSION/ports ;;
pankso@418 161 x86_64)
pankso@418 162 ccflags="-m64" ;;
pankso@361 163 esac
pankso@404 164 #echo "CFLAGS: $CFLAGS"
pankso@361 165 mkdir -p glibc-build && cd glibc-build
pankso@365 166 BUILD_CC="gcc" \
pankso@418 167 CC="${TARGET}-gcc $ccflags" \
pankso@361 168 libc_cv_forced_unwind=yes \
pankso@361 169 libc_cv_c_cleanup=yes \
pankso@361 170 ../glibc-$GLIBC_VERSION/configure \
pankso@361 171 --prefix=$PREFIX \
pankso@417 172 --libexec=$PREFIX/lib/glibc \
pankso@361 173 --host=$TARGET \
pankso@361 174 --with-headers=$PREFIX/include \
pankso@361 175 --with-binutils=$PREFIX/bin \
pankso@410 176 $GLIBC_ARGS
pankso@361 177 make || exit 1
pankso@361 178 make install
pankso@403 179 # Work around to let GCC find Glibc headers.
pankso@404 180 if [ "$SYSROOT" ]; then
pankso@404 181 cd $SYSROOT
pankso@404 182 ln -s usr/include sys-include
pankso@404 183 else
pankso@403 184 cd $PREFIX/$TARGET
pankso@403 185 rm -rf lib include
pankso@403 186 ln -s ../lib lib
pankso@403 187 ln -s ../include include
pankso@403 188 fi
pankso@403 189 #unset CFLAGS
pankso@361 190 }
pankso@361 191
pankso@361 192 # 5. GCC final
pankso@361 193 gcc_final() {
pankso@408 194 init_compile
pankso@361 195 if [ ! -d "gcc-$GCC_VERSION" ]; then
pankso@361 196 echo "Extracting: gcc-$GCC_VERSION.tar.bz2"
pankso@361 197 tar xjf $SRC/gcc-$GCC_VERSION.tar.bz2
pankso@361 198 fi
pankso@411 199 echo "Configure : $GCC_FINAL_ARGS"
pankso@403 200 check_sysroot
pankso@361 201 rm -rf gcc-build
pankso@361 202 mkdir gcc-build && cd gcc-build
pankso@361 203 ../gcc-$GCC_VERSION/configure \
pankso@361 204 --prefix=$PREFIX \
pankso@374 205 --libexec=$PREFIX/lib \
pankso@361 206 --target=$TARGET \
pankso@361 207 --enable-shared \
pankso@361 208 --enable-c99 \
pankso@361 209 --enable-long-long \
pankso@361 210 --enable-__cxa_atexit \
pankso@400 211 --with-pkgversion="SliTaz" \
pankso@403 212 $GCC_FINAL_ARGS $sysroot
pankso@361 213 make || exit 1
pankso@361 214 make install
pankso@361 215 }
pankso@361 216
paul@382 217 # Build Busybox to we can create prebuilt tiny rootfs image and boot
pankso@361 218 # from NFS ?
pankso@361 219 cross_busybox() {
pankso@408 220 init_compile
pankso@361 221 echo "Extracting: busybox-$BUSYBOX_VERSION.tar.bz2"
pankso@361 222 tar xjf $SRC/busybox-$BUSYBOX_VERSION.tar.bz2
pankso@361 223 cd busybox-$BUSYBOX_VERSION
pankso@400 224 # CROSS_COMPILE is exported via init_compile.
pankso@400 225 make defconfig
pankso@400 226 make || exit 1
pankso@400 227 make install
pankso@361 228 chmod 4755 _install/bin/busybox
pankso@361 229 readelf -h _install/bin/busybox
pankso@403 230 echo "Busybox install path: $(pwd)/_install"
pankso@361 231 }
pankso@361 232
pankso@361 233 #
pankso@361 234 # Commands
pankso@361 235 #
pankso@361 236
pankso@361 237 case "$1" in
pankso@361 238 howto|man)
pankso@361 239 doc=/usr/share/doc/cookutils/cross.txt
pankso@361 240 [ -f "$doc" ] && less -E $doc ;;
pankso@361 241 info)
pankso@361 242 init_compile
pankso@361 243 CC=${TARGET}-gcc
paul@382 244 echo -e "\nCross Toolchain information" && separator
pankso@374 245 [ "$config" ] && echo "Config file : $config"
pankso@361 246 cat << EOT
pankso@374 247 Target arch : $ARCH
pankso@374 248 C Compiler : $CC
pankso@374 249 Build directory : $WORK
pankso@361 250 EOT
pankso@403 251 if [ "$SYSROOT" ]; then
pankso@404 252 PREFIX=/usr
pankso@403 253 echo "Arch sysroot : $SYSROOT"
pankso@403 254 else
pankso@403 255 echo "Additional path : $PREFIX/bin"
pankso@403 256 fi
pankso@361 257 separator && echo ""
pankso@361 258 echo "GCC version" && separator
pankso@404 259 if [ -x "$PREFIX/bin/$CC" ]; then
pankso@374 260 $CC -v
pankso@374 261 else
pankso@374 262 echo "No C compiler. To build a toolchain run: cross compile"
pankso@374 263 fi
pankso@361 264 separator && echo "" ;;
pankso@361 265 testsuite)
pankso@361 266 init_compile
pankso@361 267 echo "[COMPILING] $TARGET-gcc -v -Wall -o test.out test.c" \
pankso@361 268 | tee $logdir/testsuite.log
pankso@361 269 echo 'int main() { return 0; }' > test.c
pankso@361 270 $TARGET-gcc -v -Wall -o test.out test.c 2>&1 | tee -a $logdir/testsuite.log
pankso@361 271 if [ -x /usr/bin/file ]; then
pankso@361 272 echo -e "\n[CHECKING] file test.out" | tee -a $logdir/testsuite.log
pankso@361 273 file test.out | tee -a $logdir/testsuite.log
pankso@361 274 fi
pankso@361 275 echo -e "\n[CHECKING] readelf -h test.out" | tee -a $logdir/testsuite.log
pankso@361 276 readelf -h test.out | tee -a $logdir/testsuite.log ;;
pankso@365 277 check-env)
pankso@361 278 for pkg in mpfr mpfr-dev gmp gmp-dev mpc-library gawk autoconf
pankso@361 279 do
pankso@361 280 if [ ! -d "/var/lib/tazpkg/installed/$pkg" ]; then
pankso@361 281 echo "Missing packages: $pkg"
pankso@361 282 [ "$install" ] && tazpkg -gi $pkg
pankso@361 283 fi
pankso@361 284 done ;;
pankso@361 285 download)
pankso@361 286 download_src ;;
pankso@361 287 show-log)
pankso@361 288 pkg=$2
pankso@371 289 log=$logdir/$pkg.log
pankso@371 290 if [ ! -f "$log" ]; then
pankso@371 291 echo "No log file found for: $pkg" && exit 1
pankso@371 292 fi
pankso@371 293 less -E $log ;;
pankso@361 294 binutils)
pankso@412 295 rm -f $logdir/binutils.log
pankso@361 296 binutils 2>&1 | tee $logdir/binutils.log ;;
pankso@403 297 gcc-static)
pankso@403 298 gcc_static 2>&1 | tee $logdir/gcc-static.log ;;
pankso@361 299 linux-headers)
pankso@363 300 linux_headers 2>&1 | tee $logdir/linux-headers.log ;;
pankso@361 301 glibc)
pankso@361 302 glibc 2>&1 | tee $logdir/glibc.log ;;
pankso@361 303 gcc-final)
pankso@361 304 gcc_final 2>&1 | tee $logdir/gcc-final.log ;;
pankso@361 305 busybox)
pankso@361 306 cross_busybox 2>&1 | tee $logdir/busybox.log ;;
pankso@361 307 compile)
pankso@400 308 # Compile the full toolchain.
pankso@400 309 time=$(date +%s)
pankso@361 310 init_compile
pankso@361 311 echo "Compile start: $(date)" | tee $logdir/compile.log
pankso@361 312 download_src
pankso@361 313 binutils 2>&1 | tee $logdir/binutils.log
pankso@403 314 gcc_static 2>&1 | tee $logdir/gcc-static.log
pankso@361 315 linux_headers 2>&1 | tee $logdir/linux-headers.log
pankso@361 316 glibc 2>&1 | tee $logdir/glibc.log
pankso@361 317 gcc_final 2>&1 | tee $logdir/gcc-final.log
pankso@361 318 echo ""
pankso@365 319 echo "Compile end : $(date)" | tee -a $logdir/compile.log
pankso@400 320 time=$(($(date +%s) - $time))
pankso@400 321 sec=$time
pankso@400 322 div=$(( ($time + 30) / 60))
pankso@400 323 [ "$div" != 0 ] && min="~ ${div}m"
pankso@401 324 echo "Build time : ${sec}s $min" | tee -a $logdir/compile.log
pankso@361 325 echo "" ;;
pankso@416 326 clean)
pankso@416 327 echo -n "Removing all source files..."
pankso@416 328 rm -rf $WORK/source/* && status
pankso@416 329 [ "$log" ] && rm -f $WORK/log/*.log
pankso@416 330 echo "To clean chroot: rm -rf $PREFIX" ;;
pankso@371 331 clean-tools)
pankso@371 332 # Remove crap :-)
pankso@371 333 init_compile
pankso@416 334 echo "Cleaning : $PREFIX ($(du -sh $PREFIX | awk '{print $1}'))"
pankso@371 335 for dir in info man locale
pankso@371 336 do
pankso@416 337 echo -n "Removing : $dir"
pankso@419 338 rm -rf $PREFIX/share/$dir && status
pankso@371 339 done
pankso@416 340 rm -f $PREFIX/lib/*-gdb.py
pankso@419 341 echo -n "Stripping : shared libs and binaries"
pankso@419 342 ${TARGET}-strip -s $PREFIX/lib/*.so* 2>/dev/null
pankso@419 343 ${TARGET}-strip -s $PREFIX/bin/* 2>/dev/null
pankso@419 344 ${TARGET}-strip -s $PREFIX/${TARGET}/bin/* 2>/dev/null
pankso@416 345 ${TARGET}-strip -s $PREFIX/$TARGET/lib/gcc/$TARGET/*/cc1*
pankso@416 346 ${TARGET}-strip -s $PREFIX/$TARGET/lib/gcc/$TARGET/*/lto*
pankso@416 347 sleep 1 && status
pankso@416 348 echo -n "Tools size : " && du -sh $PREFIX | awk '{print $1}' ;;
pankso@366 349 gen-rootfs)
pankso@419 350 echo "Use arm packages: basefile, boot-scripts, busybox and glibc-base"
pankso@419 351 echo "Install them in a rootfs: tazpkg *-arm.tazpkg --root=/my/rootfs" ;;
pankso@416 352 gen-prebuilt)
pankso@416 353 #
pankso@416 354 # TESTING
pankso@416 355 #
pankso@416 356 # Create a prebuilt cross toolchain tarball (or package ?)
pankso@416 357 init_compile
pankso@419 358 package="slitaz-cross-$ARCH-toolchain"
pankso@419 359 tarball="$package.tar.bz2"
pankso@416 360 cd /usr/cross
pankso@419 361 mkdir $package || exit 1
pankso@419 362 echo ""
pankso@419 363 echo -n "Copying $ARCH to: $package"
pankso@419 364 cp -a $ARCH $package
pankso@419 365 rm -rf $package/share $package/etc
pankso@419 366 status
pankso@419 367 echo -n "Creating toolchain README..."
pankso@419 368 cat >> $package/README << EOT
pankso@419 369
pankso@419 370
pankso@419 371 Move this $ARCH cross compilation toolchain to /usr/cross then add tools
pankso@419 372 to your PATH environment:
pankso@419 373
pankso@419 374 # mv $ARCH /usr/cross
pankso@419 375 # export PATH=\$PATH:/usr/cross/$ARCH/bin
pankso@419 376
pankso@419 377
pankso@419 378 EOT
pankso@419 379 status
pankso@416 380 echo -n "Creating prebuilt $ARCH toolchain tarball..."
pankso@419 381 tar cjf $tarball $package
pankso@416 382 status
pankso@416 383 mv -f $tarball $WORK
pankso@419 384 rm -rf $package
pankso@419 385 size=$(du -sh $WORK/$tarball | awk '{print $1}')
pankso@419 386 echo "Tarball path: $WORK/$tarball"
pankso@419 387 echo "Tarball size: $size"
pankso@419 388 echo "" ;;
pankso@361 389 *)
pankso@361 390 usage ;;
pankso@361 391 esac
pankso@361 392