cookutils view cook @ rev 1078

cook: allow multi-set & no-src receipts (sources may be downloaded inside compile_rules() individually for each set), allow change SHORT_DESC & WEB_SITE in genpkg_rules() (for differents sets);
lighttpd/cooker.css: add style for log line "Switching to the set...";
lighttpd/index.cgi: remove false-positive coloring with word "fatal", mark line "Switching to the set...", don't hide "Logs" button (fresh log initially empty and it may lasts for many seconds due to buffered "lazy write";
modules/compressor: better remove unwanted Perl files;
modules/mk_pkg_receipt: follow changed SHORT_DESC & WEB_SITE, improve condition speed (from 10 sec to 0.01 sec) when SPLIT is relatively long - looks like ${A/ $B /} is slow.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Thu Jun 21 12:57:52 2018 +0300 (2018-06-21)
parents 23700c523fdb
children 64c16be1dda4
line source
1 #!/bin/sh
2 #
3 # Cook - A tool to cook and generate SliTaz packages. Read the README
4 # before adding or modifying any code in cook!
5 #
6 # Copyright (C) SliTaz GNU/Linux - GNU GPL v3
7 # Author: Christophe Lincoln <pankso@slitaz.org>
8 #
10 . /usr/lib/slitaz/libcook.sh
12 VERSION="3.2"
13 export output=raw
14 prev_ts="/home/slitaz/cache/prev_ts"; touch $prev_ts
17 # Internationalization.
19 export TEXTDOMAIN='cook'
22 #
23 # Functions
24 #
26 usage() {
27 cat <<EOT
29 $(boldify "$(_ 'Usage:')") $(_ 'cook [package|command] [list|--option]')
31 $(boldify "$(_ 'Commands:')")
32 usage|help $(_ 'Display this short usage.')
33 setup $(_ 'Setup your build environment.')
34 *-setup $(_ 'Setup a cross environment.')
35 * = {arm|armv6hf|armv7|x86_64}
36 test $(_ 'Test environment and cook a package.')
37 list-wok $(_ 'List packages in the wok.')
38 search $(_ 'Simple packages search function.')
39 new $(_ 'Create a new package with a receipt.')
40 list $(_ 'Cook a list of packages.')
41 clean-wok $(_ 'Clean-up all packages files.')
42 clean-src $(_ 'Clean-up all packages sources.')
43 uncook $(_ 'Check for uncooked packages')
44 pkgdb $(_ 'Create packages DB lists and flavors.')
46 $(boldify "$(_ 'Options:')")
47 cook <pkg>
48 --clean -c $(_ 'clean the package in the wok.')
49 --install -i $(_ 'cook and install the package.')
50 --getsrc -gs $(_ 'get the package source tarball.')
51 --block -b $(_ 'block a package so cook will skip it.')
52 --unblock -ub $(_ 'unblock a blocked package.')
53 --cdeps $(_ 'check dependencies of cooked package.')
54 --pack $(_ 'repack an already built package.')
55 --debug $(_ 'display debugging messages.')
56 --continue $(_ 'continue running compile_rules.')
57 cook new <pkg>
58 --interactive -x $(_ 'create a receipt interactively.')
59 cook setup
60 --wok $(_ 'clone the cooking wok from Hg repo.')
61 --stable $(_ 'clone the stable wok from Hg repo.')
62 --undigest $(_ 'clone the undigest wok from Hg repo.')
63 --tiny $(_ 'clone the tiny SliTaz wok from Hg repo.')
64 --forced $(_ 'force reinstall of chroot packages.')
65 cook pkgdb
66 --flavors $(_ 'create up-to-date flavors files.')
67 cook splitdb $(_ 'create up-to-date split.db file.')
69 EOT
70 exit 0
71 }
74 # We don't want these escapes in web interface.
76 clean_log() {
77 sed -i -e 's|\[70G\[ \[1;32m| |' \
78 -e 's|\[0;39m \]||' $LOGS/${1:-$pkg}.log
79 }
82 # Be sure package exists in wok.
84 check_pkg_in_wok() {
85 [ -d "$WOK/$pkg" ] || die 'Unable to find package "%s" in the wok' "$pkg"
86 }
89 # Initialize files used in $CACHE
91 init_db_files() {
92 _ 'Creating directories structure in "%s"' "$SLITAZ"
93 mkdir -p $WOK $PKGS $SRC $CACHE $LOGS $FEEDS
94 _ 'Creating DB files in "%s"' "$CACHE"
95 touch $activity $command $broken $blocked $CACHE/webstat
96 chown www:www $cache/webstat
97 }
100 # Paths used in receipt and by cook itself.
102 set_paths() {
103 # Kernel version is set from wok/linux or installed/linux-api-headers(wok-undigest)
104 if [ -f "$WOK/linux/receipt" ]; then
105 kvers=$(. $WOK/linux/receipt; echo $VERSION)
106 kbasevers=$(echo $kvers | cut -d. -f1,2)
107 elif [ -f "$INSTALLED/linux-api-headers/receipt" ]; then
108 kvers=$(. $INSTALLED/linux-api-headers/receipt; echo $VERSION)
109 kbasevers=$(echo $kvers | cut -d. -f1,2)
110 fi
112 # Python version
113 [ -f "$WOK/python/receipt" ] && pyvers=$(. $WOK/python/receipt; echo $VERSION)
114 # Perl version for some packages needed it
115 [ -f "$WOK/perl/receipt" ] && perlvers=$(. $WOK/perl/receipt; echo $VERSION)
117 pkgdir="$WOK/$pkg"
118 . "$pkgdir/receipt"
119 basesrc="$pkgdir/source"
120 tmpsrc="$basesrc/tmp"
121 src="$basesrc/$PACKAGE-$VERSION"
122 taz="$pkgdir/taz"
123 pack="$taz/${1:-$PACKAGE}-$VERSION$EXTRAVERSION" # v2: multiple taz/* folders
124 fs="$pack/fs"
125 stuff="$pkgdir/stuff"
126 install="$pkgdir/install"
128 pkgsrc="${SOURCE:-$PACKAGE}-${KBASEVER:-$VERSION}"
129 lzma_tarball="$pkgsrc.tar.lzma"
131 [ -n "$PATCH" -a -z "$PTARBALL" ] && PTARBALL="$(basename $PATCH)"
133 if [ -n "$WANTED" ]; then
134 basesrc="$WOK/$WANTED/source"
135 src="$basesrc/$WANTED-$VERSION"
136 install="$WOK/$WANTED/install"
137 wanted_stuff="$WOK/$WANTED/stuff"
138 fi
140 [ -n "$SOURCE" ] && source_stuff="$WOK/$SOURCE/stuff"
142 # Old way compatibility.
143 _pkg="$install"
144 }
147 # Create source tarball when URL is a SCM.
149 create_tarball() {
150 local tarball
151 tarball="$pkgsrc.tar.bz2"
152 [ -n "$LZMA_SRC" ] && tarball="$lzma_tarball"
153 _ 'Creating tarball "%s"' "$tarball"
154 if [ -n "$LZMA_SRC" ]; then
155 tar -c $pkgsrc | lzma e $SRC/$tarball -si $LZMA_SET_DIR || exit 1
156 LZMA_SRC=''
157 else
158 tar -cjf $tarball $pkgsrc || exit 1
159 mv $tarball $SRC; rm -rf $pkgsrc
160 fi
161 TARBALL="$tarball"
162 }
165 # Get package source. For SCM we are in cache so clone here and create a
166 # tarball here.
168 get_source() {
169 local url
170 url=${WGET_URL#*|}
171 set_paths
172 pwd=$(pwd)
173 case "$WGET_URL" in
174 http://*|ftp://*|https://*)
175 url="$MIRROR_URL/sources/packages/${TARBALL:0:1}/$TARBALL"
176 wget -T 60 -c -O $SRC/$TARBALL $WGET_URL ||
177 wget -T 60 -c -O $SRC/$TARBALL $url ||
178 die 'ERROR: %s' "wget $WGET_URL"
179 ;;
181 hg*|mercurial*)
182 _ 'Getting source from %s...' 'Hg'
183 _ 'URL: %s' "$url"
184 _ 'Cloning to "%s"' "$pwd/$pkgsrc"
185 if [ -n "$BRANCH" ]; then
186 _ 'Hg branch: %s' "$BRANCH"
187 hg clone $url --rev $BRANCH $pkgsrc ||
188 die 'ERROR: %s' "hg clone $url --rev $BRANCH"
189 else
190 hg clone $url $pkgsrc || die 'ERROR: %s' "hg clone $url"
191 fi
192 rm -rf $pkgsrc/.hg
193 create_tarball
194 ;;
196 git*)
197 _ 'Getting source from %s...' 'Git'
198 _ 'URL: %s' "$url"
199 cd $SRC
200 git clone $url $pkgsrc || die 'ERROR: %s' "git clone $url"
201 if [ -n "$BRANCH" ]; then
202 _ 'Git branch: %s' "$BRANCH"
203 cd $pkgsrc; git checkout $BRANCH; cd ..
204 fi
205 cd $SRC
206 create_tarball
207 ;;
209 cvs*)
210 mod=$PACKAGE
211 [ -n "$CVS_MODULE" ] && mod=$CVS_MODULE
212 _ 'Getting source from %s...' 'CVS'
213 _ 'URL: %s' "$url"
214 [ -n "$CVS_MODULE" ] && _ 'CVS module: %s' "$mod"
215 _ 'Cloning to "%s"' "$pwd/$mod"
216 cvs -d:$url co $mod && mv $mod $pkgsrc
217 create_tarball
218 ;;
220 svn*|subversion*)
221 _ 'Getting source from %s...' 'SVN'
222 _ 'URL: %s' "$url"
223 if [ -n "$BRANCH" ]; then
224 echo t | svn co $url -r $BRANCH $pkgsrc
225 else
226 echo t | svn co $url $pkgsrc
227 fi
228 create_tarball
229 ;;
231 bzr*)
232 _ 'Getting source from %s...' 'bazaar'
233 cd $SRC
234 pkgsrc=${url#*:}
235 if [ -n "$BRANCH" ]; then
236 echo "bzr -Ossl.cert_reqs=none branch $url -r $BRANCH"
237 bzr -Ossl.cert_reqs=none branch $url -r $BRANCH
238 else
239 echo "bzr -Ossl.cert_reqs=none branch $url"
240 bzr -Ossl.cert_reqs=none branch $url
241 cd $pkgsrc; BRANCH=$(bzr revno); cd ..
242 _ "Don't forget to add to receipt:"
243 echo -e "BRANCH=\"$BRANCH\"\n"
244 fi
245 mv $pkgsrc $pkgsrc-$BRANCH
246 pkgsrc="$pkgsrc-$BRANCH"
247 create_tarball
248 ;;
250 *)
251 broken; die 'ERROR: Unable to handle "%s"' "$WGET_URL"
252 ;;
253 esac
254 }
257 # Extract source package.
259 extract_source() {
260 if [ ! -s "$SRC/$TARBALL" ]; then
261 local url
262 url="$MIRROR_URL/sources/packages"
263 url="$url/${TARBALL:0:1}/$TARBALL"
264 _ 'Getting source from %s...' 'mirror'
265 _ 'URL: %s' "$url"
266 busybox wget -c -P $SRC $url || _ 'ERROR: %s' "wget $url"
267 fi
268 _ 'Extracting source archive "%s"' "$TARBALL"
269 case "$TARBALL" in
270 *.tar.gz|*.tgz) tar -xzf $SRC/$TARBALL 2>/dev/null ;;
271 *.tar.bz2|*.tbz|*.tbz2) tar -xjf $SRC/$TARBALL 2>/dev/null ;;
272 *.tar.lzma) tar -xaf $SRC/$TARBALL ;;
273 *.tar.lz|*.tlz) lzip -d < $SRC/$TARBALL | tar -xf - 2>/dev/null ;;
274 *.tar) tar -xf $SRC/$TARBALL ;;
275 *.zip|*.xpi) unzip -o $SRC/$TARBALL 2>/dev/null >&2;;
276 *.xz) unxz -c $SRC/$TARBALL | tar -xf - || \
277 tar -xf $SRC/$TARBALL 2>/dev/null;;
278 *.7z) 7zr x $SRC/$TARBALL 2>/dev/null >&2 ;;
279 *.Z|*.z) uncompress -c $SRC/$TARBALL | tar -xf - ;;
280 *.rpm) rpm2cpio $SRC/$TARBALL | cpio -idm --quiet ;;
281 *.run) /bin/sh $SRC/$TARBALL $RUN_OPTS ;;
282 *) cp $SRC/$TARBALL $(pwd) ;;
283 esac
284 }
287 # Display time.
289 disp_time() {
290 local sec div min
291 sec="$1"
292 div=$(( ($1 + 30) / 60))
293 case $div in
294 0) min='';;
295 # L10n: 'm' is for minutes (approximate cooking time)
296 *) min=$(_n ' ~ %dm' "$div");;
297 esac
299 # L10n: 's' is for seconds (cooking time)
300 _ '%ds%s' "$sec" "$min"
301 }
304 # Display cooked package summary.
306 summary() {
307 local arch=''
308 case "$ARCH" in
309 arm*|x86_64) arch="-$ARCH" ;;
310 esac
312 set_paths
313 cd $WOK/$pkg
314 [ -d $WOK/$pkg/install ] && prod=$(du -sh $WOK/$pkg/install | awk '{print $1}' 2>/dev/null)
315 [ -d $WOK/$pkg/source ] && srcdir=$(du -sh $WOK/$pkg/source | awk '{print $1}' 2>/dev/null)
316 [ -n "$TARBALL" ] && srcsize=$(du -sh $SRC/$TARBALL | awk '{print $1}')
318 title 'Summary for: %s' "$PACKAGE $VERSION$EXTRAVERSION$arch"
320 # L10n: keep the same width of translations to get a consistent view
321 [ -n "$TARBALL" ] && _ 'Src file : %s' "$TARBALL"
322 [ -n "$srcsize" ] && _ 'Src size : %s' "$srcsize"
323 [ -n "$srcdir" ] && _ 'Source dir : %s' "$srcdir"
324 [ -n "$prod" ] && _ 'Produced : %s' "$prod"
325 _ 'Cook time : %s' "$(disp_time "$time")"
326 _ 'Cook date : %s' "$(date "$(_ '+%%F %%R')")"
327 _ 'Target arch : %s' "$ARCH"
329 separator -
330 _ ' # : Packed : Compressed : Files : Package name'
331 separator -
332 pkgi=1
333 for i in $(all_names); do
334 version=$(awk -F$'\t' -vpkg="$i" '{
335 if ($1 == pkg) {print $2; exit}
336 }' "$PKGS/packages.info")
337 fs=$(du -sh $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION | awk '{print $1}')
338 pkgname="$i-$version$EXTRAVERSION$arch.tazpkg"
339 size=$(ls -lh $PKGS/$pkgname | awk '{print $5}')
340 files=$(wc -l < $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION/files.list)
341 printf "%2d : %7s : %10s : %5s : %s\n" "$pkgi" "$fs" "$size" "$files" "$pkgname"
342 pkgi=$((pkgi + 1))
343 done
344 separator
345 }
348 # Display debugging error info.
350 debug_info() {
351 title 'Debug information'
352 # L10n: specify your format of date and time (to help: man date)
353 # L10n: not bad one is '+%x %R'
354 _ 'Cook date: %s' "$(date "$(_ '+%%F %%R')")"
355 if [ -n "$time" ]; then
356 times="$(($(date +%s) - $time))"
357 _ 'Wasted time : %s' "$(disp_time "$times")"
358 fi
359 for error in \
360 ERROR 'No package' "cp: can't" "can't open" "can't cd" \
361 'error:' 'fatal error:' 'undefined reference to' \
362 'Unable to connect to' 'link: cannot find the library' \
363 'CMake Error' ': No such file or directory' \
364 'Could not read symbols: File in wrong format'
365 do
366 # format "line number:line content"
367 fgrep -n "$error" $LOGS/$pkg.log
368 done > $LOGS/$pkg.log.debug_info 2>&1
369 # sort by line number, remove duplicates
370 sort -gk1,1 -t: -u $LOGS/$pkg.log.debug_info
371 rm -f $LOGS/$pkg.log.debug_info
372 footer
373 }
376 # A bit smarter function than the classic `cp` command
378 scopy() {
379 if [ "$(stat -c %h -- "$1")" -eq 1 ]; then
380 cp -a "$1" "$2" # copy generic files
381 else
382 cp -al "$1" "$2" # copy hardlinks
383 fi
384 }
387 # Copy all generic files (locale, pixmaps, .desktop) from $install to $fs.
388 # We use standard paths, so some packages need to copy these files with the
389 # receipt and genpkg_rules.
390 # This function executes inside the packaging process, before compressor call.
392 copy_generic_files() {
393 # Proceed only for "main" package (for v2), and for any packages (v1)
394 [ "$pkg" == "$PACKAGE" ] || return 0
396 # $LOCALE is set in cook.conf
397 if [ -n "$LOCALE" -a -z "$WANTED" ]; then
398 if [ -d "$install/usr/share/locale" ]; then
399 mkdir -p "$fs/usr/share/locale"
400 for i in $LOCALE; do
401 if [ -d "$install/usr/share/locale/$i" ]; then
402 cp -r $install/usr/share/locale/$i $fs/usr/share/locale
403 fi
404 done
405 fi
406 fi
408 # Generic pixmaps copy can be disabled with COOKOPTS="!pixmaps" (or GENERIC_PIXMAPS="no")
409 if [ "${COOKOPTS/!pixmaps/}" == "$COOKOPTS" -a "$GENERIC_PIXMAPS" != 'no' ]; then
410 if [ -d "$install/usr/share/pixmaps" ]; then
411 mkdir -p "$fs/usr/share/pixmaps"
412 for i in png xpm; do
413 [ -f "$install/usr/share/pixmaps/$PACKAGE.$i" -a ! -f "$fs/usr/share/pixmaps/$PACKAGE.$i" ] &&
414 cp -r $install/usr/share/pixmaps/$PACKAGE.$i $fs/usr/share/pixmaps
415 done
416 fi
417 fi
419 # Desktop entry (.desktop).
420 # Generic desktop entry copy can be disabled with COOKOPTS="!menus" (or GENERIC_MENUS="no")
421 if [ "${COOKOPTS/!menus/}" == "$COOKOPTS" -a "$GENERIC_MENUS" != 'no' ]; then
422 if [ -d "$install/usr/share/applications" -a -z "$WANTED" ]; then
423 mkdir -p "$fs/usr/share"
424 cp -r $install/usr/share/applications $fs/usr/share
425 fi
426 fi
427 }
430 # Copy pixmaps, desktop files and licenses from $stuff to $install.
431 # This function executes after the main compile_rules() is done.
433 copy_generic_stuff() {
434 # Custom or homemade PNG pixmap can be in stuff.
435 if [ -f "$stuff/$PACKAGE.png" ]; then
436 mkdir -p $install/usr/share/pixmaps
437 cp $stuff/$PACKAGE.png $install/usr/share/pixmaps
438 fi
440 # Homemade desktop file(s) can be in stuff.
441 if [ -d "$stuff/applications" ]; then
442 mkdir -p $install/usr/share
443 cp -r $stuff/applications $install/usr/share
444 fi
445 if [ -f "$stuff/$PACKAGE.desktop" ]; then
446 mkdir -p $install/usr/share/applications
447 cp $stuff/$PACKAGE.desktop $install/usr/share/applications
448 fi
450 # Add custom licenses
451 if [ -d "$stuff/licenses" ]; then
452 mkdir -p $install/usr/share/licenses
453 cp -r $stuff/licenses $install/usr/share/licenses/$PACKAGE
454 fi
455 }
458 # Update installed.cook.diff
460 update_installed_cook_diff() {
461 # If a cook failed deps are removed.
462 cd $root$INSTALLED; ls -1 > $CACHE/installed.cook
463 cd $CACHE
464 [ "$1" == 'force' -o ! -s '/tmp/installed.cook.diff' ] && \
465 busybox diff installed.list installed.cook > /tmp/installed.cook.diff
466 deps=$(grep ^+[a-zA-Z0-9] /tmp/installed.cook.diff | wc -l)
467 }
470 # Remove installed deps.
472 remove_deps() {
473 # Now remove installed build deps.
474 diff='/tmp/installed.cook.diff'
475 [ -s "$diff" ] || return
477 deps=$(grep ^+[a-zA-Z0-9] $diff | sed 's|^+||')
478 nb=$(grep ^+[a-zA-Z0-9] $diff | wc -l)
479 newline
480 _n 'Build dependencies to remove:'; echo " $nb"
481 [ -n "$root" ] && echo "root=\"$root\""
482 {
483 _n 'Removing:'
484 for dep in $deps; do
485 echo -n " $dep"
486 # Do not waste time uninstalling the packages if we are inside
487 # aufs chroot - unmounting chroot will "uninstall" all packages.
488 [ -s /aufs-umount.sh ] ||
489 echo 'y' | tazpkg remove $dep --root=$root >/dev/null
490 done
491 } | busybox fold -sw80
492 newline; newline
493 # Keep the last diff for debug and info.
494 mv -f $diff $CACHE/installed.diff
495 }
498 # Automatically patch the sources.
500 patchit() {
501 [ -f "$stuff/patches/series" ] || return
503 IFS=$'\n'
504 while read i; do
505 patchname=$(echo ${i%%#*} | cut -d' ' -f1) # allow comments (anything after the # or space)
506 case $patchname in # allow patch options in form <options_no_spaces>|<file_name>
507 *\|*) patchopts="${patchname%|*}"; patchname="${patchname#*|}";;
508 *) patchopts='-Np1';;
509 esac
510 [ -n "$patchname" ] || continue # allow empty lines
511 [ -f "$src/done.$patchname" ] && continue # already applied (useful with `cook --continue`)
512 newline
513 _ 'Applying patch %s' "$patchname"
514 patch $patchopts -i $stuff/patches/$patchname | sed 's|^| |'
515 touch $src/done.$patchname
516 done < $stuff/patches/series
517 newline
518 unset IFS
519 }
522 # Check source tarball integrity.
524 check_integrity() {
525 for i in sha1 sha3 sha256 sha512 md5; do
526 I=$(echo $i | tr 'a-z' 'A-Z')
527 eval sum=\$TARBALL_$I
528 if [ -n "$sum" ]; then
529 newline
530 _ 'Checking %ssum of source tarball...' "$i"
531 echo "$sum $SRC/$TARBALL" | ${i}sum -c || exit 1
532 fi
533 done
534 newline
535 }
538 # Misc fix functions
540 fix() {
541 case $1 in
542 # https://bugzilla.gnome.org/show_bug.cgi?id=655517
543 # https://wiki.gentoo.org/wiki/Project:Quality_Assurance/As-needed
544 ld)
545 export LDFLAGS="$LDFLAGS -Wl,-Os,--as-needed"
546 ;;
547 libtool)
548 if [ -e 'libtool' ]; then
549 sed -i 's| -shared | -Wl,-Os,--as-needed\0|g' libtool
550 else
551 echo "fix libtool: warning: libtool absent, nothing to fix."
552 fi
553 ;;
554 math)
555 # fix C++ math issue introduced in Glibc 2.26:
556 # error: '__builtin_isnan' is not a member of 'std'
557 # if (std::isnan(N)) {
558 # ^
559 find $src -type f -exec sed -i '
560 s|std::signbit|__builtin_signbit|g;
561 s|std::isnan|__builtin_isnan|g;
562 s|std::isinf|__builtin_isinf_sign|g;
563 s|std::isfinite|__builtin_isfinite|g;
564 s|std::isnormal|__builtin_isnormal|g
565 ' '{}' \;
566 ;;
567 symlinks)
568 # make absolute symlinks relative
569 echo "fix symlinks"
570 local ifs="$IFS" link target
571 IFS=$'\n'
572 # step 1: fast job, prefix all the absolute symlinks with "$install"
573 for link in $(find $install -type l); do
574 target="$(readlink $link)"
575 case "$target" in
576 /*) ln -sfv "$install$target" "$link";;
577 esac
578 done
579 IFS="$ifs"
580 # step 2: fine tuning, make symlinks relative
581 tazpkg -gi --quiet --local --cookmode symlinks
582 symlinks -cr $install
583 ;;
584 esac
585 }
588 # Store timestamps, log jobs length
590 timestamp() {
591 local ts_file="$WOK/$pkg/.ts"
592 local curr_ts=$(date '+%s')
593 case $1 in
594 init)
595 rm $ts_file 2>/dev/null
596 echo $curr_ts > $prev_ts
597 ;;
598 job*)
599 # calculate time from the last timestamp
600 echo "$1='$(( $curr_ts - $(cat $prev_ts) ))'" >> $ts_file
601 echo $curr_ts > $prev_ts
602 ;;
603 sets)
604 echo "sets='$2'" >> $ts_file
605 ;;
606 esac
607 }
610 # Store time statsistics to the cache
612 store_timestats() {
613 # see doc/timestats.txt for file format
614 temp=$(mktemp)
615 {
616 for i in $(seq 1 30); do echo "job$i=0"; done
617 cat $WOK/$pkg/.ts
618 echo -n 'total=$(( 0'
619 for i in $(seq 1 30); do echo -n " + job$i"; done
620 echo ' ))'
621 } > $temp
622 . $temp
623 {
624 echo -n "$pkg $sets "
625 for i in $(seq 1 30); do echo -n "$((job$i)) "; done
626 echo "$total"
627 } >> /home/slitaz/cache/timestats
628 rm $temp $WOK/$pkg/.ts # clean
629 }
632 # The main cook function.
634 cookit() {
635 if [ -n "$SETUP_MD5" -a "$SETUP_MD5" != "$(ls $root$INSTALLED | md5sum | cut -c1-32)" ]; then
636 _ 'ERROR: Broken setup. Abort.'
637 return
638 fi
640 title 'Cook: %s' "$PACKAGE $VERSION"
641 set_paths
642 timestamp init # the very start
644 # Handle cross-tools.
645 [ "$BUILD_SYSTEM" != "$HOST_SYSTEM" ] &&
646 case "$ARCH" in
647 arm*|x86_64)
648 # CROSS_COMPILE is used by at least Busybox and the kernel to set
649 # the cross-tools prefix. Sysroot is the root of our target arch
650 sysroot="$CROSS_TREE/sysroot"
651 tools="$CROSS_TREE/tools"
652 # Set root path when cross compiling. ARM tested but not x86_64
653 # When cross compiling we must install build deps in $sysroot.
654 arch="-$ARCH"
655 root="$sysroot"
656 _ '%s sysroot: %s' "$ARCH" "$sysroot"
657 _ 'Adding "%s" to PATH' "$tools/bin"
658 export PATH="$PATH:$tools/bin"
659 export PKG_CONFIG_PATH="$sysroot/usr/lib/pkgconfig"
660 export CROSS_COMPILE="$HOST_SYSTEM-"
661 _ 'Using cross-tools: %s' "$CROSS_COMPILE"
662 if [ "$ARCH" == 'x86_64' ]; then
663 export CC="$HOST_SYSTEM-gcc -m64"
664 export CXX="$HOST_SYSTEM-g++ -m64"
665 else
666 export CC="$HOST_SYSTEM-gcc"
667 export CXX="$HOST_SYSTEM-g++"
668 fi
669 export AR="$HOST_SYSTEM-ar"
670 export AS="$HOST_SYSTEM-as"
671 export RANLIB="$HOST_SYSTEM-ranlib"
672 export LD="$HOST_SYSTEM-ld"
673 export STRIP="$HOST_SYSTEM-strip"
674 export LIBTOOL="$HOST_SYSTEM-libtool"
675 ;;
676 esac
678 @@PREFIX@@/libexec/cookutils/precheck $receipt || exit 1 # former receipt_quality()
680 cd $pkgdir
681 [ -z "$continue" ] && rm -rf source 2>/dev/null
682 rm -rf install taz 2>/dev/null
684 # Disable -pipe if less than 512 MB free RAM.
685 free=$(awk '/^MemFree|^Buffers|^Cached/{s+=$2}END{print int(s/1024)}' /proc/meminfo)
686 if [ "$free" -lt 512 ] && [ "$CFLAGS" != "${CFLAGS/-pipe}" ]; then
687 _ 'Disabling -pipe compile flag: %d MB RAM free' "$free"
688 CFLAGS="${CFLAGS/-pipe}"; CFLAGS=$(echo "$CFLAGS" | tr -s ' ')
689 CXXFLAGS="${CXXFLAGS/-pipe}"; CXXFLAGS=$(echo "$CXXFLAGS" | tr -s ' ')
690 fi
691 unset free
693 # Export flags and path to be used by make and receipt.
694 DESTDIR="$pkgdir/install"
695 # FIXME: L10n: Is this the right time for 'LC_ALL=C LANG=C'?
696 export DESTDIR MAKEFLAGS CFLAGS CXXFLAGS CONFIG_SITE LC_ALL=C LANG=C \
697 LDFLAGS
699 timestamp job1 # pre-checks
701 # BUILD_DEPENDS may vary depending on the ARCH
702 case "$ARCH" in
703 arm*) [ -n "$BUILD_DEPENDS_arm" ] && BUILD_DEPENDS=$BUILD_DEPENDS_arm ;;
704 x86_64) [ -n "$BUILD_DEPENDS_x86_64" ] && BUILD_DEPENDS=$BUILD_DEPENDS_x86_64 ;;
705 esac
707 # Check for build deps and handle implicit depends of *-dev packages
708 # (ex: libusb-dev :: libusb).
709 [ -n "$BUILD_DEPENDS" ] && _ 'Checking build dependencies...'
710 [ -n "$root" ] && _ 'Using packages DB: %s' "$root$DB"
712 # Get the list of installed packages
713 cd $root$INSTALLED; ls > $CACHE/installed.list
715 for action in check install; do
716 for dep in $BUILD_DEPENDS; do
717 implicit="${dep%-dev}"; [ "$implicit" == "$dep" ] && implicit=''
718 for i in $dep $implicit; do
719 # Skip if package already installed
720 [ -f "$root$INSTALLED/$i/receipt" ] && continue
722 case $action in
723 check)
724 # Search for local package or local provided-package
725 name=$(awk -F$'\t' -vpkg="$i" '{
726 if (index(" " $1 " " $10 " ", " " pkg " ")) {print $1; exit}
727 }' "$PKGS/packages.info")
728 if [ -z "$name" ]; then
729 # Search for package in mirror
730 name="$(awk -F$'\t' -vi="$i" '$1==i{print $1; exit}' "$root$DB/packages.info")"
731 [ -z "$name" -a "$i" == "$dep" ] && die 'ERROR: unknown dep "%s"' "$i"
732 fi
733 ;;
734 install)
735 tazpkg get-install $i --root=$root --local --quiet --cookmode || { broken; exit 1; }
736 ;;
737 esac
738 done
739 done
740 done
742 update_installed_cook_diff
744 timestamp job2 # installing bdeps
746 # Get source tarball and make sure we have source dir named:
747 # $PACKAGE-$VERSION to be standard in receipts. Here we use tar.lzma
748 # tarball if it exists.
749 if [ -n "$WGET_URL" -a ! -f "$SRC/$TARBALL" ]; then
750 if [ -f "$SRC/${SOURCE:-$PACKAGE}-$VERSION.tar.lzma" ]; then
751 TARBALL="${SOURCE:-$PACKAGE}-$VERSION.tar.lzma"
752 LZMA_SRC=''
753 else
754 get_source || { broken; exit 1; }
755 fi
756 fi
757 if [ -z "$WANTED" -a -n "$TARBALL" -a ! -d "$src" ]; then
758 mkdir -p $pkgdir/source/tmp; cd $pkgdir/source/tmp
759 if ! extract_source ; then
760 get_source
761 extract_source || { broken; exit 1; }
762 fi
763 if [ -n "$LZMA_SRC" ]; then
764 cd $pkgdir/source
765 if [ "$(ls -A tmp | wc -l)" -gl 1 -o -f "$(echo tmp/*)" ]; then
766 mv tmp tmp-1; mkdir tmp
767 mv tmp-1 tmp/${SOURCE:-$PACKAGE}-$VERSION
768 fi
769 if [ -d "tmp/${SOURCE:-$PACKAGE}-$VERSION" ]; then
770 cd tmp; tar -c * | lzma e $SRC/$TARBALL -si
771 fi
772 fi
774 cd $pkgdir/source/tmp
775 # Some archives are not well done and don't extract to one dir (ex lzma).
776 files=$(ls | wc -l)
777 [ "$files" -eq 1 -a -d "$(ls)" ] &&
778 mv * ../$PACKAGE-$VERSION
779 [ "$files" -eq 1 -a -f "$(ls)" ] &&
780 mkdir -p ../$PACKAGE-$VERSION &&
781 mv * ../$PACKAGE-$VERSION/$TARBALL
782 [ "$files" -gt 1 ] &&
783 mkdir -p ../$PACKAGE-$VERSION &&
784 mv * ../$PACKAGE-$VERSION
785 cd ..; rm -rf tmp
786 fi
788 # Check md5sum (or similar) for sources tarball
789 check_integrity
791 # Libtool shared libs path hack.
792 case "$ARCH" in
793 arm*) cross libhack ;;
794 esac
796 timestamp job3 # get/unpack src tarball
798 # Compiling all the sets
799 if grep -q ^compile_rules $receipt; then
800 _ 'Executing: %s' 'compile_rules'
801 echo "CFLAGS : $CFLAGS"
802 echo "LDFLAGS : $LDFLAGS"
803 [ -d "$src" ] && cd $src
804 patchit
806 timestamp job4 # patching
808 # Get set names from $SPLIT variable, format ex. 'pkg1 pkg2:set1 pkg3:set2'
809 SETS=$(echo $SPLIT \
810 | awk '
811 BEGIN { RS = " "; FS = ":"; }
812 { print $2; }' \
813 | sort -u \
814 | tr '\n' ' ')
815 SETS=${SETS% } # normalize space
816 # Prepare specified source sets using patched sources
817 [ -n "$SETS" -a -d "$src" ] &&
818 for set in $SETS; do
819 echo "Preparing set $set" # debug
820 cp -a $src $src-$set
821 done
823 timestamp job5 # preparing sets
824 timestamp sets "$SETS"
826 job_counter='6'
827 for SET in '' $SETS; do
828 # Switch to the specified source set
829 set_paths
830 local suffix=''
831 [ -n "$SET" ] && suffix="-$SET"
832 export src="$WOK/$pkg/source/$PACKAGE-$VERSION$suffix"
833 export install="$WOK/$pkg/install$suffix"
834 export DESTDIR="$install"
836 if [ -n "$SETS" ]; then
837 if [ -n "$SET" ]; then
838 title "Switching to the set '$SET'"
839 else
840 title "Switching to the default set"
841 fi
842 echo "src : $src"
843 echo "install: $install"
844 fi
845 [ -d "$src" ] && cd $src # packages without sources exists
846 echo
848 [ -d "$install" ] && rm -r $install
849 #mkdir -p $install
851 compile_rules $@ || { broken; exit 1; }
853 # Stay compatible with _pkg
854 [ -d "$src/_pkg" ] && mv $src/_pkg $install
856 copy_generic_stuff
858 timestamp job$job_counter # compiling (set '$SET')
860 # Actions to do after compiling the package
861 # Skip all for split packages (already done in main package)
862 if [ -z "$WANTED" ]; then
863 footer
864 export COOKOPTS ARCH install
865 @@PREFIX@@/libexec/cookutils/compressor install
866 timestamp job$(($job_counter + 1)) # compressing (set '$SET')
867 fi
869 job_counter=$(($job_counter + 2))
870 done
871 else
872 mkdir -p $install # allow receipts without `compile_rules()`
873 fi
874 footer
876 timestamp job # reset counter
878 # Execute testsuite.
879 if grep -q ^testsuite $receipt; then
880 title 'Running testsuite'
881 testsuite $@ || { broken; exit 1; }
882 footer
883 fi
885 timestamp job26 # test suite
887 update_installed_cook_diff force
888 }
891 # Cook quality assurance.
893 cookit_quality() {
894 while true; do
895 [ ! -d "$WOK/$pkg/install" -a -z "$WANTED" ] || break
896 _ 'ERROR: cook failed' | tee -a $LOGS/$pkg.log
897 [ "$trials" == 'yes' ] || break
898 title "Interactive mode"
899 # TODO: allow commands:
900 # q - quit; v - edit receipt here using vi;
901 # s - search for package containing package;
902 # <package name> - install package; [Enter] - retry
903 _ 'You may install the packages here and/or edit the receipt there.'
904 newline
905 while true; do
906 _n 'Install the package? [name/N] '; read answer
907 [ -n "$answer" ] || break
908 tazpkg -gi $answer --root=$root --local --quiet --cookmode
909 done
910 newline
911 _n 'Try again? [Y/n] '; read answer
912 [ "$answer" == 'n' ] && break
913 # here you may append log if you want (">>" instead of last ">")
914 cookit $@ 2>&1 | loglimit 50 > $LOGS/$pkg.log
915 done
917 [ "${COOKOPTS/skip-log-errors/}" != "$COOKOPTS" ] && return 0
919 # ERROR can be echoed any time in cookit()
920 if grep -Ev "(conftest|configtest)" $LOGS/$pkg.log | \
921 grep -Eq "(^ERROR|undefined reference to)" ; then
922 debug_info | tee -a $LOGS/$pkg.log
923 put_status $pkg Failed
924 rm -f $command
925 broken; exit 1
926 fi
927 }
930 # Create the package. Wanted to use TazPkg to create a tazpkg package at first,
931 # but it doesn't handle EXTRAVERSION.
933 packit() {
934 set_paths "$1"
935 PACKAGE="${1:-$PACKAGE}"
937 # Handle cross compilation
938 case "$ARCH" in
939 arm*|x86_64) arch="-$ARCH" ;;
940 esac
942 title 'Pack: %s' "$PACKAGE $VERSION$arch"
944 # Get set name for specified package from $SPLIT variable
945 local set=$(echo -n $SPLIT \
946 | awk -vpkg="$PACKAGE" '
947 BEGIN { RS = " "; FS = ":"; }
948 { if ($1 == pkg && $2 != "") { print "-" $2; exit; } }')
949 # Change set, make filelist and folderlist for new set
950 export src="$src$set"
951 export install="$install$set"
952 export DESTDIR="$install"
954 if grep -q ^genpkg_rules $receipt; then
955 _ 'Executing: %s' 'genpkg_rules'
956 set -e; cd $pkgdir; mkdir -p $fs
957 genpkg_rules || (newline; _ 'ERROR: genpkg_rules failed'; newline) >> \
958 $LOGS/$pkg.log
959 else
960 _ 'No packages rules: meta package'
961 mkdir -p $fs
962 fi
964 # Check CONFIG_FILES
965 if [ -n "$CONFIG_FILES" ]; then
966 unset IFS
967 for i in $CONFIG_FILES; do
968 if [ ! -e $fs$i ]; then
969 case $i in
970 */) mkdir -p $fs$i ;;
971 *) mkdir -p $fs$(dirname $i); touch $fs$i ;;
972 esac
973 fi
974 done
975 fi
977 # First QA check to stop now if genpkg_rules failed.
978 lerror=$(_n 'ERROR')
979 if fgrep -q ^$lerror $LOGS/$pkg.log; then
980 broken; exit 1
981 fi
983 cd $taz
984 action 'Copying "%s"...' 'receipt'
985 export PACKAGE VERSION SHORT_DESC WEB_SITE DEPENDS PROVIDE SUGGESTED TAZPANEL_DAEMON TAGS CAT CONFIG_FILES
986 @@PREFIX@@/libexec/cookutils/mk_pkg_receipt "$(realpath ../receipt)" > $pack/receipt
987 chown 0.0 $pack/receipt; status
989 unset desc
990 [ "$pkg" == "$PACKAGE" -a -f "../description.txt" ] && desc="../description.txt"
991 [ -f "../description.$PACKAGE.txt" ] && desc="../description.$PACKAGE.txt"
992 if [ -n "$desc" ]; then
993 action 'Copying "%s"...' "$(basename "$desc")"
994 cp -f $desc $pack/description.txt; chown 0.0 $pack/description.txt; status
995 fi
997 copy_generic_files
999 # Strip and stuff files.
1000 export COOKOPTS ARCH HOST_SYSTEM LOCALE fs; @@PREFIX@@/libexec/cookutils/compressor fs
1002 # Create files.list with redirecting find output.
1003 action 'Creating the list of files...'
1004 cd $fs
1005 find . -type f -print > ../files.list
1006 find . -type l -print >> ../files.list
1007 cd ..; sed -i 's|^.||' files.list
1008 status
1010 # Md5sum of files.
1011 action 'Creating md5sum of files...'
1012 while read file; do
1013 [ -L "fs$file" ] && continue
1014 [ -f "fs$file" ] || continue
1015 case "$file" in
1016 /lib/modules/*/modules.*|*.pyc) continue ;;
1017 esac
1018 md5sum "fs$file" | sed 's| fs| |'
1019 done < files.list | sort -k2 > md5sum
1020 status
1022 UNPACKED_SIZE=$(du -chs fs receipt files.list md5sum description.txt \
1023 2>/dev/null | awk 'END{ print $1 }')
1025 # Build cpio archive.
1026 action 'Compressing the FS...'
1027 find fs -newer $receipt -exec touch -hr $receipt '{}' \;
1028 # find fs | cpio -o -H newc --quiet | lzma-alone e fs.cpio.lzma -si
1029 find fs | cpio -o -H newc --quiet | /bin/lzma -qzeT0 >fs.cpio.lzma
1030 mv fs ../
1031 status
1033 PACKED_SIZE=$(du -chs fs.cpio.lzma receipt files.list md5sum description.txt \
1034 2>/dev/null | awk 'END{ print $1 }')
1036 action 'Updating receipt sizes...'
1037 sed -i '/^PACKED_SIZE=/d; /^UNPACKED_SIZE=/d' receipt
1038 sed -i "s|^PACKAGE=|PACKED_SIZE=\"$PACKED_SIZE\"\nUNPACKED_SIZE=\"$UNPACKED_SIZE\"\nPACKAGE=|" receipt
1039 status
1041 # Set extra version.
1042 if [ -n "$EXTRAVERSION" ]; then
1043 action 'Updating receipt EXTRAVERSION: %s' "$EXTRAVERSION"
1044 sed -i '/^EXTRAVERSION=/d' receipt
1045 sed -i "s|^VERSION=|EXTRAVERSION=\"$EXTRAVERSION\"\nVERSION=|" receipt
1046 status
1047 fi
1049 # Compress.
1050 action 'Creating full cpio archive...'
1051 find . -newer $receipt -exec touch -hr $receipt '{}' \;
1052 find . | cpio -o -H newc --quiet > ../$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg
1053 status
1055 # Restoring original package tree.
1056 mv ../fs .
1058 rm fs.cpio.lzma; cd ..
1060 # QA and give info.
1061 tazpkg=$(ls *.tazpkg)
1062 packit_quality
1063 footer "$(_ 'Package "%s" created' "$tazpkg")"
1067 # Verify package quality and consistency.
1069 packit_quality() {
1070 local arch=''
1071 case "$ARCH" in
1072 arm*|x86_64) arch="-$ARCH" ;;
1073 esac
1075 local rsum rsumold='' rsum_changed old_file
1076 local pi="$PKGS/packages.info" fl="$cache/files.list"
1077 local pkg_file="$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg"
1078 local rsum_file=$(mktemp) rsum_file_old=$(mktemp) tmpdir=$(mktemp -d)
1081 if [ "${COOKOPTS/skip-log-errors/}" == "$COOKOPTS" ]; then
1082 # Exit if any error found in log file.
1083 if fgrep -q ^ERROR $LOGS/$pkg.log; then
1084 rm -f $command
1085 broken; exit 1
1086 fi
1087 fi
1090 [ -n "$CAT" ] && CATEGORY="${CAT%|*}" # allow meta-packages in v2 receipts
1092 if [ "${COOKOPTS/empty-pkg/}" == "$COOKOPTS" ]; then
1093 action 'QA: checking for empty package...'
1094 if [ ! -s "$pack/files.list" -a "$CATEGORY" != 'meta' ]; then
1095 broken
1096 rm -f $command
1097 false; status
1098 die 'ERROR: empty package'
1099 fi
1100 :; status
1101 fi
1104 # Calculate release checksum: usually it does not change on "just recook".
1105 # Release checksum is md5sum of file containing md5sums of:
1106 # a) all files, b) receipt, and c) description.txt.
1107 # Md5sum of the package file will change every time because of embedded timestamps;
1108 # release checksum based only on files content, and will change only when files change.
1109 # (Pitfall: ownership and permissions...)
1111 # Calculate rsum for new package
1112 cp $pack/md5sum $rsum_file
1113 md5sum $pack/receipt | sed 's| [^ ]*/| |' >> $rsum_file
1114 [ -e "$pack/description.txt" ] &&
1115 md5sum $pack/description.txt | sed 's| [^ ]*/| |' >> $rsum_file
1116 rsum=$(md5sum $rsum_file | awk '{print $1}')
1118 # Calculate rsum for existing previous "old" package
1119 if [ -f "$pkg_file" ]; then
1120 # don't trust database entry, check the package file
1121 cd $tmpdir
1122 cpio -F "$pkg_file" -i md5sum receipt description.txt >/dev/null 2>&1
1123 cp ./md5sum $rsum_file_old
1124 md5sum ./receipt | sed 's| [^ ]*/| |' >> $rsum_file_old
1125 [ -e "./description.txt" ] &&
1126 md5sum ./description.txt | sed 's| [^ ]*/| |' >> $rsum_file_old
1127 rsumold=$(md5sum $rsum_file_old | awk '{print $1}')
1128 cd - >/dev/null
1129 fi
1131 # Clean
1132 rm $rsum_file $rsum_file_old
1133 rm -r $tmpdir
1136 touch $pi $broken
1139 # Find and remove old package only if "release checksum" has changed
1141 if [ "$rsum" != "$rsumold" ]; then
1142 old_file=$(awk -F$'\t' -vname="$PACKAGE" -varch="$arch" '{
1143 if ($1 == name) printf("%s-%s%s.tazpkg", $1, $2, arch);
1144 }' $pi) # <name>-<version><extra_version><-arch>.tazpkg
1145 if [ -f "$PKGS/$old_file" ]; then
1146 action 'Removing old package "%s"' "$old_file"
1147 rm -f "$PKGS/$old_file"
1148 status
1149 fi
1150 # package changed, substitute old package by new one
1151 mv -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg $PKGS
1152 _ 'The release checksum has changed.'
1153 else
1154 # package not changed, remove new package
1155 rm -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg
1156 _ 'The release checksum has not changed.'
1157 fi
1160 sed -i "/^${pkg}$/d" $broken
1163 # Update packages database every time after successful build
1165 # packages.info (unsorted, located near to packages)
1166 unset_receipt; . $pack/receipt
1167 SIZES=$(echo $PACKED_SIZE $UNPACKED_SIZE | sed 's|\.0||g')
1168 DEPENDS=$(echo $DEPENDS) # remove newlines, tabs and multiple spaces from variable
1169 sed -i "/^$PACKAGE\t/d" $pi # remove old entry
1170 cat >> $pi <<EOT
1171 $PACKAGE $VERSION$EXTRAVERSION $CATEGORY $SHORT_DESC $WEB_SITE $TAGS $SIZES $DEPENDS $rsum $PROVIDE
1172 EOT
1174 # files.list (uncompressed, unsorted, located in $cache)
1175 touch $fl
1176 sed -i "/^$PACKAGE: /d" $fl
1177 sed "s/^/$PACKAGE: \0/" $pack/files.list >> $fl
1181 # Return all the names of packages bundled in this receipt
1183 all_names() {
1184 # Get package names from $SPLIT variable
1185 local split=$(echo $SPLIT \
1186 | awk '
1187 BEGIN { RS = " "; FS = ":"; }
1188 { print $1; }' \
1189 | tr '\n' ' ')
1190 local split_space=" $split "
1191 if ! head -n1 $WOK/$pkg/receipt | fgrep -q 'v2'; then
1192 # For receipts v1: $SPLIT may present in the $WANTED package,
1193 # but split packages have their own receipts
1194 echo $PACKAGE
1195 elif [ "${split_space/ $PACKAGE /}" != "$split_space" ]; then
1196 # $PACKAGE included somewhere in $SPLIT (probably in the end).
1197 # We should build packages in the order defined in the $SPLIT.
1198 echo $split
1199 else
1200 # We'll build the $PACKAGE, then all defined in the $SPLIT.
1201 echo $PACKAGE $split
1202 fi
1206 # v2: pack all packages using compiled files
1208 packall() {
1209 set_paths
1210 if head -n1 "$pkgdir/receipt" | fgrep -q 'v2'; then
1211 for i in $(all_names); do
1212 unset TAGS DEPENDS CAT CONFIG_FILES PROVIDE SUGGESTED DATABASE_FILES TAZPANEL_DAEMON
1213 packit $i
1214 done
1215 else
1216 packit
1217 fi
1221 # Reverse "cat" command: prints input lines in the reverse order
1223 tac() {
1224 sed '1!G;h;$!d' $1
1228 # Update chroot with freshly rebuilt package: keep env up-to-date.
1230 update_chroot() {
1231 local PACKAGE="$pkg"
1232 for i in $(all_names); do
1233 if [ -d "$root$INSTALLED/$i" ]; then
1234 . /etc/slitaz/cook.conf
1235 . $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION/receipt
1236 _ 'Updating %s chroot environment...' "$ARCH"
1237 _ 'Updating chroot: %s' "$i ($VERSION$EXTRAVERSION$arch)" | log
1238 cd $PKGS
1239 tazpkg -i "$PKGS/$i-$VERSION$EXTRAVERSION$arch.tazpkg" --forced --root=$root
1240 fi
1241 done
1245 # Install package on --inst or update the chroot.
1247 install_package() {
1248 set_paths
1249 case "$ARCH" in
1250 arm*)
1251 arch="-$ARCH"
1252 root="$CROSS_TREE/sysroot"
1253 ;;
1254 x86_64)
1255 arch="-$ARCH"
1256 ;;
1257 esac
1258 # Install package if requested but skip install if target host doesn't
1259 # match build system or it will break the build chroot.
1260 build=$(echo $BUILD_SYSTEM | cut -d- -f1)
1261 if [ -n "$inst" -a "$build" == "$ARCH" ]; then
1262 if [ -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg" ]; then
1263 cd $PKGS
1264 tazpkg -i "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg" --forced
1265 else
1266 broken
1267 die 'Unable to install package, build has failed.'
1268 fi
1269 fi
1271 update_chroot
1275 # remove chroot jail
1277 umount_aufs() {
1278 tac ${1}rw/aufs-umount.sh | sh
1279 rm -rf ${1}rw
1280 umount ${1}root
1281 rmdir ${1}r*
1285 # Launch the cook command into a chroot jail protected by aufs.
1286 # The current filesystems are used read-only and updates are
1287 # stored in a separate branch.
1289 try_aufs_chroot() {
1291 base="/dev/shm/aufsmnt$$"
1293 # Can we setup the chroot? Is it already done?
1294 grep -q ^AUFS_NOT_SUPPORTED $receipt && return
1295 grep -q ^AUFS_NOT_RAMFS $receipt && base="/mnt/aufsmnt$$"
1296 [ -n "$AUFS_MOUNTS" -a ! -f /aufs-umount.sh ] || return
1297 grep -q ^aufs /proc/modules || modprobe aufs 2>/dev/null || return
1298 mkdir ${base}root ${base}rw || return
1300 _ 'Setup aufs chroot...'
1302 # Sanity check
1303 for i in / /proc /sys /dev /dev/shm /home; do
1304 case " $AUFS_MOUNTS " in
1305 *\ $i\ *) ;;
1306 *) AUFS_MOUNTS="$AUFS_MOUNTS $i" ;;
1307 esac
1308 done
1309 for mnt in $(ls -d $AUFS_MOUNTS | sort | uniq); do
1310 mkdir -p ${base}root$mnt # for `mount -o bind`
1311 mount -o bind $mnt ${base}root$mnt # use `-o bind` instead of `--bind`
1312 if [ $mnt == / ] && ! mount -t aufs -o br=${base}rw:/ none ${base}root; then
1313 _ 'Aufs mount failure'
1314 umount ${base}root
1315 rm -rf ${base}r*
1316 return
1317 fi
1318 echo "umount ${base}root$mnt" >> ${base}rw/aufs-umount.sh
1319 done
1320 trap "umount_aufs ${base}" INT
1322 chroot ${base}root $(cd $(dirname $0); pwd)/$(basename $0) "$@"
1323 status=$?
1325 _ 'Leaving aufs chroot...'
1326 umount_aufs $base
1327 # Install package outside the aufs jail
1328 install_package
1329 exit $status
1333 # Encode predefined XML entities
1335 xml_ent() {
1336 sed -e 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g; s|"|\&quot;|g' -e "s|'|\&apos;|g"
1340 # Create a XML feed for freshly built packages.
1342 gen_rss() {
1343 pubdate=$(date '+%a, %d %b %Y %X')
1344 cat > $FEEDS/$pkg.xml <<EOT
1345 <item>
1346 <title>$PACKAGE $VERSION$EXTRAVERSION</title>
1347 <link>${COOKER_URL}?pkg=${PACKAGE//+/%2B}</link>
1348 <guid>$PACKAGE-$VERSION$EXTRAVERSION</guid>
1349 <pubDate>$pubdate</pubDate>
1350 <description>$(echo -n "$SHORT_DESC" | xml_ent)</description>
1351 </item>
1352 EOT
1356 # Truncate stdout log file to $1 Mb.
1358 loglimit() {
1359 if [ -n "$DEFAULT_LOG_LIMIT" ]; then
1360 tee /dev/stderr | head -qc ${1:-$DEFAULT_LOG_LIMIT}m
1361 else
1362 tee /dev/stderr
1363 fi
1368 # Receipt functions to ease packaging
1371 get_dev_files() {
1372 action 'Getting standard devel files...'
1373 mkdir -p $fs/usr/lib
1374 cp -a $install/usr/lib/pkgconfig $fs/usr/lib
1375 cp -a $install/usr/lib/*a $fs/usr/lib
1376 cp -a $install/usr/include $fs/usr
1377 status
1381 # Function to use in compile_rules() to copy man page from $src to $install
1383 cook_pick_manpages() {
1384 local name section
1385 action 'Copying man pages...'
1387 for i in $@; do
1388 name=$(echo $i | sed 's|\.[gbx]z2*$||')
1389 section=${name##*/}; section=${section##*.}
1390 mkdir -p $install/usr/share/man/man$section
1391 scopy $i $install/usr/share/man/man$section
1392 done
1393 status
1397 # Function to use in compile_rules() to copy documentation from $src to $install
1399 cook_pick_docs() {
1400 local docdir="$install/usr/share/doc/$PACKAGE-$VERSION"
1401 action 'Copying documentation...'
1402 mkdir -p $docdir
1403 cp -r $@ $docdir
1404 chmod -R a+r $docdir
1405 status
1409 # Function to use in genpkg_rules() to copy specified files from $install to $fs
1411 cook_copy_files() {
1412 action 'Copying files...'
1413 cd $install
1414 local i j
1415 IFS=$'\n'
1416 for i in $@; do
1417 for j in $(find . -name $i ! -type d); do
1418 mkdir -p $fs$(dirname ${j#.})
1419 scopy $j $fs$(dirname ${j#.})
1420 done
1421 done
1422 cd - >/dev/null
1423 status
1427 # Function to use in genpkg_rules() to copy specified folders from $install to $fs
1429 cook_copy_folders() {
1430 action 'Copying folders...'
1431 cd $install
1432 local i j
1433 IFS=$'\n'
1434 for i in $@; do
1435 for j in $(find . -name $i -type d); do
1436 mkdir -p $fs$(dirname ${j#.})
1437 cp -a $j $fs$(dirname ${j#.})
1438 done
1439 done
1440 cd - >/dev/null
1441 status
1445 # Remove from current $fs files that are already packed (for receipts v2).
1446 # Note: the order in $SPLIT is very important.
1447 # Note 2: working in the current set.
1449 remove_already_packed() {
1450 local i j
1451 # $pkg is the name of the main package; $PACKAGE is the name of the current one
1452 # $pkg may (or may not) be included in the $SPLIT
1453 neighbors=$(
1454 echo $pkg $SPLIT" " \
1455 | awk -F$'\t' -vpkg="$PACKAGE" '
1456 BEGIN { RS = " "; FS = ":"; }
1457 { set[$1] = $2; }
1458 END {
1459 current_set = set[pkg];
1460 for (i in set)
1461 { if (i != pkg && set[i] == current_set) print i; }
1463 ')
1464 IFS=$'\n'
1465 for neighbor in $neighbors; do
1466 i="$taz/$neighbor-$VERSION$EXTRAVERSION/files.list"
1467 [ -e "$i" ] || continue
1468 while read j; do
1469 [ -f $fs$j -o -h $fs$j ] || continue
1470 rm $fs$j
1471 rmdir --parents --ignore-fail-on-non-empty $fs$(dirname $j)
1472 done < $i
1473 done
1474 unset IFS
1478 # Function to use in genpkg_rules() to copy hicolor icons in specified sizes
1479 # (default: 16 and 48) from $install to $fs
1481 cook_copy_icons() {
1482 local sizes=$@ i j ifs="$IFS"
1483 unset IFS
1484 action 'Copying hicolor icons...'
1485 [ -d "$fs/usr/share/icons/hicolor" ] && rm -rf "$fs/usr/share/icons/hicolor"
1486 mkdir -p $fs/usr/share/icons/hicolor
1487 for i in ${sizes:-16 48}; do
1488 j="${i}x$i"; [ "$i" == 'scalable' ] && j="$i"
1489 [ ! -e "$install/usr/share/icons/hicolor/$j" ] ||
1490 scopy $install/usr/share/icons/hicolor/$j \
1491 $fs/usr/share/icons/hicolor
1492 done
1493 status
1494 IFS="$ifs"
1498 # Common function to copy files, folders and patterns
1500 copy() {
1501 action 'Copying folders and files...'
1502 local i j k filelist=$(mktemp) folderlist=$(mktemp)
1504 IFS=$'\n'
1505 cd $install
1506 find ! -type d | sed 's|\.||' > $filelist
1507 find -type d | sed 's|\.||' > $folderlist
1509 for i in $@; do
1510 case $i in
1511 @std)
1512 # Copy "standard" files (all but "developer files", man pages, documentation, translations)
1513 sed '/\.h$/d; /\.hxx$/d; /\.a$/d; /\.la$/d; /\.pc$/d; /\.pri$/d; /bin\/.*-config$/d;
1514 /\.m4$/d; /\.gir$/d; /\.typelib$/d; /\.vapi$/d; /\.deps$/d; /\.cmake$/d;
1515 /\/Makefile.*/d; /\.inc$/d; /\/include\//d;
1516 /\/share\/man\//d; /\/share\/doc\//d; /\/share\/gtk-doc\//d; /\/share\/info\//d;
1517 /\/share\/devhelp\//d; /\/share\/locale\//d;
1518 /\/share\/bash-completion\//d; /\/etc\/bash_completion\.d\//d; /\/lib\/systemd\//d;
1519 /\/fonts\.scale$/d; /\/fonts\.dir$/d;
1520 /\/share\/appdata\//d; /\/share\/help\//d; /\/share\/metainfo\//d;
1521 /\/share\/icons\/hicolor\/[12356][1245][268]*x[12356][1245][268]*\//d; # 22, 24, 32, 64, 128, 256, 512
1522 /\.so\.dbg$/d;
1523 ' $filelist
1524 ;;
1525 @dev)
1526 # Copy "developer files"
1527 sed -n '/\.h$/p; /\.hxx$/p; /\.a$/p; /\.pc$/p; /\.pri$/p; /bin\/.*-config$/p;
1528 /\.m4$/p; /\.gir$/p; /\.typelib$/p; /\.vapi$/p; /\.deps$/p; /\.cmake$/p;
1529 /\/Makefile.*/p; /\.inc$/p; /\/include\//p;
1530 /\.so\.dbg$/p;
1531 ' $filelist
1532 ;;
1533 @rm)
1534 # Quick alias
1535 remove_already_packed
1536 ;;
1537 @ico)
1538 # Quick alias
1539 cook_copy_icons >/dev/null
1540 ;;
1541 */)
1542 # Copy specified folders.
1543 i="${i%/}"
1544 find -type d -path "*/${i#/}" | sed 's|^.||'
1545 ;;
1546 *)
1547 # Copy specified files.
1548 find ! -type d -path "*/${i#/}" | sed 's|^.||'
1549 ;;
1550 esac \
1551 | sort -u \
1552 | while read j; do
1553 mkdir -p $fs$(dirname "$j")
1554 if [ -d "$install$j" ]; then
1555 cp -a "$install$j" $fs$(dirname "$j")
1556 else
1557 scopy "$install$j" $fs$(dirname "$j")
1558 fi
1559 done
1560 # Copy empty directories
1561 case $i in
1562 @std)
1563 while read j; do
1564 case $j in
1565 # skip empty man & doc folders
1566 */man/*|*/doc/*) continue;;
1567 esac
1568 [ -z "$(ls -A "$install$j")" ] || continue
1569 # directory $j is empty
1570 k="$j"
1571 # make 'ladder' from directories, from root dir to $j
1572 # /a /a/b /a/b/c etc.
1573 while :; do
1574 [ -z "$k" ] && break
1575 echo "$k"
1576 k="${k%/*}"
1577 done \
1578 | tac \
1579 | while read k; do
1580 # make dir if it does not exist
1581 if [ ! -d "$fs$k" ]; then
1582 # It's like "copy the directory without its underlying content".
1583 # keep original ownership/permissions, access:
1584 keepIFS="$IFS"; unset IFS
1585 install -d $(stat -c'-o%u -g%g -m%a' "$install$k") "$fs$k"
1586 # keep last-modified date:
1587 touch -r "$install$k" "$fs$k"
1588 IFS="$keepIFS"; unset keepIFS
1589 fi
1590 done
1591 done < $folderlist
1592 ;;
1593 esac
1594 done
1595 cd - >/dev/null
1596 unset IFS
1597 rm $filelist $folderlist
1598 status
1602 # Update split.db once for receipt
1604 update_split_db() {
1605 local db="$cache/split.db"
1606 touch $db
1607 sed -i "/^$pkg\t/d" $db
1608 echo -e "$pkg\t$(all_names)" >> $db
1612 # Recreate whole split.db from scratch
1614 recreate_split_db() {
1615 # Clean
1616 local db="$cache/split.db"
1617 touch $db
1618 > $db
1620 cd $WOK
1621 for pkg in *; do
1622 [ -f "$WOK/$pkg/receipt" ] || continue
1623 unset PACKAGE SPLIT
1624 . $WOK/$pkg/receipt
1625 echo -e "$PACKAGE\t$(all_names)" >> $db
1626 done
1630 # Put the status to the activity log
1632 put_status() {
1633 # $1: package, $2: status, one of 'Done', 'Failed'
1634 sed -i "s|>$1</a>$|& [ $2 ]|" $activity
1635 if [ "$2" == 'Done' ]; then
1636 # overstrike all previous 'Failed' to indicate package is OK now
1637 sed -i "/>$1<\/a>/ s|\[ Failed \]|[ -Failed ]|" $activity
1638 fi
1645 # Commands
1648 # cook <package> --deps
1649 [ -n "$deps" ] && {
1650 @@PREFIX@@/libexec/cookutils/deps $1
1651 exit 0
1654 # cook <package> --clean
1655 # cook <package> -c
1656 [ -n "$clean" -o "$2" == '-c' ] && {
1657 action 'Cleaning "%s"' "$1"
1658 cd $WOK/$1; rm -rf install taz source
1659 status; newline
1660 touch $activity # update $activity -> something changed -> update webstat
1661 exit 0
1664 # cook <package> --getsrc
1665 # cook <package> -gs
1666 [ -n "$getsrc" -o "$2" == '-gs' ] && {
1667 title 'Getting source for "%s"' "$1"
1668 receipt="$WOK/$pkg/receipt"
1669 check_pkg_in_wok
1670 unset_receipt
1671 . $receipt
1672 get_source
1673 _ 'Tarball: %s' "$SRC/$TARBALL"; newline
1674 exit 0
1677 # cook <package> --block
1678 # cook <package> -b
1679 [ -n "$block" -o "$2" == '-b' ] && {
1680 action 'Blocking package "%s"' "$1"
1681 [ $(grep "^$1$" $blocked) ] || echo "$1" >> $blocked
1682 status; newline
1683 touch $activity
1684 exit 0
1687 # cook <package> --unblock
1688 # cook <package> -ub
1689 [ -n "$unblock" -o "$2" == '-ub' ] && {
1690 action 'Unblocking package "%s"' "$1"
1691 sed -i "/^$1$/d" $blocked
1692 status; newline
1693 touch $activity
1694 exit 0
1700 case "$1" in
1701 usage|help|-u|-h)
1702 usage ;;
1704 list-wok)
1705 title 'List of %s packages in "%s"' "$ARCH" "$WOK"
1706 cd $WOK
1707 if [ "$ARCH" != 'i486' ]; then
1708 count=0
1709 for pkg in $(fgrep 'HOST_ARCH=' */receipt | egrep "$ARCH|any" | cut -d: -f1)
1710 do
1711 unset HOST_ARCH
1712 . ./$pkg
1713 count=$(($count + 1))
1714 colorize 34 "$PACKAGE"
1715 done
1716 else
1717 count=$(ls | wc -l)
1718 ls -1
1719 fi
1720 footer "$(_p '%s package' '%s packages' "$count" "$(colorize 32 "$count")")"
1721 ;;
1723 activity)
1724 cat $activity ;;
1726 search)
1727 # Just a simple search function, we don't need more actually.
1728 query="$2"
1729 title 'Search results for "%s"' "$query"
1730 cd $WOK; ls -1 | grep "$query"
1731 footer ;;
1733 setup)
1734 # Setup a build environment
1735 check_root
1736 _ 'Cook: setup environment' | log
1737 title 'Setting up your environment'
1738 [ -d $SLITAZ ] || mkdir -p $SLITAZ
1739 cd $SLITAZ
1740 init_db_files
1741 _ 'Checking for packages to install...'
1742 # Use setup pkgs from cross.conf or cook.conf. When cross compiling
1743 # ARCH-setup or 'cross check' should be used before: cook setup
1744 case "$ARCH" in
1745 arm*|x86_64)
1746 [ -x '/usr/bin/cross' ] || die 'ERROR: %s is not installed' 'cross'
1747 _ 'Using config file: %s' '/etc/slitaz/cross.conf'
1748 . /etc/slitaz/cross.conf ;;
1749 esac
1750 for pkg in $SETUP_PKGS; do
1751 if [ -n "$forced" ]; then
1752 tazpkg -gi $pkg --forced
1753 else
1754 [ ! -d "$INSTALLED/$pkg" ] && tazpkg get-install $pkg
1755 fi
1756 done
1758 # Handle --options
1759 case "$2" in
1760 --wok) hg clone $WOK_URL wok || exit 1 ;;
1761 --stable) hg clone $WOK_URL-stable wok || exit 1 ;;
1762 --undigest) hg clone $WOK_URL-undigest wok || exit 1 ;;
1763 --tiny) hg clone $WOK_URL-tiny wok || exit 1 ;;
1764 esac
1766 # SliTaz group and permissions
1767 if ! grep -q ^slitaz /etc/group; then
1768 _ 'Adding group "%s"' 'slitaz'
1769 addgroup slitaz
1770 fi
1771 _ 'Setting permissions for group "%s"...' 'slitaz'
1772 find $SLITAZ -maxdepth 2 -exec chown root.slitaz {} \;
1773 find $SLITAZ -maxdepth 2 -exec chmod g+w {} \;
1774 footer "$(_ 'All done, ready to cook packages :-)')" ;;
1776 *-setup)
1777 # Setup for cross compiling.
1778 arch="${1%-setup}"
1779 check_root
1780 . /etc/slitaz/cook.conf
1781 for pkg in $CROSS_SETUP; do
1782 if [ -n "$forced" ]; then
1783 tazpkg -gi $pkg --forced
1784 else
1785 [ ! -d "$INSTALLED/$pkg" ] && tazpkg -gi $pkg
1786 fi
1787 done
1789 _ 'Cook: setup %s cross environment' "$arch" | log
1790 title 'Setting up your %s cross environment' "$arch"
1791 init_db_files
1792 sed -i \
1793 -e "s|ARCH=.*|ARCH=\"$arch\"|" \
1794 -e "s|CROSS_TREE=.*|CROSS_TREE=\"/cross/$arch\"|" \
1795 -e 's|BUILD_SYSTEM=.*|BUILD_SYSTEM=i486-slitaz-linux|' \
1796 /etc/slitaz/cook.conf
1797 case "$arch" in
1798 arm)
1799 flags='-O2 -march=armv6'
1800 host="$ARCH-slitaz-linux-gnueabi" ;;
1801 armv6hf)
1802 flags='-O2 -march=armv6j -mfpu=vfp -mfloat-abi=hard'
1803 host="$ARCH-slitaz-linux-gnueabi" ;;
1804 armv7)
1805 flags='-Os -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -pipe'
1806 host="$ARCH-slitaz-linux-gnueabi" ;;
1807 x86_64)
1808 flags='-O2 -mtune=generic -pipe'
1809 host="$ARCH-slitaz-linux" ;;
1810 esac
1811 sed -i \
1812 -e "s|CFLAGS=.*|CFLAGS=\"$flags\"|" \
1813 -e "s|HOST_SYSTEM=.*|HOST_SYSTEM=$host|" /etc/slitaz/cook.conf
1814 . /etc/slitaz/cook.conf
1815 sysroot="$CROSS_TREE/sysroot"
1816 tools="/cross/$arch/tools"
1817 root="$sysroot"
1818 # L10n: keep the same width of translations to get a consistent view
1819 _ 'Target arch : %s' "$ARCH"
1820 _ 'Configure args : %s' "$CONFIGURE_ARGS"
1821 _ 'Build flags : %s' "$flags"
1822 _ 'Arch sysroot : %s' "$sysroot"
1823 _ 'Tools prefix : %s' "$tools/bin"
1824 # Tell the packages manager where to find packages.
1825 _ 'Packages DB : %s' "$root$DB"
1826 mkdir -p $root$INSTALLED
1827 cd $root$DB; rm -f *.bak
1828 for list in packages.list packages.desc packages.equiv packages.md5; do
1829 rm -f $list
1830 ln -s $SLITAZ/packages/$list $list
1831 done
1832 # We must have the cross compiled glibc-base installed or default
1833 # i486 package will be used as dep by tazpkg and then break the
1834 # cross environment
1835 if [ ! -f "$root$INSTALLED/glibc-base/receipt" ]; then
1836 colorize 36 $(_ 'WARNING: %s is not installed in sysroot' '(e)glibc-base')
1837 fi
1838 # Show GCC version or warn if not yet compiled.
1839 if [ -x "$tools/bin/$HOST_SYSTEM-gcc" ]; then
1840 _ 'Cross compiler : %s' "$HOST_SYSTEM-gcc"
1841 else
1842 colorize 36 $(_ 'C compiler "%s" is missing' "$HOST_SYSTEM-gcc")
1843 _ 'Run "%s" to cook a toolchain' 'cross compile'
1844 fi
1845 footer ;;
1847 test)
1848 # Test a cook environment.
1849 _ 'Cook test: testing the cook environment' | log
1850 [ ! -d "$WOK" ] && exit 1
1851 [ ! -d "$WOK/cooktest" ] && cp -r $DATA/cooktest $WOK
1852 cook cooktest ;;
1854 new)
1855 # Create the package folder and an empty receipt.
1856 pkg="$2"
1857 [ -z "$pkg" ] && usage
1858 newline
1859 [ -d "$WOK/$pkg" ] && die 'Package "%s" already exists.' "$pkg"
1861 action 'Creating folder "%s"' "$WOK/$pkg"
1862 mkdir $WOK/$pkg; cd $WOK/$pkg; status
1864 action 'Preparing the package receipt...'
1865 cp $DATA/receipt .
1866 sed -i "s|^PACKAGE=.*|PACKAGE=\"$pkg\"|" receipt
1867 status; newline
1869 # Interactive mode, asking and seding.
1870 case "$3" in
1871 --interactive|-x)
1872 _ 'Entering interactive mode...'
1873 separator
1874 _ 'Package : %s' "$pkg"
1876 _n 'Version : ' ; read answer
1877 sed -i "s|^VERSION=.*|VERSION=\"$answer\"|" receipt
1879 _n 'Category : ' ; read answer
1880 sed -i "s|^CATEGORY=.*|CATEGORY=\"$answer\"|" receipt
1882 # L10n: Short description
1883 _n 'Short desc : ' ; read answer
1884 sed -i "s|^SHORT_DESC=.*|SHORT_DESC=\"$answer\"|" receipt
1886 _n 'Maintainer : ' ; read answer
1887 sed -i "s|^MAINTAINER=.*|MAINTAINER=\"$answer\"|" receipt
1889 _n 'License : ' ; read answer
1890 sed -i "s|^LICENSE=.*|LICENSE=\"$answer\"|" receipt
1892 _n 'Web site : ' ; read answer
1893 sed -i "s|^WEB_SITE=.*|WEB_SITE=\"$answer\"|" receipt
1894 newline
1896 # Wget URL.
1897 _ 'Wget URL to download source tarball.'
1898 _n 'Example : ' ; echo '$GNU_MIRROR/$PACKAGE/$TARBALL'
1899 _n 'Wget url : ' ; read answer
1900 sed -i "s|^WGET_URL=.*|WGET_URL=\"$answer\"|" receipt
1902 # Ask for a stuff dir.
1903 confirm "$(_n 'Do you need a stuff directory? (y/N)')"
1904 if [ "$?" -eq 0 ]; then
1905 action 'Creating the stuff directory...'
1906 mkdir $WOK/$pkg/stuff; status
1907 fi
1909 # Ask for a description file.
1910 confirm "$(_n 'Are you going to write a description? (y/N)')"
1911 if [ "$?" -eq 0 ]; then
1912 action 'Creating the "%s" file...' 'description.txt'
1913 touch $WOK/$pkg/description.txt; status
1914 fi
1916 footer "$(_ 'Receipt is ready to use.')" ;;
1917 esac ;;
1919 list)
1920 # Cook a list of packages (better use the Cooker since it will order
1921 # packages before executing cook).
1922 check_root
1923 [ -z "$2" ] && die 'No list in argument.'
1924 [ -f "$2" ] || die 'List "%s" not found.' "$2"
1926 _ 'Starting cooking the list "%s"' "$2" | log
1928 while read pkg; do
1929 cook $pkg || broken
1930 done < $2
1931 ;;
1933 clean-wok)
1934 check_root
1935 newline; action 'Cleaning all packages files...'
1936 rm -rf $WOK/*/taz $WOK/*/install $WOK/*/source
1937 status; newline ;;
1939 clean-src)
1940 check_root
1941 newline; action 'Cleaning all packages sources...'
1942 rm -rf $WOK/*/source
1943 status; newline ;;
1945 uncook)
1946 cd $WOK
1947 count=0
1948 title 'Checking for uncooked packages'
1950 for i in *; do
1951 unset HOST_ARCH EXTRAVERSION
1952 [ ! -e $i/receipt ] && continue
1953 . ./$i/receipt
1954 # Source cooked pkg receipt to get EXTRAVERSION
1955 if [ -d "$WOK/$i/taz" ]; then
1956 cd $WOK/$i/taz/$(ls $WOK/$i/taz/ | head -n1)
1957 . ./receipt; cd $WOK
1958 fi
1959 case "$ARCH" in
1960 i486)
1961 debug "$(_ 'Package "%s"' "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg")"
1962 if [ ! -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg" ]; then
1963 count=$(($count + 1))
1964 colorize 34 "$i"
1965 fi ;;
1966 arm*)
1967 # Check only packages included in arch
1968 if echo "$HOST_ARCH" | egrep -q "$ARCH|any"; then
1969 # *.tazpkg
1970 if [ ! -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg" ]; then
1971 count=$(($count + 1))
1972 colorize 34 "$i"
1973 fi
1974 fi ;;
1975 esac
1976 done
1978 if [ "$count" -gt 0 ]; then
1979 footer "$(_p '%s uncooked package' '%s uncooked packages' "$count" "$(colorize 31 "$count")")"
1980 else
1981 _ 'All packages are cooked :-)'
1982 newline
1983 fi
1984 ;;
1986 pkgdb)
1987 # Create suitable packages list for TazPkg and only for built packages
1988 # as well as flavors files for TazLiTo. We don't need logs since we do it
1989 # manually to ensure everything is fine before syncing the mirror.
1990 recreate_split_db
1991 @@PREFIX@@/libexec/cookutils/pkgdb "$2"
1992 ;;
1994 splitdb)
1995 # File split.db is useful for searching for split packages.
1996 recreate_split_db
1997 ;;
1999 *)
2000 # Just cook and generate a package.
2001 check_root
2002 time=$(date +%s)
2003 pkg="$1"
2004 [ -z "$pkg" ] && usage
2006 # Search last successful cook time in all logs from newer to older
2007 for i in '' $(seq 0 9 | sed 's|^|.|'); do
2008 [ -f "$LOGS/$pkg.log$i" ] || break
2009 lastcooktime=$(sed '/^Cook time/!d; s|.*: *\([0-9]*\)s.*|\1|' \
2010 $LOGS/$pkg.log$i 2>/dev/null | sed '$!d')
2011 [ -n "$lastcooktime" ] && break
2012 done
2014 receipt="$WOK/$pkg/receipt"
2015 check_pkg_in_wok
2016 newline
2018 unset inst
2019 unset_receipt
2020 . $receipt
2022 # Handle cross compilation.
2023 case "$ARCH" in
2024 arm*)
2025 if [ -z "$HOST_ARCH" ]; then
2026 _ 'cook: HOST_ARCH is not set in "%s" receipt' "$pkg"
2027 error="$(_ 'package "%s" is not included in %s' "$pkg" "$ARCH")"
2028 _ 'cook: %s' "$error"
2029 [ -n "$CROSS_BUGS" ] && _ 'bugs: %s' "$CROSS_BUGS"
2030 _ 'Cook skip: %s' "$error" | log
2031 newline
2032 broken; exit 1
2033 fi ;;
2034 esac
2036 # Some packages are not included in some arch or fail to cross compile.
2037 : ${HOST_ARCH=$ARCH}
2038 debug "$(_ 'Host arch %s' "$HOST_ARCH")"
2039 # Handle arm{v6hf,v7,..}
2040 if ! $(echo "$HOST_ARCH" | egrep -q "${ARCH%v[0-9]*}|any"); then
2041 _ 'cook: %s' "HOST_ARCH=$HOST_ARCH"
2042 error="$(_ "package \"%s\" doesn't cook or is not included in %s" "$pkg" "$ARCH")"
2043 _ 'cook: %s' "error"
2044 [ -n "$CROSS_BUGS" ] && _ 'bugs: %s' "$CROSS_BUGS"
2045 _ 'Cook skip: %s' "$error" | log
2046 sed -i "/^${pkg}$/d" $broken
2047 newline
2048 exit 0
2049 fi
2051 # Skip blocked, 3 lines also for the Cooker.
2052 grep -q "^$pkg$" $blocked && [ "$2" != '--unblock' ] &&
2053 die 'Package "%s" is blocked' "$pkg"
2055 try_aufs_chroot "$@"
2057 # Log and source receipt.
2058 _ 'Cook started for: %s' "<a href='cooker.cgi?pkg=${pkg//+/%2B}'>$pkg</a>" | log
2059 echo "cook:$pkg" > $command
2061 [ -n "$lastcooktime" ] && echo "cook:$pkg $lastcooktime $(date +%s)" >> $cooktime
2063 while read cmd duration start; do
2064 [ $(($start + $duration)) -lt $(date +%s) ] &&
2065 echo "sed -i '/^$cmd $duration/d' $cooktime"
2066 done < $cooktime | sh
2068 # Display and log info if cook process stopped.
2069 # FIXME: gettext not working (in single quotes) here!
2070 trap '_ "\n\nCook stopped: control-C\n\n" | \
2071 tee -a $LOGS/$pkg.log' INT
2073 update_split_db
2075 # Handle --options
2076 case "$2" in
2077 --install|-i)
2078 inst='yes' ;;
2080 --pack)
2081 [ -d "$WOK/$pkg/install" ] || die 'Need to build "%s"' "$pkg"
2082 [ ! -d "$WOK/$pkg/taz" ] || rm -rf "$WOK/$pkg/taz"
2083 [ ! -f "$LOGS/$pkg-pack.log" ] || rm -f $LOGS/$pkg-pack.log
2084 sed -i '$ s|$| (packing)|' $activity
2085 packall 2>&1 | tee -a $LOGS/$pkg-pack.log
2086 clean_log "$pkg-pack"
2087 time=$(($(date +%s) - $time))
2088 summary | sed 's|^Cook |Pack |' | tee -a $LOGS/$pkg-pack.log
2089 put_status $pkg Done
2090 rm -f $command
2091 exit 0 ;;
2093 --trials|-t)
2094 trials='yes' ;;
2095 esac
2097 # Rotate log
2098 for i in $(seq 9 -1 1); do
2099 j=$(($i - 1))
2100 [ -e $LOGS/$pkg.log.$j ] && mv -f $LOGS/$pkg.log.$j $LOGS/$pkg.log.$i
2101 done
2102 [ -e $LOGS/$pkg.log ] && mv $LOGS/$pkg.log $LOGS/$pkg.log.0
2104 # Check if wanted is built now so we have separate log files.
2105 for wanted in $WANTED ; do
2106 if grep -q "^$wanted$" $blocked; then
2107 broken
2108 rm -f $command
2109 die 'WANTED package "%s" is blocked' "$wanted"
2110 fi
2111 if grep -q "^$wanted$" $broken; then
2112 broken
2113 rm -f $command
2114 die 'WANTED package "%s" is broken' "$wanted"
2115 fi
2116 if [ ! -d "$WOK/$wanted/install" ]; then
2117 cook "$wanted" || { broken; exit 1; }
2118 fi
2119 done
2121 # Cook and pack or exit on error and log everything.
2122 ((((cookit $@ 2>&1; echo $? >&3) | loglimit 50 > $LOGS/$pkg.log) 3>&1) | (read rq; exit $rq))
2123 rq=$? # the return code of `cookit $@` above command
2125 # Remove build dependencies both when `cookit` done or fail
2126 remove_deps | tee -a $LOGS/$pkg.log
2127 timestamp job27 # removing bdeps
2128 cookit_quality
2129 timestamp job28 # checking quality
2131 # Log and stop if `cookit` fails
2132 if [ $rq -eq 1 ]; then
2133 debug_info | tee -a $LOGS/$pkg.log
2134 put_status $pkg Failed
2135 rm -f $command
2136 broken; exit 1
2137 fi
2139 # Proceed only if `cookit` return code is zero-OK
2140 packall 2>&1 | loglimit 5 >> $LOGS/$pkg.log
2141 timestamp job29 # packing
2143 clean_log
2145 # Exit if any error in packing.
2146 if [ "${COOKOPTS/skip-log-errors/}" == "$COOKOPTS" ] &&
2147 grep -Ev "(/root/.cvspass|conftest|df: /|rm: can't remove)" $LOGS/$pkg.log | \
2148 grep -Eq "(^ERROR|: No such file or directory|not remade because of errors|ake: \*\*\* .* Error)"; then
2149 debug_info | tee -a $LOGS/$pkg.log
2150 put_status $pkg Failed
2151 rm -f $command
2152 broken; exit 1
2153 fi
2155 # Create an XML feed
2156 gen_rss
2158 # Time and summary
2159 time=$(($(date +%s) - $time))
2160 summary | tee -a $LOGS/$pkg.log
2161 newline
2163 # We may want to install/update (outside aufs jail!).
2164 [ -s /aufs-umount.sh ] || install_package
2166 put_status $pkg Done
2168 # Finally we DON'T WANT to build the *-dev or packages with WANTED="$pkg"
2169 # If you want automation, use the Cooker Build Bot.
2170 rm -f $command
2171 timestamp job30 # misc. final operations
2172 store_timestats
2174 sed -n '/^Build dependencies to remove:/,/^$/p' $LOGS/$pkg.log \
2175 | sed '/^Build/d; s|Removing: ||' \
2176 | tr ' ' '\n' \
2177 | sed '/^$/d' \
2178 > $WOK/$pkg/.bdeps
2180 ;;
2181 esac
2183 exit 0