cookutils view cross @ rev 652

cross: Fix compile order
author Christophe Lincoln <pankso@slitaz.org>
date Tue Mar 04 19:42:17 2014 +0100 (2014-03-04)
parents 8e8237a1e876
children b357bbf78c7b
line source
1 #!/bin/sh
2 #
3 # Cross - Help build a cross toolchain on SliTaz.
4 #
5 # Copyright 2012-2014 (C) SliTaz GNU/Linux - BSD License
6 # Author: Christophe Lincoln <pankso@slitaz.org>
7 #
8 . /lib/libtaz.sh
10 [ -f "/etc/slitaz/cross.conf" ] && . /etc/slitaz/cross.conf
11 [ -f "cross.conf" ] && . ./cross.conf
13 # Handle --config=/path/to/cross.conf
14 [ "$config" ] && . $config
15 source=$WORK/source
16 tools=$WORK/tools
17 sysroot=$WORK/sysroot
18 logdir=$WORK/log
20 # Cross-tools tarballs
21 binutils_tarball="binutils-$BINUTILS_VERSION.tar.bz2"
22 linux_tarball="linux-$LINUX_VERSION.tar.xz"
23 glibc_tarball="glibc-$GLIBC_VERSION.tar.bz2"
24 eglibc_tarball="eglibc-$EGLIBC_VERSION.tar.bz2"
25 gcc_tarball="gcc-$GCC_VERSION.tar.bz2"
27 # Cross-tools URLs
28 binutils_wget="http://ftp.gnu.org/gnu/binutils/$binutils_tarball"
29 linux_wget="http://www.kernel.org/pub/linux/kernel/v3.x/$linux_tarball"
30 glibc_wget="http://ftp.gnu.org/gnu/libc/$glibc_tarball"
31 eglibc_wget="svn://svn.eglibc.org/branches/eglibc-2_13"
32 gcc_wget="http://ftp.gnu.org/gnu/gcc/gcc-$GCC_VERSION/$gcc_tarball"
34 # Help and usage.
35 usage() {
36 cat << EOT
38 Usage: $(basename $0) command --option
40 Commands:
41 howto Man[like] page and howto
42 info Display cross-tools info
43 testsuite Execute a small testsuite
44 setup [arch] Setup build host environment
45 download Download necessary sources
46 show-log Show a compile log
47 binutils Compile Binutils
48 linux-headers Install Kernel headers
49 gcc-static Compile GCC static
50 glibc Compile GNU Glibc
51 gcc-final Compile final GCC
52 compile Compile everything at once
53 clean Clean-up build environment
54 clean-tools Clean: $tools
55 gen-prebuilt Create a prebuilt toolchain archive
57 EOT
58 }
60 # Prebuilt README
61 prebuilt_readme() {
62 echo -n "Creating toolchain README..."
63 cat >> $package/README << EOT
65 SliTaz Prebuilt $ARCH cross toolchain
66 ================================================================================
67 Move this $ARCH cross compilation toolchain to /usr/cross then add tools
68 to your PATH environment and test the toolchain:
70 # mv $ARCH /cross
71 # export PATH=\$PATH:/cross/$ARCH/tools/bin
73 # echo 'int main() { return 0; }' > test.c
74 # $TARGET-gcc -v -o test.out test.c
75 # readelf -h test.out
77 ================================================================================
79 EOT
80 status
81 }
83 # Make sure we have all directories.
84 init_compile() {
85 unset CFLAGS CXXFLAGS
86 export LC_ALL=POSIX LANG=POSIX
87 export PATH=$PATH:$tools/bin
88 export CROSS_COMPILE=${TARGET}-
89 mkdir -p $source $logdir $sysroot $tools
90 echo "Tools prefix : --prefix=$tools "
91 echo "Target sysroot : --with-sysroot=$sysroot"
92 cd $source
93 }
95 # Some arch may need custom CFLAGS to build Glibc/Eglibc
96 init_cflags() {
97 case "$ARCH" in
98 arm|armv6) export CFLAGS="-march=armv6 -O2" ;;
99 armv6hf) export CFLAGS="-O2 -march=armv6j -mfpu=vfp -mfloat-abi=hard" ;;
100 armv7) export CFLAGS="-Os -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -pipe" ;;
101 esac
102 }
104 # Get source if not yet in $SRC.
105 download_src() {
106 mkdir -p $SRC && cd $SRC
107 [ -f "$binutils_tarball" ] || wget $binutils_wget
108 [ -f "$linux_tarball" ] || wget $linux_wget
109 [ -f "$glibc_tarball" ] || wget $glibc_wget
110 [ -f "$gcc_tarball" ] || wget $gcc_wget
111 }
113 # 1. Binutils
114 binutils() {
115 init_compile
116 rm -rf binutils-$BINUTILS_VERSION
117 echo "Extracting: $binutils_tarball"
118 tar xjf $SRC/$binutils_tarball
119 echo "Configure: $BINUTILS_ARGS"
120 cd binutils-$BINUTILS_VERSION
121 ./configure \
122 --prefix=$tools \
123 --target=$TARGET \
124 --enable-plugins \
125 --enable-threads \
126 --enable-targets=$BUILD_SYSTEM \
127 --with-sysroot=$sysroot \
128 $BINUTILS_ARGS &&
129 make || exit 1
130 make install
131 echo "cross: binutils compiled on: $(date)"
132 }
134 # 2. Kernel headers could use CROSS_COMPILE but gcc is not yet built.
135 linux_headers() {
136 init_compile
137 if [ ! -d "linux-$LINUX_VERSION" ]; then
138 echo "Extracting: $linux_tarball"
139 tar xJf $SRC/$linux_tarball
140 fi
141 case "$ARCH" in
142 armv6hf) KARCH="arm" ;;
143 *) KARCH="$ARCH" ;;
144 esac
145 rm -rf linux-headers
146 cd linux-$LINUX_VERSION
147 make CROSS_COMPILE="" mrproper
148 make ARCH=$KARCH headers_check
149 make ARCH=$KARCH headers_install \
150 INSTALL_HDR_PATH=$source/linux-headers
151 rm $source/linux-headers/include/.*install*
152 echo "Copying headers to: $sysroot/usr"
153 cp -a $source/linux-headers/* $sysroot/usr
154 }
156 # 2.1 Glibc headers needed to compile x86_64 gcc-static.
157 glibc_headers() {
158 init_compile
159 echo "Extracting: $glibc_tarball"
160 tar xjf $SRC/$glibc_tarball
161 rm -rf glibc-headers
162 mkdir glibc-headers && cd glibc-headers
163 libc_cv_forced_unwind=yes \
164 libc_cv_c_cleanup=yes \
165 ../glibc-$GLIBC_VERSION/configure \
166 --prefix=/usr \
167 --host=$TARGET \
168 --with-headers=$sysroot/usr/include \
169 --without-cvs \
170 --disable-sanity-checks \
171 --enable-kernel=2.6.32 &&
172 make -k install-headers install_root=$sysroot
173 # Fixes
174 mkdir -p $sysroot/usr/include/gnu
175 touch $sysroot/usr/include/gnu/stubs.h
176 cp bits/stdio_lim.h $sysroot/usr/include/bits
177 }
179 # 3. GCC static (first pass)
180 gcc_static() {
181 init_compile
182 echo "Extracting: $gcc_tarball"
183 tar xjf $SRC/$gcc_tarball
184 echo "Configure: $GCC_STATIC_ARGS"
185 rm -rf gcc-static
186 mkdir gcc-static && cd gcc-static
187 ../gcc-$GCC_VERSION/configure \
188 --prefix=$tools \
189 --libexec=$tools/lib \
190 --target=$TARGET \
191 --disable-shared \
192 --disable-threads \
193 --disable-libgomp \
194 --disable-libmudflap \
195 --disable-libssp \
196 --without-headers \
197 --with-newlib \
198 --with-sysroot=$sysroot \
199 $GCC_STATIC_ARGS &&
200 make all-gcc all-target-libgcc || exit 1
201 make install-gcc install-target-libgcc
202 echo "cross: gcc-static compiled on: $(date)"
203 }
205 # 4. GNU Glibc: TODO Improve ARM support
206 glibc() {
207 init_compile
208 echo "Extracting: $glibc_tarball"
209 tar xjf $SRC/$glibc_tarball
210 echo "Configure: $GLIBC_ARGS"
211 # Some arch may need glibc-ports and custom CFLAGS
212 case "$ARCH" in
213 arm*)
214 export CFLAGS="-march=armv6 -O2"
215 [ -f "$SRC/glibc-ports-$GLIBC_VERSION.tar.bz2" ] || wget \
216 http://ftp.gnu.org/gnu/libc/glibc-ports-$GLIBC_VERSION.tar.bz2 \
217 -O $SRC/glibc-ports-$GLIBC_VERSION.tar.bz2 || exit 1
218 echo "Extracting: glibc-ports-$GLIBC_VERSION.tar.bz2"
219 rm -rf glibc-$GLIBC_VERSION/ports
220 tar xjf $SRC/glibc-ports-$GLIBC_VERSION.tar.bz2
221 mv glibc-ports-$GLIBC_VERSION glibc-$GLIBC_VERSION/ports
222 libexec=/usr/lib/glibc ;;
223 x86_64)
224 #export CFLAGS="-march=nocona -O2 -pipe"
225 ccflags="-m64"
226 libexec=/usr/lib64/glibc ;;
227 esac
228 # Disable linking to libgcc_eh
229 cd glibc-$GLIBC_VERSION
230 cp Makeconfig Makeconfig.orig
231 sed -e 's/-lgcc_eh//g' Makeconfig.orig > Makeconfig
232 cd ..
233 echo "CFLAGS: $CFLAGS"
234 rm -rf glibc-build
235 mkdir -p glibc-build && cd glibc-build
236 BUILD_CC="gcc" \
237 CC="${TARGET}-gcc $ccflags" \
238 AR="${TARGET}-ar" \
239 RANLIB="${TARGET}-ranlib" \
240 libc_cv_forced_unwind=yes \
241 libc_cv_c_cleanup=yes \
242 ../glibc-$GLIBC_VERSION/configure \
243 --prefix=/usr \
244 --libexec=$libexec \
245 --host=$TARGET \
246 --with-headers=$sysroot/usr/include \
247 --with-binutils=$tools/bin \
248 --enable-kernel=2.6.32 \
249 $GLIBC_ARGS &&
250 make || exit 1
251 make install_root=$sysroot install
252 # Symlink lib64 to lib
253 case "$ARCH" in
254 x86_64)
255 rm -f $sysroot/lib $sysroot/usr/lib
256 cd $sysroot && ln -s lib64 lib
257 cd usr && ln -s lib64 lib ;;
258 esac
259 echo "cross: glibc compiled on: $(date)"
260 }
262 # 4. eglibc: always use --prefix=/usr
263 eglibc() {
264 init_compile
265 init_cflags
266 rm -rf eglibc-build eglibc-$EGLIBC_VERSION
267 echo "Extracting: $eglibc_tarball"
268 tar xjf $SRC/$eglibc_tarball || exit 1
269 case "$ARCH" in
270 arm*)
271 if [ ! -d "$source/eglibc-ports-$EGLIBC_VERSION" ]; then
272 echo "Cloning $eglibc_wget/ports"
273 svn co $eglibc_wget/ports eglibc-ports-$EGLIBC_VERSION >/dev/null
274 fi
275 cp -a eglibc-ports-$EGLIBC_VERSION eglibc-$EGLIBC_VERSION/ports
276 libexec=/usr/lib/eglibc ;;
277 x86_64)
278 #export CFLAGS="-march=nocona -O2 -pipe"
279 ccflags="-m64"
280 libexec=/usr/lib64/eglibc ;;
281 esac
282 # Disable linking to libgcc_eh
283 cd eglibc-$EGLIBC_VERSION
284 cp Makeconfig Makeconfig.orig
285 sed -e 's/-lgcc_eh//g' Makeconfig.orig > Makeconfig
286 cd ..
287 echo "CFLAGS: $CFLAGS"
288 mkdir -p eglibc-build && cd eglibc-build
289 # config.cache
290 cat > config.cache << EOT
291 libc_cv_forced_unwind=yes
292 libc_cv_c_cleanup=yes
293 libc_cv_gnu89_inline=yes
294 EOT
295 BUILD_CC="gcc" \
296 CC="${TARGET}-gcc $ccflags" \
297 AR="${TARGET}-ar" \
298 RANLIB="${TARGET}-ranlib" \
299 ../eglibc-$EGLIBC_VERSION/configure \
300 --prefix=/usr \
301 --libexec=$libexec \
302 --host=$TARGET \
303 --with-headers=$sysroot/usr/include \
304 --with-binutils=$tools/bin \
305 --enable-kernel=2.6.32 \
306 --with-__thread \
307 --without-gd \
308 --without-cvs \
309 --cache-file=config.cache \
310 $EGLIBC_ARGS &&
311 make || exit 1
312 make install_root=$sysroot install
313 echo "cross: eglibc compiled on: $(date)"
314 }
316 # 5. GCC final
317 gcc_final() {
318 init_compile
319 if [ ! -d "gcc-$GCC_VERSION" ]; then
320 echo "Extracting: $gcc_tarball"
321 tar xjf $SRC/$gcc_tarball
322 fi
323 echo "Configure: $GCC_FINAL_ARGS"
324 rm -rf gcc-build
325 mkdir -p gcc-build && cd gcc-build
326 AR=ar \
327 ../gcc-$GCC_VERSION/configure \
328 --prefix=$tools \
329 --libexec=$tools/lib \
330 --target=$TARGET \
331 --enable-shared \
332 --enable-c99 \
333 --enable-long-long \
334 --enable-__cxa_atexit \
335 --with-system-zlib \
336 --enable-plugin \
337 --disable-multilib \
338 --disable-libssp \
339 --disable-checking \
340 --disable-werror \
341 --with-pkgversion="SliTaz" \
342 --with-bugurl="http://bugs.slitaz.org/" \
343 --with-sysroot=$sysroot \
344 $GCC_FINAL_ARGS &&
345 make AS_FOR_TARGET="${TARGET}-as" \
346 LD_FOR_TARGET="${TARGET}-ld" || exit 1
347 make install
348 echo "cross: GCC final compiled on: $(date)"
349 }
351 #
352 # Commands
353 #
355 case "$1" in
356 howto|man)
357 doc=/usr/share/doc/cookutils/cross.txt
358 [ -f "$doc" ] && less -E $doc ;;
359 info)
360 init_compile
361 init_cflags
362 CC=${TARGET}-gcc
363 echo -e "\nCross Toolchain information" && separator
364 [ "$config" ] && echo "Config file : $config"
365 cat << EOT
366 Target arch : $ARCH
367 C Compiler : $CC
368 CFLAGS : $CFLAGS
369 Build directory : $WORK
370 Tools prefix : $tools/bin
371 Arch sysroot : $sysroot
372 EOT
373 separator && echo ""
374 echo "GCC version" && separator
375 if [ -x "$tools/bin/$CC" ]; then
376 $CC -v
377 else
378 echo "No C compiler. To build a toolchain run: cross compile"
379 echo "Missing: $tools/bin/$CC"
380 fi
381 separator && echo "" ;;
382 testsuite)
383 init_compile
384 echo "[COMPILING] $TARGET-gcc -v -Wall -o test.out test.c" \
385 | tee $logdir/testsuite.log
386 echo 'int main() { return 0; }' > test.c
387 $TARGET-gcc -v -Wall -o test.out test.c 2>&1 | tee -a $logdir/testsuite.log
388 if [ -x /usr/bin/file ]; then
389 echo -e "\n[CHECKING] file test.out" | tee -a $logdir/testsuite.log
390 file test.out | tee -a $logdir/testsuite.log
391 fi
392 echo -e "\n[CHECKING] readelf -h test.out" | tee -a $logdir/testsuite.log
393 readelf -h test.out | tee -a $logdir/testsuite.log ;;
394 *setup)
395 data="/usr/share/cross"
396 arch=${1%-setup}
397 [ "$arch" == "setup" ] && arch="arm"
398 newline
399 echo "Checking: build system packages"
400 for pkg in slitaz-toolchain mpfr mpfr-dev gmp gmp-dev mpc-library \
401 gawk autoconf; do
402 if [ ! -d "/var/lib/tazpkg/installed/$pkg" ]; then
403 echo "Missing packages: $pkg"
404 if [ -x /usr/sbin/spk-add ]; then
405 spk-add $pkg
406 else
407 tazpkg -gi $pkg
408 fi
409 fi
410 done
411 echo "Getting $arch cross.conf"
412 cp -f ${data}/cross-${arch}.conf /etc/slitaz/cross.conf
413 cook ${arch}-setup
414 newline ;;
415 download)
416 download_src ;;
417 show-log)
418 pkg=$2
419 log=$logdir/$pkg.log
420 if [ ! -f "$log" ]; then
421 echo "No log file found for: $pkg" && exit 1
422 fi
423 less -E $log ;;
424 binutils)
425 rm -f $logdir/binutils.log
426 binutils 2>&1 | tee $logdir/binutils.log ;;
427 linux-headers)
428 linux_headers 2>&1 | tee $logdir/linux-headers.log ;;
429 glibc-headers)
430 glibc_headers 2>&1 | tee $logdir/glibc-headers.log ;;
431 gcc-static)
432 gcc_static 2>&1 | tee $logdir/gcc-static.log ;;
433 glibc)
434 glibc 2>&1 | tee $logdir/glibc.log ;;
435 eglibc)
436 eglibc 2>&1 | tee $logdir/eglibc.log ;;
437 gcc-final)
438 gcc_final 2>&1 | tee $logdir/gcc-final.log ;;
439 compile)
440 # Compile the full toolchain.
441 time=$(date +%s)
442 init_compile
443 echo "Compile start: $(date)" | tee $logdir/compile.log
444 download_src
445 binutils 2>&1 | tee $logdir/binutils.log
446 case "$ARCH" in
447 x86_64) glibc_headers 2>&1 | tee $logdir/glibc-headers.log ;;
448 esac
449 linux_headers 2>&1 | tee $logdir/linux-headers.log
450 gcc_static 2>&1 | tee $logdir/gcc-static.log
451 case "$ARCH" in
452 arm*) eglibc 2>&1 | tee $logdir/eglibc.log ;;
453 x86_64) glibc 2>&1 | tee $logdir/glibc.log ;;
454 esac
455 gcc_final 2>&1 | tee $logdir/gcc-final.log
456 echo ""
457 echo "Compile end : $(date)" | tee -a $logdir/compile.log
458 time=$(($(date +%s) - $time))
459 sec=$time
460 div=$(( ($time + 30) / 60))
461 [ "$div" != 0 ] && min="~ ${div}m"
462 echo "Build time : ${sec}s $min" | tee -a $logdir/compile.log
463 echo "" ;;
464 clean)
465 echo -n "Removing all source files..."
466 rm -rf $WORK/source && status
467 [ "$log" ] && rm -f $WORK/log/*.log ;;
468 clean-tools)
469 # Remove crap :-)
470 init_compile
471 echo "Cleaning : $tools ($(du -sh $tools | awk '{print $1}'))"
472 for file in share/info share/man share/local
473 do
474 echo -n "Removing : $file"
475 rm -rf $tools/$file && status
476 done
477 echo -n "Stripping : shared libs and binaries"
478 find $tools/bin -type f -exec strip -s '{}' 2>/dev/null \;
479 find $tools/lib -name cc1* -exec strip -s '{}' 2>/dev/null \;
480 find $tools/lib -name lto* -exec strip -s '{}' 2>/dev/null \;
481 find $sysroot -name "*.so*" -exec ${TARGET}-strip -s '{}' 2>/dev/null \;
482 sleep 1 && status
483 echo -n "Tools size : " && du -sh $tools | awk '{print $1}' ;;
484 gen-prebuilt)
485 # Create a prebuilt cross toolchain tarball.
486 init_compile
487 date=$(date "+%Y%m%d")
488 package="slitaz-$ARCH-toolchain-$date"
489 tarball="$package.tar.bz2"
490 cd /cross
491 mkdir -p $package/$ARCH || exit 1
492 echo ""
493 echo -n "Copying $ARCH to: $package"
494 cp -a $ARCH/tools $package/$ARCH
495 cp -a $ARCH/sysroot $package/$ARCH
496 status
497 prebuilt_readme
498 echo -n "Creating prebuilt $ARCH toolchain tarball..."
499 tar cjf $tarball $package
500 status
501 rm -rf $package
502 size=$(du -sh $tarball | awk '{print $1}')
503 echo "Tarball path: $(pwd)/$tarball"
504 echo "Tarball size: $size"
505 echo "" ;;
506 *)
507 usage ;;
508 esac