cookutils view cook @ rev 1089

lighttpd/index.cgi: [ For maintainers ]: you can use regexp now to list packages
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sat Aug 25 17:30:05 2018 +0300 (2018-08-25)
parents edf99e944ce6
children 77291d41f21a
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 # Find the package, return the receipt name where it was found
90 # for example, libpcreposix -> pcre
92 find_pkg_in_wok() {
93 awk -F$'\t' -vi="$1" '{
94 if (index(" " $2 " ", i)) {print $1; exit}
95 }' $cache/split.db
96 }
99 # Initialize files used in $CACHE
101 init_db_files() {
102 _ 'Creating directories structure in "%s"' "$SLITAZ"
103 mkdir -p $WOK $PKGS $SRC $CACHE $LOGS $FEEDS
104 _ 'Creating DB files in "%s"' "$CACHE"
105 touch $activity $command $broken $blocked $CACHE/webstat
106 chown www:www $cache/webstat
107 }
110 # Paths used in receipt and by cook itself.
112 set_paths() {
113 # Kernel version is set from wok/linux or installed/linux-api-headers(wok-undigest)
114 if [ -f "$WOK/linux/receipt" ]; then
115 kvers=$(. $WOK/linux/receipt; echo $VERSION)
116 kbasevers=$(echo $kvers | cut -d. -f1,2)
117 elif [ -f "$INSTALLED/linux-api-headers/receipt" ]; then
118 kvers=$(. $INSTALLED/linux-api-headers/receipt; echo $VERSION)
119 kbasevers=$(echo $kvers | cut -d. -f1,2)
120 fi
122 # Python version
123 [ -f "$WOK/python/receipt" ] && pyvers=$(. $WOK/python/receipt; echo $VERSION)
124 # Perl version for some packages needed it
125 [ -f "$WOK/perl/receipt" ] && perlvers=$(. $WOK/perl/receipt; echo $VERSION)
127 pkgdir="$WOK/$pkg"
128 . "$pkgdir/receipt"
129 basesrc="$pkgdir/source"
130 tmpsrc="$basesrc/tmp"
131 src="$basesrc/$PACKAGE-$VERSION"
132 taz="$pkgdir/taz"
133 pack="$taz/${1:-$PACKAGE}-$VERSION$EXTRAVERSION" # v2: multiple taz/* folders
134 fs="$pack/fs"
135 stuff="$pkgdir/stuff"
136 install="$pkgdir/install"
138 pkgsrc="${SOURCE:-$PACKAGE}-${KBASEVER:-$VERSION}"
139 lzma_tarball="$pkgsrc.tar.lzma"
141 [ -n "$PATCH" -a -z "$PTARBALL" ] && PTARBALL="$(basename $PATCH)"
143 if [ -n "$WANTED" ]; then
144 basesrc="$WOK/$WANTED/source"
145 src="$basesrc/$WANTED-$VERSION"
146 install="$WOK/$WANTED/install"
147 wanted_stuff="$WOK/$WANTED/stuff"
148 fi
150 [ -n "$SOURCE" ] && source_stuff="$WOK/$SOURCE/stuff"
152 # Old way compatibility.
153 _pkg="$install"
154 }
157 # Create source tarball when URL is a SCM.
159 create_tarball() {
160 local tarball
161 tarball="$pkgsrc.tar.bz2"
162 [ -n "$LZMA_SRC" ] && tarball="$lzma_tarball"
163 _ 'Creating tarball "%s"' "$tarball"
164 if [ -n "$LZMA_SRC" ]; then
165 tar -c $pkgsrc | lzma e $SRC/$tarball -si $LZMA_SET_DIR || exit 1
166 LZMA_SRC=''
167 else
168 tar -cjf $tarball $pkgsrc || exit 1
169 mv $tarball $SRC; rm -rf $pkgsrc
170 fi
171 TARBALL="$tarball"
172 }
175 # Get package source. For SCM we are in cache so clone here and create a
176 # tarball here.
178 get_source() {
179 local url
180 url=${WGET_URL#*|}
181 set_paths
182 pwd=$(pwd)
183 case "$WGET_URL" in
184 http://*|ftp://*|https://*)
185 url="$MIRROR_URL/sources/packages/${TARBALL:0:1}/$TARBALL"
186 wget -T 60 -c -O $SRC/$TARBALL $WGET_URL ||
187 wget -T 60 -c -O $SRC/$TARBALL $url ||
188 die 'ERROR: %s' "wget $WGET_URL"
189 ;;
191 hg*|mercurial*)
192 _ 'Getting source from %s...' 'Hg'
193 _ 'URL: %s' "$url"
194 _ 'Cloning to "%s"' "$pwd/$pkgsrc"
195 if [ -n "$BRANCH" ]; then
196 _ 'Hg branch: %s' "$BRANCH"
197 hg clone $url --rev $BRANCH $pkgsrc ||
198 die 'ERROR: %s' "hg clone $url --rev $BRANCH"
199 else
200 hg clone $url $pkgsrc || die 'ERROR: %s' "hg clone $url"
201 fi
202 rm -rf $pkgsrc/.hg
203 create_tarball
204 ;;
206 git*)
207 _ 'Getting source from %s...' 'Git'
208 _ 'URL: %s' "$url"
209 cd $SRC
210 git clone $url $pkgsrc || die 'ERROR: %s' "git clone $url"
211 if [ -n "$BRANCH" ]; then
212 _ 'Git branch: %s' "$BRANCH"
213 cd $pkgsrc; git checkout $BRANCH; cd ..
214 fi
215 cd $SRC
216 create_tarball
217 ;;
219 cvs*)
220 mod=$PACKAGE
221 [ -n "$CVS_MODULE" ] && mod=$CVS_MODULE
222 _ 'Getting source from %s...' 'CVS'
223 _ 'URL: %s' "$url"
224 [ -n "$CVS_MODULE" ] && _ 'CVS module: %s' "$mod"
225 _ 'Cloning to "%s"' "$pwd/$mod"
226 cvs -d:$url co $mod && mv $mod $pkgsrc
227 create_tarball
228 ;;
230 svn*|subversion*)
231 _ 'Getting source from %s...' 'SVN'
232 _ 'URL: %s' "$url"
233 if [ -n "$BRANCH" ]; then
234 echo t | svn co $url -r $BRANCH $pkgsrc
235 else
236 echo t | svn co $url $pkgsrc
237 fi
238 create_tarball
239 ;;
241 bzr*)
242 _ 'Getting source from %s...' 'bazaar'
243 cd $SRC
244 pkgsrc=${url#*:}
245 if [ -n "$BRANCH" ]; then
246 echo "bzr -Ossl.cert_reqs=none branch $url -r $BRANCH"
247 bzr -Ossl.cert_reqs=none branch $url -r $BRANCH
248 else
249 echo "bzr -Ossl.cert_reqs=none branch $url"
250 bzr -Ossl.cert_reqs=none branch $url
251 cd $pkgsrc; BRANCH=$(bzr revno); cd ..
252 _ "Don't forget to add to receipt:"
253 echo -e "BRANCH=\"$BRANCH\"\n"
254 fi
255 mv $pkgsrc $pkgsrc-$BRANCH
256 pkgsrc="$pkgsrc-$BRANCH"
257 create_tarball
258 ;;
260 *)
261 broken; die 'ERROR: Unable to handle "%s"' "$WGET_URL"
262 ;;
263 esac
264 }
267 # Extract source package.
269 extract_source() {
270 if [ ! -s "$SRC/$TARBALL" ]; then
271 local url
272 url="$MIRROR_URL/sources/packages"
273 url="$url/${TARBALL:0:1}/$TARBALL"
274 _ 'Getting source from %s...' 'mirror'
275 _ 'URL: %s' "$url"
276 busybox wget -c -P $SRC $url || _ 'ERROR: %s' "wget $url"
277 fi
278 _ 'Extracting source archive "%s"' "$TARBALL"
279 case "$TARBALL" in
280 *.tar.gz|*.tgz) tar -xzf $SRC/$TARBALL 2>/dev/null ;;
281 *.tar.bz2|*.tbz|*.tbz2) tar -xjf $SRC/$TARBALL 2>/dev/null ;;
282 *.tar.lzma) tar -xaf $SRC/$TARBALL ;;
283 *.tar.lz|*.tlz) lzip -d < $SRC/$TARBALL | tar -xf - 2>/dev/null ;;
284 *.tar) tar -xf $SRC/$TARBALL ;;
285 *.zip|*.xpi) unzip -o $SRC/$TARBALL 2>/dev/null >&2;;
286 *.xz) unxz -c $SRC/$TARBALL | tar -xf - || \
287 tar -xf $SRC/$TARBALL 2>/dev/null;;
288 *.7z) 7zr x $SRC/$TARBALL 2>/dev/null >&2 ;;
289 *.Z|*.z) uncompress -c $SRC/$TARBALL | tar -xf - ;;
290 *.rpm) rpm2cpio $SRC/$TARBALL | cpio -idm --quiet ;;
291 *.run) /bin/sh $SRC/$TARBALL $RUN_OPTS ;;
292 *) cp $SRC/$TARBALL $(pwd) ;;
293 esac
294 }
297 # Display time.
299 disp_time() {
300 local sec div min
301 sec="$1"
302 div=$(( ($1 + 30) / 60))
303 case $div in
304 0) min='';;
305 # L10n: 'm' is for minutes (approximate cooking time)
306 *) min=$(_n ' ~ %dm' "$div");;
307 esac
309 # L10n: 's' is for seconds (cooking time)
310 _ '%ds%s' "$sec" "$min"
311 }
314 # Display cooked package summary.
316 summary() {
317 local arch=''
318 case "$ARCH" in
319 arm*|x86_64) arch="-$ARCH" ;;
320 esac
322 set_paths
323 cd $WOK/$pkg
324 [ -d $WOK/$pkg/install ] && prod=$(du -sh $WOK/$pkg/install | awk '{print $1}' 2>/dev/null)
325 [ -d $WOK/$pkg/source ] && srcdir=$(du -sh $WOK/$pkg/source | awk '{print $1}' 2>/dev/null)
326 [ -n "$TARBALL" ] && srcsize=$(du -sh $SRC/$TARBALL | awk '{print $1}')
328 title 'Summary for: %s' "$PACKAGE $VERSION$EXTRAVERSION$arch"
330 # L10n: keep the same width of translations to get a consistent view
331 [ -n "$TARBALL" ] && _ 'Src file : %s' "$TARBALL"
332 [ -n "$srcsize" ] && _ 'Src size : %s' "$srcsize"
333 [ -n "$srcdir" ] && _ 'Source dir : %s' "$srcdir"
334 [ -n "$prod" ] && _ 'Produced : %s' "$prod"
335 _ 'Cook time : %s' "$(disp_time "$time")"
336 _ 'Cook date : %s' "$(date "$(_ '+%%F %%R')")"
337 _ 'Target arch : %s' "$ARCH"
339 separator -
340 _ ' # : Packed : Compressed : Files : Package name'
341 separator -
342 pkgi=1
343 for i in $(all_names); do
344 version=$(awk -F$'\t' -vpkg="$i" '{
345 if ($1 == pkg) {print $2; exit}
346 }' "$PKGS/packages.info")
347 fs=$(du -sh $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION | awk '{print $1}')
348 pkgname="$i-$version$arch.tazpkg"
349 size=$(ls -lh $PKGS/$pkgname | awk '{print $5}')
350 files=$(wc -l < $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION/files.list)
351 printf "%2d : %7s : %10s : %5s : %s\n" "$pkgi" "$fs" "$size" "$files" "$pkgname"
352 pkgi=$((pkgi + 1))
353 done
354 separator
355 }
358 # Display debugging error info.
360 debug_info() {
361 title 'Debug information'
362 # L10n: specify your format of date and time (to help: man date)
363 # L10n: not bad one is '+%x %R'
364 _ 'Cook date: %s' "$(date "$(_ '+%%F %%R')")"
365 if [ -n "$time" ]; then
366 times="$(($(date +%s) - $time))"
367 _ 'Wasted time : %s' "$(disp_time "$times")"
368 fi
369 for error in \
370 ERROR 'No package' "cp: can't" "can't open" "can't cd" \
371 'error:' 'fatal error:' 'undefined reference to' \
372 'Unable to connect to' 'link: cannot find the library' \
373 'CMake Error' ': No such file or directory' \
374 'Could not read symbols: File in wrong format'
375 do
376 # format "line number:line content"
377 fgrep -n "$error" $LOGS/$pkg.log
378 done > $LOGS/$pkg.log.debug_info 2>&1
379 # sort by line number, remove duplicates
380 sort -gk1,1 -t: -u $LOGS/$pkg.log.debug_info
381 rm -f $LOGS/$pkg.log.debug_info
382 footer
383 }
386 # A bit smarter function than the classic `cp` command
388 scopy() {
389 if [ "$(stat -c %h -- "$1")" -eq 1 ]; then
390 cp -a "$1" "$2" # copy generic files
391 else
392 cp -al "$1" "$2" # copy hardlinks
393 fi
394 }
397 # Copy all generic files (locale, pixmaps, .desktop) from $install to $fs.
398 # We use standard paths, so some packages need to copy these files with the
399 # receipt and genpkg_rules.
400 # This function executes inside the packaging process, before compressor call.
402 copy_generic_files() {
403 # Proceed only for "main" package (for v2), and for any packages (v1)
404 [ "$pkg" == "$PACKAGE" ] || return 0
406 # $LOCALE is set in cook.conf
407 if [ -n "$LOCALE" -a -z "$WANTED" ]; then
408 if [ -d "$install/usr/share/locale" ]; then
409 mkdir -p "$fs/usr/share/locale"
410 for i in $LOCALE; do
411 if [ -d "$install/usr/share/locale/$i" ]; then
412 cp -r $install/usr/share/locale/$i $fs/usr/share/locale
413 fi
414 done
415 fi
416 fi
418 # Generic pixmaps copy can be disabled with COOKOPTS="!pixmaps" (or GENERIC_PIXMAPS="no")
419 if [ "${COOKOPTS/!pixmaps/}" == "$COOKOPTS" -a "$GENERIC_PIXMAPS" != 'no' ]; then
420 if [ -d "$install/usr/share/pixmaps" ]; then
421 mkdir -p "$fs/usr/share/pixmaps"
422 for i in png xpm; do
423 [ -f "$install/usr/share/pixmaps/$PACKAGE.$i" -a ! -f "$fs/usr/share/pixmaps/$PACKAGE.$i" ] &&
424 cp -r $install/usr/share/pixmaps/$PACKAGE.$i $fs/usr/share/pixmaps
425 done
426 fi
427 fi
429 # Desktop entry (.desktop).
430 # Generic desktop entry copy can be disabled with COOKOPTS="!menus" (or GENERIC_MENUS="no")
431 if [ "${COOKOPTS/!menus/}" == "$COOKOPTS" -a "$GENERIC_MENUS" != 'no' ]; then
432 if [ -d "$install/usr/share/applications" -a -z "$WANTED" ]; then
433 mkdir -p "$fs/usr/share"
434 cp -r $install/usr/share/applications $fs/usr/share
435 fi
436 fi
437 }
440 # Copy pixmaps, desktop files and licenses from $stuff to $install.
441 # This function executes after the main compile_rules() is done.
443 copy_generic_stuff() {
444 # Custom or homemade PNG pixmap can be in stuff.
445 if [ -f "$stuff/$PACKAGE.png" ]; then
446 mkdir -p $install/usr/share/pixmaps
447 cp $stuff/$PACKAGE.png $install/usr/share/pixmaps
448 fi
450 # Homemade desktop file(s) can be in stuff.
451 if [ -d "$stuff/applications" ]; then
452 mkdir -p $install/usr/share
453 cp -r $stuff/applications $install/usr/share
454 fi
455 if [ -f "$stuff/$PACKAGE.desktop" ]; then
456 mkdir -p $install/usr/share/applications
457 cp $stuff/$PACKAGE.desktop $install/usr/share/applications
458 fi
460 # Add custom licenses
461 if [ -d "$stuff/licenses" ]; then
462 mkdir -p $install/usr/share/licenses
463 cp -r $stuff/licenses $install/usr/share/licenses/$PACKAGE
464 fi
465 }
468 # Update installed.cook.diff
470 update_installed_cook_diff() {
471 # If a cook failed deps are removed.
472 cd $root$INSTALLED; ls -1 > $CACHE/installed.cook
473 cd $CACHE
474 [ "$1" == 'force' -o ! -s '/tmp/installed.cook.diff' ] && \
475 busybox diff installed.list installed.cook > /tmp/installed.cook.diff
476 deps=$(grep ^+[a-zA-Z0-9] /tmp/installed.cook.diff | wc -l)
477 }
480 # Remove installed deps.
482 remove_deps() {
483 # Now remove installed build deps.
484 diff='/tmp/installed.cook.diff'
485 [ -s "$diff" ] || return
487 deps=$(grep ^+[a-zA-Z0-9] $diff | sed 's|^+||')
488 nb=$(grep ^+[a-zA-Z0-9] $diff | wc -l)
489 newline
490 _n 'Build dependencies to remove:'; echo " $nb"
491 [ -n "$root" ] && echo "root=\"$root\""
492 {
493 _n 'Removing:'
494 for dep in $deps; do
495 echo -n " $dep"
496 # Do not waste time uninstalling the packages if we are inside
497 # aufs chroot - unmounting chroot will "uninstall" all packages.
498 [ -s /aufs-umount.sh ] ||
499 echo 'y' | tazpkg remove $dep --root=$root >/dev/null
500 done
501 } | busybox fold -sw80
502 newline; newline
503 # Keep the last diff for debug and info.
504 mv -f $diff $CACHE/installed.diff
505 }
508 # Automatically patch the sources.
510 patchit() {
511 [ -f "$stuff/patches/series" ] || return
513 IFS=$'\n'
514 while read i; do
515 patchname=$(echo ${i%%#*} | cut -d' ' -f1) # allow comments (anything after the # or space)
516 case $patchname in # allow patch options in form <options_no_spaces>|<file_name>
517 *\|*) patchopts="${patchname%|*}"; patchname="${patchname#*|}";;
518 *) patchopts='-Np1';;
519 esac
520 [ -n "$patchname" ] || continue # allow empty lines
521 [ -f "$src/done.$patchname" ] && continue # already applied (useful with `cook --continue`)
522 newline
523 _ 'Applying patch %s' "$patchname"
524 patch $patchopts -i $stuff/patches/$patchname | sed 's|^| |'
525 touch $src/done.$patchname
526 done < $stuff/patches/series
527 newline
528 unset IFS
529 }
532 # Check source tarball integrity.
534 check_integrity() {
535 for i in sha1 sha3 sha256 sha512 md5; do
536 I=$(echo $i | tr 'a-z' 'A-Z')
537 eval sum=\$TARBALL_$I
538 if [ -n "$sum" ]; then
539 newline
540 _ 'Checking %ssum of source tarball...' "$i"
541 echo "$sum $SRC/$TARBALL" | ${i}sum -c || exit 1
542 fi
543 done
544 newline
545 }
548 # Misc fix functions
550 fix() {
551 case $1 in
552 # https://bugzilla.gnome.org/show_bug.cgi?id=655517
553 # https://wiki.gentoo.org/wiki/Project:Quality_Assurance/As-needed
554 ld)
555 export LDFLAGS="$LDFLAGS -Wl,-Os,--as-needed"
556 ;;
557 libtool)
558 if [ -e 'libtool' ]; then
559 sed -i 's| -shared | -Wl,-Os,--as-needed\0|g' libtool
560 else
561 echo "fix libtool: warning: libtool absent, nothing to fix."
562 fi
563 ;;
564 math)
565 # fix C++ math issue introduced in Glibc 2.26:
566 # error: '__builtin_isnan' is not a member of 'std'
567 # if (std::isnan(N)) {
568 # ^
569 find $src -type f -exec sed -i '
570 s|std::signbit|__builtin_signbit|g;
571 s|std::isnan|__builtin_isnan|g;
572 s|std::isinf|__builtin_isinf_sign|g;
573 s|std::isfinite|__builtin_isfinite|g;
574 s|std::isnormal|__builtin_isnormal|g
575 ' '{}' \;
576 ;;
577 symlinks)
578 # make absolute symlinks relative
579 echo "fix symlinks"
580 local ifs="$IFS" link target
581 IFS=$'\n'
582 # step 1: fast job, prefix all the absolute symlinks with "$install"
583 for link in $(find $install -type l); do
584 target="$(readlink $link)"
585 case "$target" in
586 /*) ln -sfv "$install$target" "$link";;
587 esac
588 done
589 IFS="$ifs"
590 # step 2: fine tuning, make symlinks relative
591 tazpkg -gi --quiet --local --cookmode symlinks
592 symlinks -cr $install
593 ;;
594 gem)
595 # some useful operations while Ruby gems cooking
596 _gems="$(ruby -e'puts Gem.default_dir')"
598 # remove unwanted empty folders
599 rmdir --ignore-fail-on-non-empty \
600 $install/$_gems/build_info/ \
601 $install/$_gems/cache/ \
602 $install/$_gems/doc/ \
603 $install/$_gems/extensions/
605 # move files to docdir
606 docdir=$install/usr/share/doc/$PACKAGE-$VERSION
607 for i in $(ls -ap $install/$_gems/gems/${PACKAGE#*-}-$VERSION/ | sed '
608 /\/$/d; /^\./d; /gemspec$/d; /Rakefile*/d; /Gemfile*/d; /Makefile/d;
609 /\.c$/d; /\.h$/d; /\.o$/d; /\.rb$/d; /\.so$/d; /\.yml$/d;
610 /Manifest/d; /\.inc$/d; /depend/d;
611 '); do
612 mkdir -p $docdir # docdir will not be created when nothing to move
613 mv $install/$_gems/gems/${PACKAGE#*-}-$VERSION/$i $docdir
614 done
615 if [ -d $install/$_gems/gems/${PACKAGE#*-}-$VERSION/doc/ ]; then
616 mkdir -p $docdir
617 mv $install/$_gems/gems/${PACKAGE#*-}-$VERSION/doc/ $docdir
618 fi
620 if [ -d $docdir ]; then
621 # move man pages
622 unset man_to_copy
623 for i in $(seq 1 8); do
624 for j in $(find $docdir -type f -name "*.$i" | sed '/LGPL-2\.1/d'); do
625 man_to_copy="$man_to_copy $j"
626 done
627 done
628 if [ -n "$man_to_copy" ]; then
629 cook_pick_manpages $man_to_copy
630 rm $man_to_copy
631 fi
633 # convert rdoc to markdown (thanks https://gist.github.com/teeparham/8a99e308884e1c32735a)
634 for i in $(find $docdir -type f -name '*.rdoc'); do
635 fix utf-8
636 LC_ALL=en_US.UTF-8 ruby -r rdoc -e 'puts RDoc::Markup::ToMarkdown.new.convert File.read(ARGV[0] || "'$i'")' >$i.md && rm $i || rm $i.md
637 done
638 fi
640 # move man pages (from the different place)
641 rubyman=$install/$_gems/gems/${PACKAGE#*-}-$VERSION/man
642 if [ -d $rubyman ]; then
643 unset man_to_copy
644 for i in $(seq 1 8); do
645 for j in $(find $rubyman -type f -name "*.$i" | sed '/LGPL-2\.1/d'); do
646 man_to_copy="$man_to_copy $j"
647 done
648 done
649 if [ -n "$man_to_copy" ]; then
650 cook_pick_manpages $man_to_copy
651 fi
652 rm -r $rubyman
653 fi
654 ;;
655 utf-8)
656 # Install UTF-8 locale
657 tazpkg -gi --quiet --local --cookmode locale-en-base
658 mkdir -p /usr/lib/locale
659 localedef -i 'en_US' -c -f 'UTF-8' /usr/lib/locale/en_US.UTF-8
660 ;;
661 esac
662 }
665 # Store timestamps, log jobs length
667 timestamp() {
668 local ts_file="$WOK/$pkg/.ts"
669 local curr_ts=$(date '+%s')
670 case $1 in
671 init)
672 rm $ts_file 2>/dev/null
673 echo $curr_ts > $prev_ts
674 ;;
675 job*)
676 # calculate time from the last timestamp
677 echo "$1='$(( $curr_ts - $(cat $prev_ts) ))'" >> $ts_file
678 echo $curr_ts > $prev_ts
679 ;;
680 sets)
681 echo "sets='$2'" >> $ts_file
682 ;;
683 esac
684 }
687 # Store time statsistics to the cache
689 store_timestats() {
690 # see doc/timestats.txt for file format
691 temp=$(mktemp)
692 {
693 for i in $(seq 1 30); do echo "job$i=0"; done
694 cat $WOK/$pkg/.ts
695 echo -n 'total=$(( 0'
696 for i in $(seq 1 30); do echo -n " + job$i"; done
697 echo ' ))'
698 } > $temp
699 . $temp
700 {
701 echo -n "$pkg $sets "
702 for i in $(seq 1 30); do echo -n "$((job$i)) "; done
703 echo "$total"
704 } >> /home/slitaz/cache/timestats
705 rm $temp $WOK/$pkg/.ts # clean
706 }
709 # Internal function to cook specified SET
711 cook_set() {
712 # Switch to the specified source set
713 set_paths
714 local suffix=''
715 [ -n "$SET" ] && suffix="-$SET"
716 export src="$WOK/$pkg/source/$PACKAGE-$VERSION$suffix"
717 export install="$WOK/$pkg/install$suffix"
718 export DESTDIR="$install"
720 if [ -n "$SETS" ]; then
721 if [ -n "$SET" ]; then
722 title "Switching to the set '$SET'"
723 else
724 title "Switching to the default set"
725 fi
726 echo "src : $src"
727 echo "install: $install"
728 fi
729 [ -d "$src" ] && cd $src # packages without sources exists
730 echo
732 [ -d "$install" ] && rm -r $install
733 #mkdir -p $install
735 compile_rules $@ || { broken; exit 1; }
737 # Stay compatible with _pkg
738 [ -d "$src/_pkg" ] && mv $src/_pkg $install
740 copy_generic_stuff
742 timestamp job$job_counter # compiling (set '$SET')
744 # Actions to do after compiling the package
745 # Skip all for split packages (already done in main package)
746 if [ -z "$WANTED" ]; then
747 footer
748 export COOKOPTS ARCH install
749 @@PREFIX@@/libexec/cookutils/compressor install
750 timestamp job$(($job_counter + 1)) # compressing (set '$SET')
751 fi
753 # Activate "instant-pack" mode
754 if [ "${COOKOPTS/instant-pack/}" != "$COOKOPTS" ]; then
755 echo " $SPLIT " | fgrep -q " $PACKAGE " || SPLIT="$PACKAGE $SPLIT"
756 # determine the list of the packages belongs to the current SET...
757 echo -n $SPLIT \
758 | awk -vset="$SET" '
759 BEGIN { RS = " "; FS = ":"; }
760 { if ($2 == set) print $1; }' \
761 | while read SET_PKG; do
762 # ... and then pack them
763 packit $SET_PKG
764 done
765 fi
767 job_counter=$(($job_counter + 2))
768 }
771 # The main cook function.
773 cookit() {
774 if [ -n "$SETUP_MD5" -a "$SETUP_MD5" != "$(ls $root$INSTALLED | md5sum | cut -c1-32)" ]; then
775 _ 'ERROR: Broken setup. Abort.'
776 return
777 fi
779 title 'Cook: %s' "$PACKAGE $VERSION"
780 set_paths
781 timestamp init # the very start
783 # Handle cross-tools.
784 [ "$BUILD_SYSTEM" != "$HOST_SYSTEM" ] &&
785 case "$ARCH" in
786 arm*|x86_64)
787 # CROSS_COMPILE is used by at least Busybox and the kernel to set
788 # the cross-tools prefix. Sysroot is the root of our target arch
789 sysroot="$CROSS_TREE/sysroot"
790 tools="$CROSS_TREE/tools"
791 # Set root path when cross compiling. ARM tested but not x86_64
792 # When cross compiling we must install build deps in $sysroot.
793 arch="-$ARCH"
794 root="$sysroot"
795 _ '%s sysroot: %s' "$ARCH" "$sysroot"
796 _ 'Adding "%s" to PATH' "$tools/bin"
797 export PATH="$PATH:$tools/bin"
798 export PKG_CONFIG_PATH="$sysroot/usr/lib/pkgconfig"
799 export CROSS_COMPILE="$HOST_SYSTEM-"
800 _ 'Using cross-tools: %s' "$CROSS_COMPILE"
801 if [ "$ARCH" == 'x86_64' ]; then
802 export CC="$HOST_SYSTEM-gcc -m64"
803 export CXX="$HOST_SYSTEM-g++ -m64"
804 else
805 export CC="$HOST_SYSTEM-gcc"
806 export CXX="$HOST_SYSTEM-g++"
807 fi
808 export AR="$HOST_SYSTEM-ar"
809 export AS="$HOST_SYSTEM-as"
810 export RANLIB="$HOST_SYSTEM-ranlib"
811 export LD="$HOST_SYSTEM-ld"
812 export STRIP="$HOST_SYSTEM-strip"
813 export LIBTOOL="$HOST_SYSTEM-libtool"
814 ;;
815 esac
817 @@PREFIX@@/libexec/cookutils/precheck $receipt || exit 1 # former receipt_quality()
819 cd $pkgdir
820 [ -z "$continue" ] && rm -rf source 2>/dev/null
821 rm -rf install taz 2>/dev/null
823 # Disable -pipe if less than 512 MB free RAM.
824 free=$(awk '/^MemFree|^Buffers|^Cached/{s+=$2}END{print int(s/1024)}' /proc/meminfo)
825 if [ "$free" -lt 512 ] && [ "$CFLAGS" != "${CFLAGS/-pipe}" ]; then
826 _ 'Disabling -pipe compile flag: %d MB RAM free' "$free"
827 CFLAGS="${CFLAGS/-pipe}"; CFLAGS=$(echo "$CFLAGS" | tr -s ' ')
828 CXXFLAGS="${CXXFLAGS/-pipe}"; CXXFLAGS=$(echo "$CXXFLAGS" | tr -s ' ')
829 fi
830 unset free
832 # Export flags and path to be used by make and receipt.
833 DESTDIR="$pkgdir/install"
834 # FIXME: L10n: Is this the right time for 'LC_ALL=C LANG=C'?
835 export DESTDIR MAKEFLAGS CFLAGS CXXFLAGS CONFIG_SITE LC_ALL=C LANG=C \
836 LDFLAGS
838 timestamp job1 # pre-checks
840 # BUILD_DEPENDS may vary depending on the ARCH
841 case "$ARCH" in
842 arm*) [ -n "$BUILD_DEPENDS_arm" ] && BUILD_DEPENDS=$BUILD_DEPENDS_arm ;;
843 x86_64) [ -n "$BUILD_DEPENDS_x86_64" ] && BUILD_DEPENDS=$BUILD_DEPENDS_x86_64 ;;
844 esac
846 # Check for build deps and handle implicit depends of *-dev packages
847 # (ex: libusb-dev :: libusb).
848 [ -n "$BUILD_DEPENDS" ] && _ 'Checking build dependencies...'
849 [ -n "$root" ] && _ 'Using packages DB: %s' "$root$DB"
851 # Get the list of installed packages
852 cd $root$INSTALLED; ls > $CACHE/installed.list
854 for action in check install; do
855 for dep in $BUILD_DEPENDS; do
856 implicit="${dep%-dev}"; [ "$implicit" == "$dep" ] && implicit=''
857 for i in $dep $implicit; do
858 # Skip if package already installed
859 [ -f "$root$INSTALLED/$i/receipt" ] && continue
861 case $action in
862 check)
863 # Search for local package or local provided-package
864 name=$(awk -F$'\t' -vpkg="$i" '{
865 if (index(" " $1 " " $10 " ", " " pkg " ")) {print $1; exit}
866 }' "$PKGS/packages.info")
867 if [ -z "$name" ]; then
868 # Search for package in mirror
869 name="$(awk -F$'\t' -vi="$i" '$1==i{print $1; exit}' "$root$DB/packages.info")"
870 [ -z "$name" -a "$i" == "$dep" ] && die 'ERROR: unknown dep "%s"' "$i"
871 fi
872 ;;
873 install)
874 tazpkg get-install $i --root=$root --local --quiet --cookmode || { broken; exit 1; }
875 ;;
876 esac
877 done
878 done
879 done
881 update_installed_cook_diff
883 timestamp job2 # installing bdeps
885 # Get source tarball and make sure we have source dir named:
886 # $PACKAGE-$VERSION to be standard in receipts. Here we use tar.lzma
887 # tarball if it exists.
888 if [ -n "$WGET_URL" -a ! -f "$SRC/$TARBALL" ]; then
889 if [ -f "$SRC/${SOURCE:-$PACKAGE}-$VERSION.tar.lzma" ]; then
890 TARBALL="${SOURCE:-$PACKAGE}-$VERSION.tar.lzma"
891 LZMA_SRC=''
892 else
893 get_source || { broken; exit 1; }
894 fi
895 fi
896 if [ -z "$WANTED" -a -n "$TARBALL" -a ! -d "$src" ]; then
897 mkdir -p $pkgdir/source/tmp; cd $pkgdir/source/tmp
898 if ! extract_source ; then
899 get_source
900 extract_source || { broken; exit 1; }
901 fi
902 if [ -n "$LZMA_SRC" ]; then
903 cd $pkgdir/source
904 if [ "$(ls -A tmp | wc -l)" -gl 1 -o -f "$(echo tmp/*)" ]; then
905 mv tmp tmp-1; mkdir tmp
906 mv tmp-1 tmp/${SOURCE:-$PACKAGE}-$VERSION
907 fi
908 if [ -d "tmp/${SOURCE:-$PACKAGE}-$VERSION" ]; then
909 cd tmp; tar -c * | lzma e $SRC/$TARBALL -si
910 fi
911 fi
913 cd $pkgdir/source/tmp
914 # Some archives are not well done and don't extract to one dir (ex lzma).
915 files=$(ls | wc -l)
916 [ "$files" -eq 1 -a -d "$(ls)" ] &&
917 mv * ../$PACKAGE-$VERSION
918 [ "$files" -eq 1 -a -f "$(ls)" ] &&
919 mkdir -p ../$PACKAGE-$VERSION &&
920 mv * ../$PACKAGE-$VERSION/$TARBALL
921 [ "$files" -gt 1 ] &&
922 mkdir -p ../$PACKAGE-$VERSION &&
923 mv * ../$PACKAGE-$VERSION
924 cd ..; rm -rf tmp
925 fi
927 # Check md5sum (or similar) for sources tarball
928 check_integrity
930 # Libtool shared libs path hack.
931 case "$ARCH" in
932 arm*) cross libhack ;;
933 esac
935 timestamp job3 # get/unpack src tarball
937 # Compiling all the sets
938 if grep -q ^compile_rules $receipt; then
939 _ 'Executing: %s' 'compile_rules'
940 echo "CFLAGS : $CFLAGS"
941 echo "CXXLAGS : $CXXFLAGS"
942 echo "CPPFLAGS : $CPPFLAGS"
943 echo "LDFLAGS : $LDFLAGS"
944 [ -d "$src" ] && cd $src
945 patchit
947 timestamp job4 # patching
949 # Get set names from $SPLIT variable, format ex. 'pkg1 pkg2:set1 pkg3:set2'
950 # Keep natural order of the sets, don't sort them alphabetically
951 SETS=$(echo -n $SPLIT \
952 | awk '
953 BEGIN { RS = " "; FS = ":"; }
954 {
955 if ($2 && ! set[$2]) { printf("%s ", $2); set[$2] = "1"; }
956 }' \
957 | sed 's| $||')
958 # Prepare specified source sets using patched sources
959 [ -n "$SETS" -a -d "$src" ] &&
960 for set in $SETS; do
961 echo "Preparing set $set" # debug
962 cp -a $src $src-$set
963 done
965 timestamp job5 # preparing sets
966 timestamp sets "$SETS"
968 job_counter='6'
970 SET='' cook_set # first run for empty SET
972 # Allow to change SETS after the first run, follow the changes
973 SETS=$(. $receipt; echo -n $SPLIT \
974 | awk '
975 BEGIN { RS = " "; FS = ":"; }
976 {
977 if ($2 && ! set[$2]) { printf("%s ", $2); set[$2] = "1"; }
978 }' \
979 | sed 's| $||')
980 for SET in $SETS; do
981 cook_set
982 done
983 else
984 mkdir -p $install # allow receipts without `compile_rules()`
985 fi
986 footer
988 timestamp job # reset counter
990 # Execute testsuite.
991 if grep -q ^testsuite $receipt; then
992 title 'Running testsuite'
993 testsuite $@ || { broken; exit 1; }
994 footer
995 fi
997 timestamp job26 # test suite
999 update_installed_cook_diff force
1003 # Cook quality assurance.
1005 cookit_quality() {
1006 while true; do
1007 [ ! -d "$WOK/$pkg/install" -a -z "$WANTED" ] || break
1008 _ 'ERROR: cook failed' | tee -a $LOGS/$pkg.log
1009 [ "$trials" == 'yes' ] || break
1010 title "Interactive mode"
1011 # TODO: allow commands:
1012 # q - quit; v - edit receipt here using vi;
1013 # s - search for package containing package;
1014 # <package name> - install package; [Enter] - retry
1015 _ 'You may install the packages here and/or edit the receipt there.'
1016 newline
1017 while true; do
1018 _n 'Install the package? [name/N] '; read answer
1019 [ -n "$answer" ] || break
1020 tazpkg -gi $answer --root=$root --local --quiet --cookmode
1021 done
1022 newline
1023 _n 'Try again? [Y/n] '; read answer
1024 [ "$answer" == 'n' ] && break
1025 # here you may append log if you want (">>" instead of last ">")
1026 cookit $@ 2>&1 | loglimit 50 > $LOGS/$pkg.log
1027 done
1029 [ "${COOKOPTS/skip-log-errors/}" != "$COOKOPTS" ] && return 0
1031 # ERROR can be echoed any time in cookit()
1032 if grep -Ev "(conftest|configtest)" $LOGS/$pkg.log | \
1033 grep -Eq "(^ERROR|undefined reference to)" ; then
1034 debug_info | tee -a $LOGS/$pkg.log
1035 put_status $pkg Failed
1036 rm -f $command
1037 broken; exit 1
1038 fi
1042 # Create the package. Wanted to use TazPkg to create a tazpkg package at first,
1043 # but it doesn't handle EXTRAVERSION.
1045 packit() {
1046 set_paths "$1"
1047 PACKAGE="${1:-$PACKAGE}"
1049 # Handle cross compilation
1050 case "$ARCH" in
1051 arm*|x86_64) arch="-$ARCH" ;;
1052 esac
1054 title 'Pack: %s' "$PACKAGE $VERSION$arch"
1056 # Get set name for specified package from $SPLIT variable
1057 local set=$(echo -n $SPLIT \
1058 | awk -vpkg="$PACKAGE" '
1059 BEGIN { RS = " "; FS = ":"; }
1060 { if ($1 == pkg && $2 != "") { print "-" $2; exit; } }')
1061 # Change set, make filelist and folderlist for new set
1062 export src="$src$set"
1063 export install="$install$set"
1064 export DESTDIR="$install"
1066 if grep -q ^genpkg_rules $receipt; then
1067 _ 'Executing: %s' 'genpkg_rules'
1068 set -e; cd $pkgdir; mkdir -p $fs
1069 genpkg_rules || (newline; _ 'ERROR: genpkg_rules failed'; newline) >> \
1070 $LOGS/$pkg.log
1071 else
1072 _ 'No packages rules: meta package'
1073 mkdir -p $fs
1074 fi
1076 # Check CONFIG_FILES
1077 if [ -n "$CONFIG_FILES" ]; then
1078 unset IFS
1079 for i in $CONFIG_FILES; do
1080 if [ ! -e $fs$i ]; then
1081 case $i in
1082 */) mkdir -p $fs$i ;;
1083 *) mkdir -p $fs$(dirname $i); touch $fs$i ;;
1084 esac
1085 fi
1086 done
1087 fi
1089 # First QA check to stop now if genpkg_rules failed.
1090 lerror=$(_n 'ERROR')
1091 if fgrep -q ^$lerror $LOGS/$pkg.log; then
1092 broken; exit 1
1093 fi
1095 cd $taz
1096 action 'Copying "%s"...' 'receipt'
1097 export PACKAGE VERSION CATEGORY SHORT_DESC WEB_SITE DEPENDS PROVIDE SUGGESTED TAZPANEL_DAEMON TAGS CAT CONFIG_FILES
1098 @@PREFIX@@/libexec/cookutils/mk_pkg_receipt "$(realpath ../receipt)" > $pack/receipt
1099 chown 0.0 $pack/receipt; status
1101 unset desc
1102 [ "$pkg" == "$PACKAGE" -a -f "../description.txt" ] && desc="../description.txt"
1103 [ -f "../description.$PACKAGE.txt" ] && desc="../description.$PACKAGE.txt"
1104 if [ -n "$desc" ]; then
1105 action 'Copying "%s"...' "$(basename "$desc")"
1106 cp -f $desc $pack/description.txt; chown 0.0 $pack/description.txt; status
1107 fi
1109 copy_generic_files
1111 # Strip and stuff files.
1112 export COOKOPTS ARCH HOST_SYSTEM LOCALE fs; @@PREFIX@@/libexec/cookutils/compressor fs
1114 # Create files.list with redirecting find output.
1115 action 'Creating the list of files...'
1116 cd $fs
1117 find . -type f -print > ../files.list
1118 find . -type l -print >> ../files.list
1119 cd ..; sed -i 's|^.||' files.list
1120 status
1122 # Md5sum of files.
1123 action 'Creating md5sum of files...'
1124 while read file; do
1125 [ -L "fs$file" ] && continue
1126 [ -f "fs$file" ] || continue
1127 case "$file" in
1128 /lib/modules/*/modules.*|*.pyc) continue ;;
1129 esac
1130 md5sum "fs$file" | sed 's| fs| |'
1131 done < files.list | sort -k2 > md5sum
1132 status
1134 UNPACKED_SIZE=$(du -chs fs receipt files.list md5sum description.txt \
1135 2>/dev/null | awk 'END{ print $1 }')
1137 # Build cpio archive.
1138 action 'Compressing the FS...'
1139 find fs -newer $receipt -exec touch -hr $receipt '{}' \;
1140 # find fs | cpio -o -H newc --quiet | lzma-alone e fs.cpio.lzma -si
1141 find fs | cpio -o -H newc --quiet | /bin/lzma -qzeT0 >fs.cpio.lzma
1142 mv fs ../
1143 status
1145 PACKED_SIZE=$(du -chs fs.cpio.lzma receipt files.list md5sum description.txt \
1146 2>/dev/null | awk 'END{ print $1 }')
1148 action 'Updating receipt sizes...'
1149 sed -i '/^PACKED_SIZE=/d; /^UNPACKED_SIZE=/d' receipt
1150 sed -i "s|^PACKAGE=|PACKED_SIZE=\"$PACKED_SIZE\"\nUNPACKED_SIZE=\"$UNPACKED_SIZE\"\nPACKAGE=|" receipt
1151 status
1153 # Set extra version.
1154 if [ -n "$EXTRAVERSION" ]; then
1155 action 'Updating receipt EXTRAVERSION: %s' "$EXTRAVERSION"
1156 sed -i '/^EXTRAVERSION=/d' receipt
1157 sed -i "s|^VERSION=|EXTRAVERSION=\"$EXTRAVERSION\"\nVERSION=|" receipt
1158 status
1159 fi
1161 # Compress.
1162 action 'Creating full cpio archive...'
1163 find . -newer $receipt -exec touch -hr $receipt '{}' \;
1164 find . | cpio -o -H newc --quiet > ../$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg
1165 status
1167 # Restoring original package tree.
1168 mv ../fs .
1170 rm fs.cpio.lzma; cd ..
1172 # QA and give info.
1173 tazpkg=$(ls *.tazpkg)
1174 packit_quality
1175 footer "$(_ 'Package "%s" created' "$tazpkg")"
1179 # Verify package quality and consistency.
1181 packit_quality() {
1182 local arch=''
1183 case "$ARCH" in
1184 arm*|x86_64) arch="-$ARCH" ;;
1185 esac
1187 local rsum rsumold='' rsum_changed old_file
1188 local pi="$PKGS/packages.info" fl="$cache/files.list"
1189 local pkg_file="$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg"
1190 local rsum_file=$(mktemp) rsum_file_old=$(mktemp) tmpdir=$(mktemp -d)
1193 if [ "${COOKOPTS/skip-log-errors/}" == "$COOKOPTS" ]; then
1194 # Exit if any error found in log file.
1195 if fgrep -q ^ERROR $LOGS/$pkg.log; then
1196 rm -f $command
1197 broken; exit 1
1198 fi
1199 fi
1202 [ -n "$CAT" ] && CATEGORY="${CAT%|*}" # allow meta-packages in v2 receipts
1204 if [ "${COOKOPTS/empty-pkg/}" == "$COOKOPTS" ]; then
1205 action 'QA: checking for empty package...'
1206 if [ ! -s "$pack/files.list" -a "$CATEGORY" != 'meta' ]; then
1207 broken
1208 rm -f $command
1209 false; status
1210 die 'ERROR: empty package'
1211 fi
1212 :; status
1213 fi
1216 # Calculate release checksum: usually it does not change on "just recook".
1217 # Release checksum is md5sum of file containing md5sums of:
1218 # a) all files, b) receipt, and c) description.txt.
1219 # Md5sum of the package file will change every time because of embedded timestamps;
1220 # release checksum based only on files content, and will change only when files change.
1221 # (Pitfall: ownership and permissions...)
1223 # Calculate rsum for new package
1224 cp $pack/md5sum $rsum_file
1225 md5sum $pack/receipt | sed 's| [^ ]*/| |' >> $rsum_file
1226 [ -e "$pack/description.txt" ] &&
1227 md5sum $pack/description.txt | sed 's| [^ ]*/| |' >> $rsum_file
1228 rsum=$(md5sum $rsum_file | awk '{print $1}')
1230 # Calculate rsum for existing previous "old" package
1231 if [ -f "$pkg_file" ]; then
1232 # don't trust database entry, check the package file
1233 cd $tmpdir
1234 cpio -F "$pkg_file" -i md5sum receipt description.txt >/dev/null 2>&1
1235 cp ./md5sum $rsum_file_old
1236 md5sum ./receipt | sed 's| [^ ]*/| |' >> $rsum_file_old
1237 [ -e "./description.txt" ] &&
1238 md5sum ./description.txt | sed 's| [^ ]*/| |' >> $rsum_file_old
1239 rsumold=$(md5sum $rsum_file_old | awk '{print $1}')
1240 cd - >/dev/null
1241 fi
1243 # Clean
1244 rm $rsum_file $rsum_file_old
1245 rm -r $tmpdir
1248 touch $pi $broken
1251 # Find and remove old package only if "release checksum" has changed
1253 if [ "$rsum" != "$rsumold" ]; then
1254 old_file=$(awk -F$'\t' -vname="$PACKAGE" -varch="$arch" '{
1255 if ($1 == name) printf("%s-%s%s.tazpkg", $1, $2, arch);
1256 }' $pi) # <name>-<version><extra_version><-arch>.tazpkg
1257 if [ -f "$PKGS/$old_file" ]; then
1258 action 'Removing old package "%s"' "$old_file"
1259 rm -f "$PKGS/$old_file"
1260 status
1261 fi
1262 # package changed, substitute old package by new one
1263 mv -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg $PKGS
1264 _ 'The release checksum has changed.'
1265 else
1266 # package not changed, remove new package
1267 rm -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg
1268 _ 'The release checksum has not changed.'
1269 fi
1272 sed -i "/^${pkg}$/d" $broken
1275 # Update packages database every time after successful build
1277 # packages.info (unsorted, located near to packages)
1278 unset_receipt; . $pack/receipt
1279 SIZES=$(echo $PACKED_SIZE $UNPACKED_SIZE | sed 's|\.0||g')
1280 DEPENDS=$(echo $DEPENDS) # remove newlines, tabs and multiple spaces from variable
1281 sed -i "/^$PACKAGE\t/d" $pi # remove old entry
1282 cat >> $pi <<EOT
1283 $PACKAGE $VERSION$EXTRAVERSION $CATEGORY $SHORT_DESC $WEB_SITE $TAGS $SIZES $DEPENDS $rsum $PROVIDE
1284 EOT
1286 # files.list (uncompressed, unsorted, located in $cache)
1287 touch $fl
1288 sed -i "/^$PACKAGE: /d" $fl
1289 sed "s/^/$PACKAGE: \0/" $pack/files.list >> $fl
1293 # Return all the names of packages bundled in this receipt
1295 all_names() {
1296 # Get package names from $SPLIT variable
1297 local split=$(echo -n $SPLIT \
1298 | awk '
1299 BEGIN { RS = " "; FS = ":"; }
1300 { print $1; }' \
1301 | tr '\n' ' ')
1302 local split_space=" $split "
1303 if ! head -n1 $WOK/$pkg/receipt | fgrep -q 'v2'; then
1304 # For receipts v1: $SPLIT may present in the $WANTED package,
1305 # but split packages have their own receipts
1306 echo $PACKAGE
1307 elif [ "${split_space/ $PACKAGE /}" != "$split_space" ]; then
1308 # $PACKAGE included somewhere in $SPLIT (probably in the end).
1309 # We should build packages in the order defined in the $SPLIT.
1310 echo $split
1311 else
1312 # We'll build the $PACKAGE, then all defined in the $SPLIT.
1313 echo $PACKAGE $split
1314 fi
1318 # v2: pack all packages using compiled files
1320 packall() {
1321 set_paths
1322 if head -n1 "$pkgdir/receipt" | fgrep -q 'v2'; then
1323 for i in $(all_names); do
1324 unset TAGS DEPENDS CAT CONFIG_FILES PROVIDE SUGGESTED DATABASE_FILES TAZPANEL_DAEMON
1325 packit $i
1326 done
1327 else
1328 packit
1329 fi
1333 # Reverse "cat" command: prints input lines in the reverse order
1335 tac() {
1336 sed '1!G;h;$!d' $1
1340 # Update chroot with freshly rebuilt package: keep env up-to-date.
1342 update_chroot() {
1343 local PACKAGE="$pkg"
1344 for i in $(all_names); do
1345 if [ -d "$root$INSTALLED/$i" ]; then
1346 . /etc/slitaz/cook.conf
1347 . $WOK/$pkg/taz/$i-$VERSION$EXTRAVERSION/receipt
1348 _ 'Updating %s chroot environment...' "$ARCH"
1349 _ 'Updating chroot: %s' "$i ($VERSION$EXTRAVERSION$arch)" | log
1350 cd $PKGS
1351 tazpkg -i "$PKGS/$i-$VERSION$EXTRAVERSION$arch.tazpkg" --forced --root=$root
1352 fi
1353 done
1357 # Install package on --inst or update the chroot.
1359 install_package() {
1360 set_paths
1361 case "$ARCH" in
1362 arm*)
1363 arch="-$ARCH"
1364 root="$CROSS_TREE/sysroot"
1365 ;;
1366 x86_64)
1367 arch="-$ARCH"
1368 ;;
1369 esac
1370 # Install package if requested but skip install if target host doesn't
1371 # match build system or it will break the build chroot.
1372 build=$(echo $BUILD_SYSTEM | cut -d- -f1)
1373 if [ -n "$inst" -a "$build" == "$ARCH" ]; then
1374 if [ -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg" ]; then
1375 cd $PKGS
1376 tazpkg -i "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION$arch.tazpkg" --forced
1377 else
1378 broken
1379 die 'Unable to install package, build has failed.'
1380 fi
1381 fi
1383 update_chroot
1387 # remove chroot jail
1389 umount_aufs() {
1390 tac ${1}rw/aufs-umount.sh | sh
1391 rm -rf ${1}rw
1392 umount ${1}root
1393 rmdir ${1}r*
1397 # Launch the cook command into a chroot jail protected by aufs.
1398 # The current filesystems are used read-only and updates are
1399 # stored in a separate branch.
1401 try_aufs_chroot() {
1403 base="/dev/shm/aufsmnt$$"
1405 # Can we setup the chroot? Is it already done?
1406 grep -q ^AUFS_NOT_SUPPORTED $receipt && return
1407 grep -q ^AUFS_NOT_RAMFS $receipt && base="/mnt/aufsmnt$$"
1408 [ -n "$AUFS_MOUNTS" -a ! -f /aufs-umount.sh ] || return
1409 grep -q ^aufs /proc/modules || modprobe aufs 2>/dev/null || return
1410 mkdir ${base}root ${base}rw || return
1412 _ 'Setup aufs chroot...'
1414 # Sanity check
1415 for i in / /proc /sys /dev /dev/shm /home; do
1416 case " $AUFS_MOUNTS " in
1417 *\ $i\ *) ;;
1418 *) AUFS_MOUNTS="$AUFS_MOUNTS $i" ;;
1419 esac
1420 done
1421 for mnt in $(ls -d $AUFS_MOUNTS | sort | uniq); do
1422 mkdir -p ${base}root$mnt # for `mount -o bind`
1423 mount -o bind $mnt ${base}root$mnt # use `-o bind` instead of `--bind`
1424 if [ $mnt == / ] && ! mount -t aufs -o br=${base}rw:/ none ${base}root; then
1425 _ 'Aufs mount failure'
1426 umount ${base}root
1427 rm -rf ${base}r*
1428 return
1429 fi
1430 echo "umount ${base}root$mnt" >> ${base}rw/aufs-umount.sh
1431 done
1432 trap "umount_aufs ${base}" INT
1434 chroot ${base}root $(cd $(dirname $0); pwd)/$(basename $0) "$@"
1435 status=$?
1437 _ 'Leaving aufs chroot...'
1438 umount_aufs $base
1439 # Install package outside the aufs jail
1440 install_package
1441 exit $status
1445 # Encode predefined XML entities
1447 xml_ent() {
1448 sed -e 's|&|\&amp;|g; s|<|\&lt;|g; s|>|\&gt;|g; s|"|\&quot;|g' -e "s|'|\&apos;|g"
1452 # Create a XML feed for freshly built packages.
1454 gen_rss() {
1455 pubdate=$(date '+%a, %d %b %Y %X')
1456 cat > $FEEDS/$pkg.xml <<EOT
1457 <item>
1458 <title>$PACKAGE $VERSION$EXTRAVERSION</title>
1459 <link>${COOKER_URL}?pkg=${PACKAGE//+/%2B}</link>
1460 <guid>$PACKAGE-$VERSION$EXTRAVERSION</guid>
1461 <pubDate>$pubdate</pubDate>
1462 <description>$(echo -n "$SHORT_DESC" | xml_ent)</description>
1463 </item>
1464 EOT
1468 # Truncate stdout log file to $1 Mb.
1470 loglimit() {
1471 if [ -n "$DEFAULT_LOG_LIMIT" ]; then
1472 tee /dev/stderr | head -qc ${1:-$DEFAULT_LOG_LIMIT}m
1473 else
1474 tee /dev/stderr
1475 fi
1480 # Receipt functions to ease packaging
1483 get_dev_files() {
1484 action 'Getting standard devel files...'
1485 mkdir -p $fs/usr/lib
1486 cp -a $install/usr/lib/pkgconfig $fs/usr/lib
1487 cp -a $install/usr/lib/*a $fs/usr/lib
1488 cp -a $install/usr/include $fs/usr
1489 status
1493 # Function to use in compile_rules() to copy man page from $src to $install
1495 cook_pick_manpages() {
1496 local name section
1497 action 'Copying man pages...'
1499 for i in $@; do
1500 name=$(echo $i | sed 's|\.[gbx]z2*$||')
1501 section=${name##*/}; section=${section##*.}
1502 mkdir -p $install/usr/share/man/man$section
1503 scopy $i $install/usr/share/man/man$section
1504 done
1505 status
1509 # Function to use in compile_rules() to copy documentation from $src to $install
1511 cook_pick_docs() {
1512 local docdir="$install/usr/share/doc/$PACKAGE-$VERSION"
1513 action 'Copying documentation...'
1514 mkdir -p $docdir
1515 cp -r $@ $docdir
1516 chmod -R a+r $docdir
1517 status
1521 # Function to use in genpkg_rules() to copy specified files from $install to $fs
1523 cook_copy_files() {
1524 action 'Copying files...'
1525 cd $install
1526 local i j
1527 IFS=$'\n'
1528 for i in $@; do
1529 for j in $(find . -name $i ! -type d); do
1530 mkdir -p $fs$(dirname ${j#.})
1531 scopy $j $fs$(dirname ${j#.})
1532 done
1533 done
1534 cd - >/dev/null
1535 status
1539 # Function to use in genpkg_rules() to copy specified folders from $install to $fs
1541 cook_copy_folders() {
1542 action 'Copying folders...'
1543 cd $install
1544 local i j
1545 IFS=$'\n'
1546 for i in $@; do
1547 for j in $(find . -name $i -type d); do
1548 mkdir -p $fs$(dirname ${j#.})
1549 cp -a $j $fs$(dirname ${j#.})
1550 done
1551 done
1552 cd - >/dev/null
1553 status
1557 # Remove from current $fs files that are already packed (for receipts v2).
1558 # Note: the order in $SPLIT is very important.
1559 # Note 2: working in the current set.
1561 remove_already_packed() {
1562 local i j
1563 # $pkg is the name of the main package; $PACKAGE is the name of the current one
1564 # $pkg may (or may not) be included in the $SPLIT
1565 neighbors=$(
1566 echo $pkg $SPLIT" " \
1567 | awk -F$'\t' -vpkg="$PACKAGE" '
1568 BEGIN { RS = " "; FS = ":"; }
1569 { set[$1] = $2; }
1570 END {
1571 current_set = set[pkg];
1572 for (i in set)
1573 { if (i != pkg && set[i] == current_set) print i; }
1575 ')
1576 IFS=$'\n'
1577 for neighbor in $neighbors; do
1578 i="$taz/$neighbor-$VERSION$EXTRAVERSION/files.list"
1579 [ -e "$i" ] || continue
1580 while read j; do
1581 [ -f $fs$j -o -h $fs$j ] || continue
1582 rm $fs$j
1583 rmdir --parents --ignore-fail-on-non-empty $fs$(dirname $j)
1584 done < $i
1585 done
1586 unset IFS
1590 # Function to use in genpkg_rules() to copy hicolor icons in specified sizes
1591 # (default: 16 and 48) from $install to $fs
1593 cook_copy_icons() {
1594 local sizes=$@ i j ifs="$IFS"
1595 unset IFS
1596 action 'Copying hicolor icons...'
1597 [ -d "$fs/usr/share/icons/hicolor" ] && rm -rf "$fs/usr/share/icons/hicolor"
1598 mkdir -p $fs/usr/share/icons/hicolor
1599 for i in ${sizes:-16 48}; do
1600 j="${i}x$i"; [ "$i" == 'scalable' ] && j="$i"
1601 [ ! -e "$install/usr/share/icons/hicolor/$j" ] ||
1602 scopy $install/usr/share/icons/hicolor/$j \
1603 $fs/usr/share/icons/hicolor
1604 done
1605 status
1606 IFS="$ifs"
1610 # Common function to copy files, folders and patterns
1612 copy() {
1613 action 'Copying folders and files...'
1614 local i j k filelist=$(mktemp) folderlist=$(mktemp)
1616 IFS=$'\n'
1617 cd $install
1618 find ! -type d | sed 's|\.||' > $filelist
1619 find -type d | sed 's|\.||' > $folderlist
1621 for i in $@; do
1622 case $i in
1623 @std)
1624 # Copy "standard" files (all but "developer files", man pages, documentation, translations)
1625 sed '/\.h$/d; /\.hxx$/d; /\.a$/d; /\.la$/d; /\.pc$/d; /\.pri$/d; /bin\/.*-config$/d;
1626 /\.m4$/d; /\.gir$/d; /\.typelib$/d; /\.vapi$/d; /\.deps$/d; /\.cmake$/d;
1627 /\/Makefile.*/d; /\.inc$/d; /\/include\//d;
1628 /\/share\/man\//d; /\/share\/doc\//d; /\/share\/gtk-doc\//d; /\/share\/info\//d;
1629 /\/share\/devhelp\//d; /\/share\/locale\//d;
1630 /\/share\/bash-completion\//d; /\/etc\/bash_completion\.d\//d; /\/lib\/systemd\//d;
1631 /\/fonts\.scale$/d; /\/fonts\.dir$/d;
1632 /\/share\/appdata\//d; /\/share\/help\//d; /\/share\/metainfo\//d; /\/share\/mimelnk\//d;
1633 /\/share\/icons\/hicolor\/[12356][1245][268]*x[12356][1245][268]*\//d; # 22, 24, 32, 64, 128, 256, 512
1634 /\.so\.dbg$/d;
1635 ' $filelist
1636 ;;
1637 @dev)
1638 # Copy "developer files"
1639 sed -n '/\.h$/p; /\.hxx$/p; /\.a$/p; /\.pc$/p; /\.pri$/p; /bin\/.*-config$/p;
1640 /\.m4$/p; /\.gir$/p; /\.typelib$/p; /\.vapi$/p; /\.deps$/p; /\.cmake$/p;
1641 /\/Makefile.*/p; /\.inc$/p; /\/include\//p;
1642 /\.so\.dbg$/p;
1643 ' $filelist
1644 ;;
1645 @ruby)
1646 # Copy mandatory Ruby files
1647 gem_base="\/usr\/lib\/ruby\/gems\/.*\/${PACKAGE#*-}-$VERSION"
1648 sed -n '/\/extensions\/.*\.so$/p; /'$gem_base'\/lib\//p; /\.gemspec$/p;
1649 /\/usr\/bin\//p; /\/gems\/.*\/bin\//p;
1650 ' $filelist | sed '/\/gems\/.*\/lib\/.*\.so$/d; /\/gems\/.*\/lib\/.*\.h$/d;
1651 /\/gems\/.*\/gems\/.*\.gemspec$/d;'
1652 ;;
1653 @ruby-dev)
1654 sed -n '/\/ext\/.*\.h$/p; /\/ext\/.*\.pc$/p; /\/gem.build_complete$/p;
1655 /\/gems\/.*\/lib\/.*\.h$/p;
1656 ' $filelist
1657 ;;
1658 @rm)
1659 # Quick alias
1660 remove_already_packed
1661 ;;
1662 @ico)
1663 # Quick alias
1664 cook_copy_icons >/dev/null
1665 ;;
1666 */)
1667 # Copy specified folders.
1668 i="${i%/}"
1669 find -type d -path "*/${i#/}" | sed 's|^.||'
1670 ;;
1671 *)
1672 # Copy specified files.
1673 find ! -type d -path "*/${i#/}" | sed 's|^.||'
1674 ;;
1675 esac \
1676 | sort -u \
1677 | while read j; do
1678 mkdir -p $fs$(dirname "$j")
1679 if [ -d "$install$j" ]; then
1680 cp -a "$install$j" $fs$(dirname "$j")
1681 else
1682 scopy "$install$j" $fs$(dirname "$j")
1683 fi
1684 done
1685 # Copy empty directories
1686 case $i in
1687 @std)
1688 while read j; do
1689 case $j in
1690 # skip empty man & doc folders
1691 */man/*|*/doc/*) continue;;
1692 esac
1693 [ -z "$(ls -A "$install$j")" ] || continue
1694 # directory $j is empty
1695 k="$j"
1696 # make 'ladder' from directories, from root dir to $j
1697 # /a /a/b /a/b/c etc.
1698 while :; do
1699 [ -z "$k" ] && break
1700 echo "$k"
1701 k="${k%/*}"
1702 done \
1703 | tac \
1704 | while read k; do
1705 # make dir if it does not exist
1706 if [ ! -d "$fs$k" ]; then
1707 # It's like "copy the directory without its underlying content".
1708 # keep original ownership/permissions, access:
1709 keepIFS="$IFS"; unset IFS
1710 install -d $(stat -c'-o%u -g%g -m%a' "$install$k") "$fs$k"
1711 # keep last-modified date:
1712 touch -r "$install$k" "$fs$k"
1713 IFS="$keepIFS"; unset keepIFS
1714 fi
1715 done
1716 done < $folderlist
1717 ;;
1718 esac
1719 done
1720 cd - >/dev/null
1721 unset IFS
1722 rm $filelist $folderlist
1723 status
1727 # Update split.db once for receipt
1729 update_split_db() {
1730 local db="$cache/split.db"
1731 touch $db
1732 sed -i "/^$pkg\t/d" $db
1733 echo -e "$pkg\t$(all_names)" >> $db
1737 # Recreate whole split.db from scratch
1739 recreate_split_db() {
1740 # Clean
1741 local db="$cache/split.db"
1743 cd $WOK
1744 for pkg in *; do
1745 [ -f "$WOK/$pkg/receipt" ] || continue
1746 unset PACKAGE SPLIT
1747 . $WOK/$pkg/receipt
1748 echo -e "$PACKAGE\t$(all_names)"
1749 done > $db
1753 # Recreate whole maint.db from scratch
1755 recreate_maint_db() {
1756 # Clean
1757 local db="$cache/maint.db"
1759 cd $WOK
1760 for pkg in *; do
1761 [ -f "$WOK/$pkg/receipt" ] || continue
1762 unset PACKAGE MAINTAINER
1763 . $WOK/$pkg/receipt
1764 MAINTAINER=$(echo $MAINTAINER | sed 's|.*<||; s|>.*||')
1765 echo -e "$MAINTAINER\t$PACKAGE"
1766 done | sort > $db
1770 # Put the status to the activity log
1772 put_status() {
1773 # $1: package, $2: status, one of 'Done', 'Failed'
1774 sed -i "s|>$1</a>$|& [ $2 ]|" $activity
1775 if [ "$2" == 'Done' ]; then
1776 # overstrike all previous 'Failed' to indicate package is OK now
1777 sed -i "/>$1<\/a>/ s|\[ Failed \]|[ -Failed ]|" $activity
1778 fi
1785 # Commands
1788 # cook <package> --deps
1789 [ -n "$deps" ] && {
1790 @@PREFIX@@/libexec/cookutils/deps $1
1791 exit 0
1794 # cook <package> --clean
1795 # cook <package> -c
1796 [ -n "$clean" -o "$2" == '-c' ] && {
1797 action 'Cleaning "%s"' "$1"
1798 cd $WOK/$1; rm -rf install taz source
1799 status; newline
1800 touch $activity # update $activity -> something changed -> update webstat
1801 exit 0
1804 # cook <package> --getsrc
1805 # cook <package> -gs
1806 [ -n "$getsrc" -o "$2" == '-gs' ] && {
1807 title 'Getting source for "%s"' "$1"
1808 receipt="$WOK/$pkg/receipt"
1809 check_pkg_in_wok
1810 unset_receipt
1811 . $receipt
1812 get_source
1813 _ 'Tarball: %s' "$SRC/$TARBALL"; newline
1814 exit 0
1817 # cook <package> --block
1818 # cook <package> -b
1819 [ -n "$block" -o "$2" == '-b' ] && {
1820 action 'Blocking package "%s"' "$1"
1821 [ $(grep "^$1$" $blocked) ] || echo "$1" >> $blocked
1822 status; newline
1823 touch $activity
1824 exit 0
1827 # cook <package> --unblock
1828 # cook <package> -ub
1829 [ -n "$unblock" -o "$2" == '-ub' ] && {
1830 action 'Unblocking package "%s"' "$1"
1831 sed -i "/^$1$/d" $blocked
1832 status; newline
1833 touch $activity
1834 exit 0
1840 case "$1" in
1841 usage|help|-u|-h)
1842 usage ;;
1844 list-wok)
1845 title 'List of %s packages in "%s"' "$ARCH" "$WOK"
1846 cd $WOK
1847 if [ "$ARCH" != 'i486' ]; then
1848 count=0
1849 for pkg in $(fgrep 'HOST_ARCH=' */receipt | egrep "$ARCH|any" | cut -d: -f1)
1850 do
1851 unset HOST_ARCH
1852 . ./$pkg
1853 count=$(($count + 1))
1854 colorize 34 "$PACKAGE"
1855 done
1856 else
1857 count=$(ls | wc -l)
1858 ls -1
1859 fi
1860 footer "$(_p '%s package' '%s packages' "$count" "$(colorize 32 "$count")")"
1861 ;;
1863 activity)
1864 cat $activity ;;
1866 search)
1867 # Just a simple search function, we don't need more actually.
1868 query="$2"
1869 title 'Search results for "%s"' "$query"
1870 cd $WOK; ls -1 | grep "$query"
1871 footer ;;
1873 setup)
1874 # Setup a build environment
1875 check_root
1876 _ 'Cook: setup environment' | log
1877 title 'Setting up your environment'
1878 [ -d $SLITAZ ] || mkdir -p $SLITAZ
1879 cd $SLITAZ
1880 init_db_files
1881 _ 'Checking for packages to install...'
1882 # Use setup pkgs from cross.conf or cook.conf. When cross compiling
1883 # ARCH-setup or 'cross check' should be used before: cook setup
1884 case "$ARCH" in
1885 arm*|x86_64)
1886 [ -x '/usr/bin/cross' ] || die 'ERROR: %s is not installed' 'cross'
1887 _ 'Using config file: %s' '/etc/slitaz/cross.conf'
1888 . /etc/slitaz/cross.conf ;;
1889 esac
1890 for pkg in $SETUP_PKGS; do
1891 if [ -n "$forced" ]; then
1892 tazpkg -gi $pkg --forced
1893 else
1894 [ ! -d "$INSTALLED/$pkg" ] && tazpkg get-install $pkg
1895 fi
1896 done
1898 # Handle --options
1899 case "$2" in
1900 --wok) hg clone $WOK_URL wok || exit 1 ;;
1901 --stable) hg clone $WOK_URL-stable wok || exit 1 ;;
1902 --undigest) hg clone $WOK_URL-undigest wok || exit 1 ;;
1903 --tiny) hg clone $WOK_URL-tiny wok || exit 1 ;;
1904 esac
1906 # SliTaz group and permissions
1907 if ! grep -q ^slitaz /etc/group; then
1908 _ 'Adding group "%s"' 'slitaz'
1909 addgroup slitaz
1910 fi
1911 _ 'Setting permissions for group "%s"...' 'slitaz'
1912 find $SLITAZ -maxdepth 2 -exec chown root.slitaz {} \;
1913 find $SLITAZ -maxdepth 2 -exec chmod g+w {} \;
1914 footer "$(_ 'All done, ready to cook packages :-)')" ;;
1916 *-setup)
1917 # Setup for cross compiling.
1918 arch="${1%-setup}"
1919 check_root
1920 . /etc/slitaz/cook.conf
1921 for pkg in $CROSS_SETUP; do
1922 if [ -n "$forced" ]; then
1923 tazpkg -gi $pkg --forced
1924 else
1925 [ ! -d "$INSTALLED/$pkg" ] && tazpkg -gi $pkg
1926 fi
1927 done
1929 _ 'Cook: setup %s cross environment' "$arch" | log
1930 title 'Setting up your %s cross environment' "$arch"
1931 init_db_files
1932 sed -i \
1933 -e "s|ARCH=.*|ARCH=\"$arch\"|" \
1934 -e "s|CROSS_TREE=.*|CROSS_TREE=\"/cross/$arch\"|" \
1935 -e 's|BUILD_SYSTEM=.*|BUILD_SYSTEM=i486-slitaz-linux|' \
1936 /etc/slitaz/cook.conf
1937 case "$arch" in
1938 arm)
1939 flags='-O2 -march=armv6'
1940 host="$ARCH-slitaz-linux-gnueabi" ;;
1941 armv6hf)
1942 flags='-O2 -march=armv6j -mfpu=vfp -mfloat-abi=hard'
1943 host="$ARCH-slitaz-linux-gnueabi" ;;
1944 armv7)
1945 flags='-Os -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -pipe'
1946 host="$ARCH-slitaz-linux-gnueabi" ;;
1947 x86_64)
1948 flags='-O2 -mtune=generic -pipe'
1949 host="$ARCH-slitaz-linux" ;;
1950 esac
1951 sed -i \
1952 -e "s|CFLAGS=.*|CFLAGS=\"$flags\"|" \
1953 -e "s|HOST_SYSTEM=.*|HOST_SYSTEM=$host|" /etc/slitaz/cook.conf
1954 . /etc/slitaz/cook.conf
1955 sysroot="$CROSS_TREE/sysroot"
1956 tools="/cross/$arch/tools"
1957 root="$sysroot"
1958 # L10n: keep the same width of translations to get a consistent view
1959 _ 'Target arch : %s' "$ARCH"
1960 _ 'Configure args : %s' "$CONFIGURE_ARGS"
1961 _ 'Build flags : %s' "$flags"
1962 _ 'Arch sysroot : %s' "$sysroot"
1963 _ 'Tools prefix : %s' "$tools/bin"
1964 # Tell the packages manager where to find packages.
1965 _ 'Packages DB : %s' "$root$DB"
1966 mkdir -p $root$INSTALLED
1967 cd $root$DB; rm -f *.bak
1968 for list in packages.list packages.desc packages.equiv packages.md5; do
1969 rm -f $list
1970 ln -s $SLITAZ/packages/$list $list
1971 done
1972 # We must have the cross compiled glibc-base installed or default
1973 # i486 package will be used as dep by tazpkg and then break the
1974 # cross environment
1975 if [ ! -f "$root$INSTALLED/glibc-base/receipt" ]; then
1976 colorize 36 $(_ 'WARNING: %s is not installed in sysroot' '(e)glibc-base')
1977 fi
1978 # Show GCC version or warn if not yet compiled.
1979 if [ -x "$tools/bin/$HOST_SYSTEM-gcc" ]; then
1980 _ 'Cross compiler : %s' "$HOST_SYSTEM-gcc"
1981 else
1982 colorize 36 $(_ 'C compiler "%s" is missing' "$HOST_SYSTEM-gcc")
1983 _ 'Run "%s" to cook a toolchain' 'cross compile'
1984 fi
1985 footer ;;
1987 test)
1988 # Test a cook environment.
1989 _ 'Cook test: testing the cook environment' | log
1990 [ ! -d "$WOK" ] && exit 1
1991 [ ! -d "$WOK/cooktest" ] && cp -r $DATA/cooktest $WOK
1992 cook cooktest ;;
1994 new)
1995 # Create the package folder and an empty receipt.
1996 pkg="$2"
1997 [ -z "$pkg" ] && usage
1998 newline
1999 [ -d "$WOK/$pkg" ] && die 'Package "%s" already exists.' "$pkg"
2001 action 'Creating folder "%s"' "$WOK/$pkg"
2002 mkdir $WOK/$pkg; cd $WOK/$pkg; status
2004 action 'Preparing the package receipt...'
2005 cp $DATA/receipt .
2006 sed -i "s|^PACKAGE=.*|PACKAGE=\"$pkg\"|" receipt
2007 status; newline
2009 # Interactive mode, asking and seding.
2010 case "$3" in
2011 --interactive|-x)
2012 _ 'Entering interactive mode...'
2013 separator
2014 _ 'Package : %s' "$pkg"
2016 _n 'Version : ' ; read answer
2017 sed -i "s|^VERSION=.*|VERSION=\"$answer\"|" receipt
2019 _n 'Category : ' ; read answer
2020 sed -i "s|^CATEGORY=.*|CATEGORY=\"$answer\"|" receipt
2022 # L10n: Short description
2023 _n 'Short desc : ' ; read answer
2024 sed -i "s|^SHORT_DESC=.*|SHORT_DESC=\"$answer\"|" receipt
2026 _n 'Maintainer : ' ; read answer
2027 sed -i "s|^MAINTAINER=.*|MAINTAINER=\"$answer\"|" receipt
2029 _n 'License : ' ; read answer
2030 sed -i "s|^LICENSE=.*|LICENSE=\"$answer\"|" receipt
2032 _n 'Web site : ' ; read answer
2033 sed -i "s|^WEB_SITE=.*|WEB_SITE=\"$answer\"|" receipt
2034 newline
2036 # Wget URL.
2037 _ 'Wget URL to download source tarball.'
2038 _n 'Example : ' ; echo '$GNU_MIRROR/$PACKAGE/$TARBALL'
2039 _n 'Wget url : ' ; read answer
2040 sed -i "s|^WGET_URL=.*|WGET_URL=\"$answer\"|" receipt
2042 # Ask for a stuff dir.
2043 confirm "$(_n 'Do you need a stuff directory? (y/N)')"
2044 if [ "$?" -eq 0 ]; then
2045 action 'Creating the stuff directory...'
2046 mkdir $WOK/$pkg/stuff; status
2047 fi
2049 # Ask for a description file.
2050 confirm "$(_n 'Are you going to write a description? (y/N)')"
2051 if [ "$?" -eq 0 ]; then
2052 action 'Creating the "%s" file...' 'description.txt'
2053 touch $WOK/$pkg/description.txt; status
2054 fi
2056 footer "$(_ 'Receipt is ready to use.')" ;;
2057 esac ;;
2059 list)
2060 # Cook a list of packages (better use the Cooker since it will order
2061 # packages before executing cook).
2062 check_root
2063 [ -z "$2" ] && die 'No list in argument.'
2064 [ -f "$2" ] || die 'List "%s" not found.' "$2"
2066 _ 'Starting cooking the list "%s"' "$2" | log
2068 while read pkg; do
2069 cook $pkg || broken
2070 done < $2
2071 ;;
2073 clean-wok)
2074 check_root
2075 newline; action 'Cleaning all packages files...'
2076 rm -rf $WOK/*/taz $WOK/*/install $WOK/*/source
2077 status; newline ;;
2079 clean-src)
2080 check_root
2081 newline; action 'Cleaning all packages sources...'
2082 rm -rf $WOK/*/source
2083 status; newline ;;
2085 uncook)
2086 cd $WOK
2087 count=0
2088 title 'Checking for uncooked packages'
2090 for i in *; do
2091 unset HOST_ARCH EXTRAVERSION
2092 [ ! -e $i/receipt ] && continue
2093 . ./$i/receipt
2094 # Source cooked pkg receipt to get EXTRAVERSION
2095 if [ -d "$WOK/$i/taz" ]; then
2096 cd $WOK/$i/taz/$(ls $WOK/$i/taz/ | head -n1)
2097 . ./receipt; cd $WOK
2098 fi
2099 case "$ARCH" in
2100 i486)
2101 debug "$(_ 'Package "%s"' "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg")"
2102 if [ ! -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg" ]; then
2103 count=$(($count + 1))
2104 colorize 34 "$i"
2105 fi ;;
2106 arm*)
2107 # Check only packages included in arch
2108 if echo "$HOST_ARCH" | egrep -q "$ARCH|any"; then
2109 # *.tazpkg
2110 if [ ! -f "$PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg" ]; then
2111 count=$(($count + 1))
2112 colorize 34 "$i"
2113 fi
2114 fi ;;
2115 esac
2116 done
2118 if [ "$count" -gt 0 ]; then
2119 footer "$(_p '%s uncooked package' '%s uncooked packages' "$count" "$(colorize 31 "$count")")"
2120 else
2121 _ 'All packages are cooked :-)'
2122 newline
2123 fi
2124 ;;
2126 pkgdb)
2127 # Create suitable packages list for TazPkg and only for built packages
2128 # as well as flavors files for TazLiTo. We don't need logs since we do it
2129 # manually to ensure everything is fine before syncing the mirror.
2130 recreate_split_db
2131 recreate_maint_db
2132 @@PREFIX@@/libexec/cookutils/pkgdb "$2"
2133 ;;
2135 splitdb)
2136 # File split.db is useful for searching for split packages.
2137 recreate_split_db
2138 ;;
2140 maintdb)
2141 # File maint.db is useful for searching maintainer's packages.
2142 recreate_maint_db
2143 ;;
2145 *)
2146 # Just cook and generate a package.
2147 check_root
2148 time=$(date +%s)
2149 pkg="$1"
2150 [ -z "$pkg" ] && usage
2152 # Search last successful cook time in all logs from newer to older
2153 for i in '' $(seq 0 9 | sed 's|^|.|'); do
2154 [ -f "$LOGS/$pkg.log$i" ] || break
2155 lastcooktime=$(sed '/^Cook time/!d; s|.*: *\([0-9]*\)s.*|\1|' \
2156 $LOGS/$pkg.log$i 2>/dev/null | sed '$!d')
2157 [ -n "$lastcooktime" ] && break
2158 done
2160 receipt="$WOK/$pkg/receipt"
2161 check_pkg_in_wok
2162 newline
2164 unset inst
2165 unset_receipt
2166 . $receipt
2168 # Handle cross compilation.
2169 case "$ARCH" in
2170 arm*)
2171 if [ -z "$HOST_ARCH" ]; then
2172 _ 'cook: HOST_ARCH is not set in "%s" receipt' "$pkg"
2173 error="$(_ 'package "%s" is not included in %s' "$pkg" "$ARCH")"
2174 _ 'cook: %s' "$error"
2175 [ -n "$CROSS_BUGS" ] && _ 'bugs: %s' "$CROSS_BUGS"
2176 _ 'Cook skip: %s' "$error" | log
2177 newline
2178 broken; exit 1
2179 fi ;;
2180 esac
2182 # Some packages are not included in some arch or fail to cross compile.
2183 : ${HOST_ARCH=$ARCH}
2184 debug "$(_ 'Host arch %s' "$HOST_ARCH")"
2185 # Handle arm{v6hf,v7,..}
2186 if ! $(echo "$HOST_ARCH" | egrep -q "${ARCH%v[0-9]*}|any"); then
2187 _ 'cook: %s' "HOST_ARCH=$HOST_ARCH"
2188 error="$(_ "package \"%s\" doesn't cook or is not included in %s" "$pkg" "$ARCH")"
2189 _ 'cook: %s' "error"
2190 [ -n "$CROSS_BUGS" ] && _ 'bugs: %s' "$CROSS_BUGS"
2191 _ 'Cook skip: %s' "$error" | log
2192 sed -i "/^${pkg}$/d" $broken
2193 newline
2194 exit 0
2195 fi
2197 # Skip blocked, 3 lines also for the Cooker.
2198 grep -q "^$pkg$" $blocked && [ "$2" != '--unblock' ] &&
2199 die 'Package "%s" is blocked' "$pkg"
2201 try_aufs_chroot "$@"
2203 # Log and source receipt.
2204 _ 'Cook started for: %s' "<a href='cooker.cgi?pkg=${pkg//+/%2B}'>$pkg</a>" | log
2205 echo "cook:$pkg" > $command
2207 [ -n "$lastcooktime" ] && echo "cook:$pkg $lastcooktime $(date +%s)" >> $cooktime
2209 while read cmd duration start; do
2210 [ $(($start + $duration)) -lt $(date +%s) ] &&
2211 echo "sed -i '/^$cmd $duration/d' $cooktime"
2212 done < $cooktime | sh
2214 # Display and log info if cook process stopped.
2215 # FIXME: gettext not working (in single quotes) here!
2216 trap '_ "\n\nCook stopped: control-C\n\n" | \
2217 tee -a $LOGS/$pkg.log' INT
2219 update_split_db
2221 # Handle --options
2222 case "$2" in
2223 --install|-i)
2224 inst='yes' ;;
2226 --pack)
2227 [ -d "$WOK/$pkg/install" ] || die 'Need to build "%s"' "$pkg"
2228 [ ! -d "$WOK/$pkg/taz" ] || rm -rf "$WOK/$pkg/taz"
2229 [ ! -f "$LOGS/$pkg-pack.log" ] || rm -f $LOGS/$pkg-pack.log
2230 sed -i '$ s|$| (packing)|' $activity
2231 packall 2>&1 | tee -a $LOGS/$pkg-pack.log
2232 clean_log "$pkg-pack"
2233 time=$(($(date +%s) - $time))
2234 summary | sed 's|^Cook |Pack |' | tee -a $LOGS/$pkg-pack.log
2235 put_status $pkg Done
2236 rm -f $command
2237 exit 0 ;;
2239 --trials|-t)
2240 trials='yes' ;;
2241 esac
2243 # Rotate log
2244 for i in $(seq 9 -1 1); do
2245 j=$(($i - 1))
2246 [ -e $LOGS/$pkg.log.$j ] && mv -f $LOGS/$pkg.log.$j $LOGS/$pkg.log.$i
2247 done
2248 [ -e $LOGS/$pkg.log ] && mv $LOGS/$pkg.log $LOGS/$pkg.log.0
2250 # Check if wanted is built now so we have separate log files.
2251 for wanted in $WANTED ; do
2252 if grep -q "^$wanted$" $blocked; then
2253 broken
2254 rm -f $command
2255 die 'WANTED package "%s" is blocked' "$wanted"
2256 fi
2257 if grep -q "^$wanted$" $broken; then
2258 broken
2259 rm -f $command
2260 die 'WANTED package "%s" is broken' "$wanted"
2261 fi
2262 if [ ! -d "$WOK/$wanted/install" ]; then
2263 cook "$wanted" || { broken; exit 1; }
2264 fi
2265 done
2267 # Cook and pack or exit on error and log everything.
2268 ((((cookit $@ 2>&1; echo $? >&3) | loglimit 50 > $LOGS/$pkg.log) 3>&1) | (read rq; exit $rq))
2269 rq=$? # the return code of `cookit $@` above command
2271 # Remove build dependencies both when `cookit` done or fail
2272 remove_deps | tee -a $LOGS/$pkg.log
2273 timestamp job27 # removing bdeps
2274 cookit_quality
2275 timestamp job28 # checking quality
2277 # Log and stop if `cookit` fails
2278 if [ $rq -eq 1 ]; then
2279 debug_info | tee -a $LOGS/$pkg.log
2280 put_status $pkg Failed
2281 rm -f $command
2282 broken; exit 1
2283 fi
2285 # Proceed only if `cookit` return code is zero-OK
2286 # If instant-pack if specified, then packages already packed in the cookit()
2287 [ "${COOKOPTS/instant-pack/}" == "$COOKOPTS" ] &&
2288 packall 2>&1 | loglimit 5 >> $LOGS/$pkg.log
2289 timestamp job29 # packing
2291 clean_log
2293 # Exit if any error in packing.
2294 if [ "${COOKOPTS/skip-log-errors/}" == "$COOKOPTS" ] &&
2295 grep -Ev "(/root/.cvspass|conftest|df: /|rm: can't remove)" $LOGS/$pkg.log | \
2296 grep -Eq "(^ERROR|: No such file or directory|not remade because of errors|ake: \*\*\* .* Error)"; then
2297 debug_info | tee -a $LOGS/$pkg.log
2298 put_status $pkg Failed
2299 rm -f $command
2300 broken; exit 1
2301 fi
2303 # Create an XML feed
2304 gen_rss
2306 # Time and summary
2307 time=$(($(date +%s) - $time))
2308 summary | tee -a $LOGS/$pkg.log
2309 newline
2311 # We may want to install/update (outside aufs jail!).
2312 [ -s /aufs-umount.sh ] || install_package
2314 put_status $pkg Done
2316 # Finally we DON'T WANT to build the *-dev or packages with WANTED="$pkg"
2317 # If you want automation, use the Cooker Build Bot.
2318 rm -f $command
2319 timestamp job30 # misc. final operations
2320 store_timestats
2322 sed -n '/^Build dependencies to remove:/,/^$/p' $LOGS/$pkg.log \
2323 | sed '/^Build/d; s|Removing: ||' \
2324 | tr ' ' '\n' \
2325 | sed '/^$/d' \
2326 > $WOK/$pkg/.bdeps
2328 ;;
2329 esac
2331 exit 0