cookutils view cross @ rev 418

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