cookutils view modules/pack @ rev 1135

Small improvements and fixes:
1. cook: summary(): skip unpackaged packages (when use CATEGORY="nopack");
2. modules/compressor:
a) move strip_package from "fs" to "install" stage - from this moment files in $install and $fs are identical (of course, if you use genpkg_rules() only for copying) - we may clean taz/*/fs/ in the future;
b) remove "empty" *.mo;
c) skip silly error messages when $install or $fs absent;
3. modules/pack:
a) move symlinks *.so to the @dev;
b) small improvements;
4. doc/cookopts.txt: small update;
author Aleksej Bobylev <al.bobylev@gmail.com>
date Tue Jan 29 14:12:35 2019 +0200 (2019-01-29)
parents 0385051c3996
children 4f2ea8b43594
line source
1 #!/bin/sh
2 #
3 # pack - module of the SliTaz Cook
4 # Copyright (C) SliTaz GNU/Linux - GNU GPL v3
5 #
7 . /usr/lib/slitaz/libcook.sh
10 ######################################################
11 # BEGIN: Functions may be used in the genpkg_rules() #
12 ######################################################
15 # A bit smarter function than the classic `cp` command
17 scopy() {
18 if [ "$(stat -c %h -- "$1")" -eq 1 ]; then
19 cp -a "$1" "$2" # copy generic files
20 else
21 cp -al "$1" "$2" # copy hardlinks
22 fi
23 }
26 # Copy specified files from $install to $fs
28 cook_copy_files() {
29 action 'Copying files...'
30 cd $install
31 local i j
32 IFS=$'\n'
33 for i in $@; do
34 for j in $(find . -name $i ! -type d); do
35 mkdir -p $fs$(dirname ${j#.})
36 scopy $j $fs$(dirname ${j#.})
37 done
38 done
39 cd - >/dev/null
40 status
41 }
44 # Copy specified folders from $install to $fs
46 cook_copy_folders() {
47 action 'Copying folders...'
48 cd $install
49 local i j
50 IFS=$'\n'
51 for i in $@; do
52 for j in $(find . -name $i -type d); do
53 mkdir -p $fs$(dirname ${j#.})
54 cp -a $j $fs$(dirname ${j#.})
55 done
56 done
57 cd - >/dev/null
58 status
59 }
62 # Remove from current $fs files that are already packed (for receipts v2).
63 # Note: the order in $SPLIT is very important.
64 # Note 2: working in the current set.
66 remove_already_packed() {
67 local i j
68 # $basepkg is the name of the main package;
69 # $thispkg is the name of the current one.
70 # $basepkg may (or may not) be included in the $SPLIT
71 neighbors=$(
72 echo $basepkg $SPLIT" " \
73 | awk -F$'\t' -vpkg="$thispkg" '
74 BEGIN { RS = " "; FS = ":"; }
75 { set[$1] = $2; }
76 END {
77 current_set = set[pkg];
78 for (i in set)
79 { if (i != pkg && set[i] == current_set) print i; }
80 }
81 ')
82 IFS=$'\n'
83 for neighbor in $neighbors; do
84 i="$taz/$neighbor-$VERSION$EXTRAVERSION/files.list"
85 [ -e "$i" ] || continue
86 while read j; do
87 [ -f $fs$j -o -h $fs$j ] || continue
88 rm $fs$j
89 rmdir --parents --ignore-fail-on-non-empty $fs$(dirname $j)
90 done < $i
91 done
92 unset IFS
93 }
96 # Copy hicolor icons in specified sizes (default: 16 and 48) from $install to $fs
98 cook_copy_icons() {
99 local sizes=$@ i j ifs="$IFS"
100 unset IFS
101 action 'Copying hicolor icons...'
102 [ -d "$fs/usr/share/icons/hicolor" ] && rm -rf "$fs/usr/share/icons/hicolor"
103 mkdir -p $fs/usr/share/icons/hicolor
104 for i in ${sizes:-16 48}; do
105 j="${i}x$i"; [ "$i" == 'scalable' ] && j="$i"
106 [ ! -e "$install/usr/share/icons/hicolor/$j" ] ||
107 scopy $install/usr/share/icons/hicolor/$j \
108 $fs/usr/share/icons/hicolor
109 done
110 status
111 IFS="$ifs"
112 }
115 # Common function to copy files, folders and patterns
117 copy() {
118 action 'Copying folders and files...'
119 if [ ! -d "$install" ]; then
120 false; status
121 die 'ERROR: copy from the empty $install'
122 fi
124 local i j k
125 local tmp=$(mktemp -d) filelist=$tmp/f folderlist=$tmp/d solist=$tmp/s
126 local copylist=$tmp/c
128 IFS=$'\n'
129 cd $install
130 # filelist: all files and symlinks excluding *.so symlinks
131 find \( -type f -o \( -type l ! -name '*.so' \) \) | sed 's|\.||' >$filelist
132 # solist: *.so symlinks only
133 find -type l -name '*.so' | sed 's|\.||' >$solist
134 # folderlist: folders
135 find -type d | sed 's|\.||' >$folderlist
137 for i in $@; do
138 case $i in
139 @std)
140 # Copy "standard" files (all but "developer files", man pages, documentation, translations)
141 sed '/\.h$/d; /\.hxx$/d; /\.a$/d; /\.la$/d; /\.pc$/d; /\.pri$/d; /bin\/.*-config$/d;
142 /\.m4$/d; /\.gir$/d; /\.typelib$/d; /\.vapi$/d; /\.deps$/d; /\.cmake$/d;
143 /\/Makefile.*/d; /\.inc$/d; /\/include\//d;
144 /\/share\/man\//d; /\/share\/doc\//d; /\/share\/gtk-doc\//d; /\/share\/info\//d;
145 /\/share\/devhelp\//d; /\/share\/locale\//d;
146 /\/share\/bash-completion\//d; /\/etc\/bash_completion\.d\//d; /\/lib\/systemd\//d;
147 /\/fonts\.scale$/d; /\/fonts\.dir$/d;
148 /\/share\/appdata\//d; /\/share\/help\//d; /\/share\/metainfo\//d; /\/share\/mimelnk\//d;
149 /\/share\/application-registry\//d; /\/share\/mime-info\//d;
150 /\/share\/gnome\/help\//d; /\/share\/omf\//d;
151 /\/share\/icons\/hicolor\/[12356][1245][268]*x[12356][1245][268]*\//d; # 22, 24, 32, 64, 128, 256, 512
152 /\.so\.dbg$/d;
153 ' $filelist
154 ;;
155 @dev)
156 # Copy "developer files"
157 sed -n '
158 /\/share\/doc\//d;
159 /\.h$/p; /\.hxx$/p; /\.a$/p; /\.pc$/p; /\.pri$/p; /bin\/.*-config$/p;
160 /\.m4$/p; /\.gir$/p; /\.typelib$/p; /\.vapi$/p; /\.deps$/p; /\.cmake$/p;
161 /\/Makefile.*/p; /\.inc$/p; /\/include\//p;
162 /\.so\.dbg$/p;
163 ' $filelist
164 cat $solist # append copy list by *.so symlinks
165 ;;
166 @ruby)
167 # Copy mandatory Ruby files
168 gem_base="\/usr\/lib\/ruby\/gems\/.*\/${PACKAGE#*-}-$VERSION"
169 sed -n '/\/extensions\/.*\.so$/p; /'$gem_base'\/lib\//p; /\.gemspec$/p;
170 /\/usr\/bin\//p; /\/gems\/.*\/bin\//p;
171 ' $filelist | sed '/\/gems\/.*\/lib\/.*\.so$/d; /\/gems\/.*\/lib\/.*\.h$/d;
172 /\/gems\/.*\/gems\/.*\.gemspec$/d;'
173 ;;
174 @ruby-dev)
175 sed -n '/\/ext\/.*\.h$/p; /\/ext\/.*\.pc$/p; /\/gem.build_complete$/p;
176 /\/gems\/.*\/lib\/.*\.h$/p;
177 ' $filelist
178 ;;
179 @rm)
180 # Quick alias
181 remove_already_packed
182 ;;
183 @ico)
184 # Quick alias
185 cook_copy_icons >/dev/null
186 ;;
187 */)
188 # Copy specified folders.
189 i="${i%/}"
190 find -type d -path "*/${i#/}" | sed 's|^.||'
191 ;;
192 *)
193 # Copy specified files.
194 find ! -type d -path "*/${i#/}" | sed 's|^.||'
195 ;;
196 esac \
197 | sort -u \
198 | while read j; do
199 mkdir -p $fs$(dirname "$j")
200 if [ -d "$install$j" ]; then
201 cp -a "$install$j" $fs$(dirname "$j")
202 else
203 scopy "$install$j" $fs$(dirname "$j")
204 fi
205 done
206 # Copy empty directories
207 case $i in
208 @std)
209 while read j; do
210 case $j in
211 # skip empty man, doc and locale folders
212 */man/*|*/doc/*|*/share/locale/*) continue;;
213 esac
214 [ -z "$(ls -A "$install$j")" ] || continue
215 # directory $j is empty
216 k="$j"
217 # make 'ladder' from directories, from root dir to $j
218 # /a /a/b /a/b/c etc.
219 while :; do
220 [ -z "$k" ] && break
221 echo "$k"
222 k="${k%/*}"
223 done \
224 | tac \
225 | while read k; do
226 # make dir if it does not exist
227 if [ ! -d "$fs$k" ]; then
228 # It's like "copy the directory without its underlying content".
229 # keep original ownership/permissions, access:
230 keepIFS="$IFS"; unset IFS
231 install -d $(stat -c'-o%u -g%g -m%a' "$install$k") "$fs$k"
232 # keep last-modified date:
233 touch -r "$install$k" "$fs$k"
234 IFS="$keepIFS"; unset keepIFS
235 fi
236 done
237 done < $folderlist
238 ;;
239 esac
240 done
241 cd - >/dev/null
242 unset IFS
243 rm -r $tmp # clean
244 status
245 }
247 ####################################################
248 # END: Functions may be used in the genpkg_rules() #
249 ####################################################
254 # Receipt used for cooking the package is redundant to be included into package.
255 # This script will strip the original receipt to bare minimum: variables,
256 # {pre,post}_{install,remove} functions.
258 mk_pkg_receipt() {
259 orig_receipt="$1"
261 # 1. Main package.
262 # By default it has no dependencies.
263 # You can write or omit DEPENDS="" for indicating packages that have no
264 # dependencies.
265 # 2. Split package (excluding *-dev).
266 # By default every split package depends on the main package.
267 # Unfortunately, in the shell script (receipt is the shell script too),
268 # every undeclared variable has an empty value, so there's no difference if
269 # you wrote DEPENDS="" or omit it - result will be the same empty value.
270 # If you want to define that the split package has no dependencies - you need
271 # to to put a single space between the quotes: DEPENDS=" ".
272 # 3. Development split package.
273 # Installing *-dev package should install all the files produced during
274 # compilation and then were separated into the different packages, so
275 # by default (if you wrote DEPENDS="" or omit it) *-dev package depends
276 # on the main package and all the split packages (excluding itself).
277 [ "$DEPENDS" == ' ' ] && DEPENDS='@EMPTY@'
279 # Receipt's signature is important, although some receipts may miss it
280 signature=$(head -n1 "$orig_receipt")
281 [ "${signature:0:1}" == '#' ] || signature='# SliTaz package receipt.'
283 save="$(mktemp)"
284 # `$(echo ...)`: normalize whitespace (space, tab, newline and their
285 # combinations and repeats)
286 cat > $save <<-EOT
287 PACKAGE="$PACKAGE"; DEPENDS="$(echo $DEPENDS)"; PROVIDE="$(echo $PROVIDE)"
288 SUGGESTED="$(echo $SUGGESTED)"; TAZPANEL_DAEMON="$TAZPANEL_DAEMON"
289 TAGS="$(echo $TAGS)"; VERSION="$VERSION"; SHORT_DESC="$SHORT_DESC"
290 WEB_SITE="$WEB_SITE"; CATEGORY="$CATEGORY"
291 EOT
292 unset_receipt
293 . "$orig_receipt"
294 MAIN_PACKAGE="$PACKAGE"
295 . $save; rm $save # restore values
297 # Manage split packages
298 SPLIT=" $SPLIT "
299 if [ "$PACKAGE" != "$MAIN_PACKAGE" -a "$SPLIT" != ' ' ] &&
300 echo "$SPLIT" | fgrep -q " $PACKAGE "; then
301 # For packages with empty $DEPENDS
302 if [ -z "$DEPENDS" ]; then
303 case $PACKAGE in
304 *-dev)
305 # main package and all the split packages but this *-dev itself
306 DEPENDS=$(echo "$MAIN_PACKAGE $SPLIT " | sed "s| $PACKAGE | |; s| *$||");;
307 *)
308 DEPENDS="$MAIN_PACKAGE";;
309 esac
310 fi
312 # Default $CAT
313 [ -z "$CAT" ] &&
314 case $PACKAGE in
315 *-dev) CAT="development|development files" ;;
316 esac
317 fi
319 # Manage two-in-one $CAT="$CATEGORY|$SHORT_DESC_ADDITION"
320 if [ -n "$CAT" ]; then
321 CATEGORY="${CAT%|*}"
322 SHORT_DESC="$SHORT_DESC (${CAT#*|})"
323 fi
325 # escape quotes for receipt
326 SHORT_DESC="${SHORT_DESC//\"/\\\"}"
328 # Mandatory variables
329 cat <<-EOF
330 $signature
332 PACKAGE="$PACKAGE"
333 VERSION="$VERSION"
334 EOF
335 [ -n "$EXTRAVERSION" ] && echo "EXTRAVERSION=\"$EXTRAVERSION\""
336 cat <<-EOF
337 CATEGORY="$CATEGORY"
338 SHORT_DESC="$SHORT_DESC"
339 MAINTAINER="$MAINTAINER"
340 LICENSE="$LICENSE"
341 WEB_SITE="$WEB_SITE"
342 EOF
344 # Optional variables
345 [ -n "$TAGS" ] && echo "TAGS=\"$TAGS\"" | tr -ds '\t' ' '
346 case "x$DEPENDS" in
347 x|x@EMPTY@) ;;
348 *) echo "DEPENDS=\"$DEPENDS\"" | tr -ds '\t' ' ';;
349 esac
350 [ -n "$PROVIDE" ] && echo "PROVIDE=\"$PROVIDE\"" | tr -ds '\t' ' '
351 [ -n "$CONFIG_FILES" ] && echo "CONFIG_FILES=\"$CONFIG_FILES\"" | tr -ds '\t' ' '
352 [ -n "$SUGGESTED" ] && echo "SUGGESTED=\"$SUGGESTED\"" | tr -ds '\t' ' '
353 [ -n "$DATABASE_FILES" ] && echo "DATABASE_FILES=\"$DATABASE_FILES\""
354 [ -n "$TAZPANEL_DAEMON" ] && echo "TAZPANEL_DAEMON=\"$TAZPANEL_DAEMON\""
356 # Extract {pre,post}_{install,remove} functions;
357 # post_install() will be copied for both main and all the split packages
358 # post_install_gtk_() will be copied as post_install() for gtk+ package only
359 #
360 # restricted name (gtk+ -> gtk_; acl-dev -> acl_dev)
361 rname=$(echo -n $PACKAGE | tr -c 'a-zA-Z0-9' '_')
362 for i in pre post; do
363 for j in install remove; do
364 sed "/^${i}_${j}()/,/^}/!d" "$orig_receipt"
365 sed "/^${i}_${j}_$rname()/,/^}/!d" "$orig_receipt" \
366 | sed "s|^${i}_${j}_$rname()|${i}_${j}()|"
367 done
368 done
369 }
372 # Copy all generic files (locale, pixmaps, .desktop) from $install to $fs.
373 # We use standard paths, so some packages need to copy these files with the
374 # receipt and genpkg_rules.
375 # This function executes inside the packaging process, before compressor call.
377 copy_generic_files() {
378 # $LOCALE is set in cook.conf
379 if [ -n "$LOCALE" -a -z "$WANTED" ]; then
380 if [ -d "$install/usr/share/locale" ]; then
381 mkdir -p "$fs/usr/share/locale"
382 for i in $LOCALE; do
383 if [ -d "$install/usr/share/locale/$i" ]; then
384 cp -r $install/usr/share/locale/$i $fs/usr/share/locale
385 fi
386 done
387 fi
388 fi
390 # Generic pixmaps copy can be disabled with COOKOPTS="!pixmaps" (or GENERIC_PIXMAPS="no")
391 if [ "${COOKOPTS/!pixmaps/}" == "$COOKOPTS" -a "$GENERIC_PIXMAPS" != 'no' ]; then
392 if [ -d "$install/usr/share/pixmaps" ]; then
393 mkdir -p "$fs/usr/share/pixmaps"
394 for i in png xpm; do
395 [ -f "$install/usr/share/pixmaps/$PACKAGE.$i" -a ! -f "$fs/usr/share/pixmaps/$PACKAGE.$i" ] &&
396 cp -r $install/usr/share/pixmaps/$PACKAGE.$i $fs/usr/share/pixmaps
397 done
398 fi
399 fi
401 # Desktop entry (.desktop).
402 # Generic desktop entry copy can be disabled with COOKOPTS="!menus" (or GENERIC_MENUS="no")
403 if [ "${COOKOPTS/!menus/}" == "$COOKOPTS" -a "$GENERIC_MENUS" != 'no' ]; then
404 if [ -d "$install/usr/share/applications" -a -z "$WANTED" ]; then
405 mkdir -p "$fs/usr/share"
406 cp -r $install/usr/share/applications $fs/usr/share
407 fi
408 fi
409 }
412 # Determine package architecture
413 # Input: $1 = $fs; output string: i486 | x86_64 | any
415 determine_pkg_arch() {
416 if [ "${COOKOPTS/force-arch/}" != "$COOKOPTS" ]; then
417 action 'Forced package architecture to' >&2
418 echo " $ARCH" >&2
419 arch="$ARCH"
420 elif [ -n "$(busybox find "$1" -type f -name '*.typelib')" ]; then
421 # GObject-introspection *.typelib binary data is architecture-dependent
422 action 'Found typelib. Forced package architecture to' >&2
423 echo " $ARCH" >&2
424 arch="$ARCH"
425 else
426 action 'Determining package architecture...' >&2
427 archs="$(
428 IFS=$'\n'
429 {
430 # examine all the executables and static libs (*.a)
431 busybox find "$1" -type f \( -perm +111 -o -name '*.a' \) \
432 | while read i; do
433 readelf -Wh "$i" 2>/dev/null \
434 | sed '/Machine:/!d; s|.* ||'
435 done
437 # examine compressed kernel modules (we use exclusively *.ko.xz)
438 tmpko=$(mktemp)
439 find "$1" -type f -name '*.ko.xz' \
440 | while read i; do
441 unxz -kc $i >$tmpko
442 readelf -Wh "$tmpko" 2>/dev/null \
443 | sed '/Machine:/!d; s|.* ||'
444 done
445 rm $tmpko
447 # examine Guile *.go files (Machine: None, so check Class)
448 find "$1" -type f -name '*.go' \
449 | while read i; do
450 readelf -Wh "$i" 2>/dev/null \
451 | sed '/Class:/!d; s|.* ||'
452 done \
453 | sed 's|ELF32|80386|; s|ELF64|X86-64|'
454 } | sort -u
455 )"
457 case $archs in
458 80386) arch='i486'; echo ' i486' >&2;;
459 X86-64) arch='x86_64'; echo ' x86_64' >&2;;
460 '') arch='any'; echo ' any' >&2;;
461 *) arch="$ARCH"; echo ' ' $archs >&2
462 echo "Warning: weird architecture found, forced to use $ARCH for now." >&2
463 ;;
464 esac
465 fi
467 touch $pkgdir/.arch
468 sed -i "/^$PACKAGE /d" $pkgdir/.arch # remove previous entry
469 echo "$PACKAGE $arch" >> $pkgdir/.arch # put new one
471 echo $arch
472 }
475 # Find the variables inside receipt
477 find_vars() {
478 # You can define variables in the root of the receipt describing
479 # the dependencies (or tags, config files, etc.) for each sub-package.
480 # Example:
481 # PACKAGE="cool"
482 # SPLIT="$PACKAGE-extra libcool $PACKAGE-dev"
483 #
484 # DEPENDS_cool or DEPENDS_std # latter is the universal name for main package deps
485 # DEPENDS_cool_extra or DEPENDS_extra # you can skip "$PACKAGE" at the start
486 # DEPENDS_libcool # name not starts with "$PACKAGE" so no "short" name
487 # DEPENDS_cool_dev or DEPENDS_dev
489 local out
490 local var=$1
491 local pkg=$(echo -n $2 | tr -c 'a-zA-Z0-9' '_')
492 local end=$(echo -n ${2#$basepkg-} | tr -c 'a-zA-Z0-9' '_')
493 if [ "$2" == "$basepkg" ]; then
494 eval out="\$${var}_$pkg" # DEPENDS_cool
495 [ -n "$out" ] || eval out="\$${var}_std" # DEPENDS_std
496 [ -n "$out" ] || eval out="\$$var" # DEPENDS
497 else
498 eval out="\$${var}_$pkg" # DEPENDS_cool_extra
499 [ -n "$out" ] || eval out="\$${var}_$end" # DEPENDS_extra
500 fi
501 echo "$out"
502 }
505 # Create the package
507 packit() {
508 basepkg="$PACKAGE"
509 thispkg="$1"
511 pkgdir="$WOK/$basepkg"
512 receipt="$pkgdir/receipt"
513 . $receipt
515 title 'Pack: %s' "$thispkg $VERSION"
518 #
519 # Set variables
520 #
522 # Determine set name for specified package from $SPLIT variable
523 local set=$(echo -n $SPLIT \
524 | awk -vpkg="$thispkg" '
525 BEGIN { RS = " "; FS = ":"; }
526 { if ($1 == pkg && $2 != "") { print "-" $2; exit; } }')
528 # Set paths
529 export stuff="$pkgdir/stuff"
530 export src="$pkgdir/source/$basepkg-$VERSION$set"
531 export install="$pkgdir/install$set"
532 export DESTDIR="$install"
533 export taz="$pkgdir/taz"
534 export pack="$taz/$thispkg-$VERSION$EXTRAVERSION"
535 export fs="$pack/fs"
537 export PACKAGE=$thispkg
540 #
541 # Execute genpkg_rules()
542 #
544 require_copy='yes'
545 [ "${COOKOPTS/empty-pkg/}" != "$COOKOPTS" ] && require_copy='no'
547 if grep -q ^genpkg_rules $receipt; then
548 _ 'Executing: %s' 'genpkg_rules'
549 set -e
550 cd $pkgdir; mkdir -p $fs
551 genpkg_rules || (newline; _ 'ERROR: genpkg_rules failed'; newline) >> $LOGS/$pkg.log
552 set +e
553 require_copy='no'
554 else
555 cd $pkgdir; mkdir -p $fs
556 if [ "$CATEGORY" == 'meta' -a "$thispkg" == "$basepkg" ]; then
557 _ 'No packages rules: meta package'
558 require_copy='no'
559 fi
560 fi
562 # Auto-packing
564 for i in DEPENDS SUGGESTED PROVIDE CONFIG_FILES TAGS CATEGORY CAT COPY; do
565 # variable may be already set in genpkg_rules(), check it
566 eval tmpvar="\$$i"
567 [ -n "$tmpvar" ] && continue
568 eval $i="\$(find_vars $i $thispkg)"
569 done
571 [ -n "$CAT" ] && CATEGORY=$(echo "$CAT" | cut -d'|' -f1)
573 if [ "$CATEGORY" != 'meta' -a "$CATEGORY" != 'nopack' ]; then
574 if [ -z "$COPY" -a "$require_copy" == 'yes' ]; then
575 case "$thispkg" in
576 $basepkg) COPY='@std @rm';;
577 *-dev) COPY='@dev @rm';;
578 lib$basepkg) COPY='*.so*';;
579 esac
580 fi
582 if [ -n "$COPY" ]; then
583 copy $COPY
584 elif [ "$require_copy" == 'yes' ]; then
585 var=$(echo -n COPY_$thispkg | tr -c 'a-zA-Z0-9' '_')
586 die "ERROR: $var rules undefined"
587 fi
588 fi
590 if [ "$CATEGORY" == 'nopack' ]; then
591 echo "Skipping $thispkg"
592 return
593 fi
596 #
597 # Check CONFIG_FILES
598 #
600 if [ -n "$CONFIG_FILES" ]; then
601 unset IFS
602 for i in $CONFIG_FILES; do
603 if [ ! -e $fs$i ]; then
604 case $i in
605 */) mkdir -p $fs$i ;;
606 *) mkdir -p $fs$(dirname $i); touch $fs$i ;;
607 esac
608 fi
609 done
610 fi
612 # First QA check to stop now if genpkg_rules failed.
613 if fgrep -q '^ERROR' $LOGS/$basepkg.log; then
614 broken; exit 1
615 fi
618 #
619 # Copy receipt and description
620 #
622 cd $taz
623 action 'Copying "%s"...' 'receipt'
624 mk_pkg_receipt "$(realpath ../receipt)" > $pack/receipt
625 chown 0:0 $pack/receipt
626 status
628 unset desc
629 # description common to all the sub-packages
630 [ -f "../description.txt" ] && desc="../description.txt"
631 # description for specified sub-package
632 [ -f "../description.$thispkg.txt" ] && desc="../description.$thispkg.txt"
633 if [ -n "$desc" ]; then
634 action 'Copying "%s"...' "$(basename "$desc")"
635 cp -f $desc $pack/description.txt
636 chown 0:0 $pack/description.txt
637 status
638 fi
641 #
642 # Copy generic files
643 #
645 # Proceed only for "main" package (for v2), and for any packages (v1)
646 [ "$thispkg" == "$mainpkg" ] && copy_generic_files
649 #
650 # Strip / compress files
651 #
653 arch="$(determine_pkg_arch $fs)"
655 export COOKOPTS ARCH HOST_SYSTEM LOCALE fs; @@PREFIX@@/libexec/cookutils/compressor fs
658 #
659 # Make lists
660 #
662 # Create files.list
663 action 'Creating the list of files...'
664 cd $fs
665 find . \( -type f -o -type l \) | sed 's|^.||' > ../files.list
666 cd ..
667 status
669 # Md5sum of files.
670 action 'Creating md5sum of files...'
671 while read file; do
672 [ -L "fs$file" ] && continue
673 [ -f "fs$file" ] || continue
674 case "$file" in
675 /lib/modules/*/modules.*|*.pyc) continue ;;
676 esac
677 md5sum "fs$file" | sed 's| fs| |'
678 done < files.list | sort -k2 > md5sum
679 status
682 #
683 # Calculate release checksum
684 #
686 # Usually it does not change on "just recook".
687 # Md5sum of the *.tazpkg will change every time because of embedded timestamps;
688 # on the other hand release checksums don't rely on the timestamps, but
689 # only on files content and their permissions.
691 # Calculate rsum for new package
692 RSUM=$(
693 {
694 # a) md5sums of all files
695 cat $pack/md5sum
696 # b) md5sum of receipt
697 md5sum $pack/receipt | sed 's| [^ ]*/| |'
698 # c) md5sum of description.txt
699 [ -e "$pack/description.txt" ] &&
700 md5sum $pack/description.txt | sed 's| [^ ]*/| |'
701 # d) md5sum of list of permissions and ownership of all the files and
702 # folders of the package
703 # stat line example: -rwsr-xr-x 0:0 ./bin/busybox
704 {
705 cd $fs
706 find . -print0 | sort -z | xargs -0rn 1 stat -c '%A %g:%u %N' | md5sum
707 }
708 } | md5sum $rsum_file | awk '{print $1}')
711 #
712 # Compressing
713 #
715 UNPACKED_SIZE=$(du -cks fs receipt files.list md5sum description.txt \
716 2>/dev/null | awk 'END{ print $1 "K"}')
718 # Build fs cpio archive
719 action 'Compressing the FS...'
720 find fs -newer $receipt -exec touch -hr $receipt '{}' \;
721 # find fs | cpio -o -H newc --quiet | lzma-alone e fs.cpio.lzma -si
722 find fs | cpio -o -H newc --quiet | /bin/lzma -qzeT0 >fs.cpio.lzma
723 mv fs ../
724 status
726 PACKED_SIZE=$(du -cks fs.cpio.lzma receipt files.list md5sum description.txt \
727 2>/dev/null | awk 'END{ print $1 "K"}')
730 #
731 # Add variables to the receipt
732 #
734 # Store sizes
735 sed -i '/^PACKED_SIZE=/d; /^UNPACKED_SIZE=/d' receipt
736 sed -i "s|^PACKAGE=|PACKED_SIZE=\"$PACKED_SIZE\"\nUNPACKED_SIZE=\"$UNPACKED_SIZE\"\nPACKAGE=|" receipt
738 # Store RSUM
739 sed -i "s|^PACKAGE=|RSUM=\"$RSUM\"\nPACKAGE=|" receipt
741 # Set extra version
742 if [ -n "$EXTRAVERSION" ]; then
743 sed -i '/^EXTRAVERSION=/d' receipt
744 sed -i "s|^VERSION=|EXTRAVERSION=\"$EXTRAVERSION\"\nVERSION=|" receipt
745 fi
748 #
749 # Build *.tazpkg
750 #
752 action 'Creating full cpio archive...'
753 find . -newer $receipt -exec touch -hr $receipt '{}' \;
754 find . | cpio -o -H newc --quiet > ../$PACKAGE-$VERSION$EXTRAVERSION-$arch.tazpkg
755 status
757 # Restoring original package tree.
758 mv ../fs .
760 rm fs.cpio.lzma; cd ..
762 tazpkg=$(ls *.tazpkg)
765 #
766 # Verify package quality and consistency
767 #
769 # Preferrable way is to combine the commands chain in the compile_rules()
770 # using '&&': when any of the chunk broke, process will stop and function
771 # will return non-zero return code.
772 # On the other hand some old receipts don't use '&&' but depend on the
773 # error messages on the log.
774 # Sometimes it produces false positives in the configuration stage.
775 # In this case we can use the "skip-log-errors".
776 if [ "${COOKOPTS/skip-log-errors/}" == "$COOKOPTS" ]; then
777 # Exit if any error found in log file.
778 if fgrep -q ^ERROR $LOGS/$basepkg.log; then
779 rm -f $command
780 broken; exit 1
781 fi
782 fi
785 # Allow meta-packages in v2 receipts
786 [ -n "$CAT" ] && CATEGORY="${CAT%|*}"
788 if [ "${COOKOPTS/empty-pkg/}" == "$COOKOPTS" ]; then
789 action 'QA: checking for empty package...'
790 if [ ! -s "$pack/files.list" -a "$CATEGORY" != 'meta' ]; then
791 broken
792 rm -f $command
793 false; status
794 die 'ERROR: empty package'
795 fi
796 :; status
797 fi
800 #
801 # Get RSUM from the old package
802 #
804 pkg_file="$PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$arch.tazpkg"
805 if [ -f "$pkg_file" ]; then
806 # don't trust database entry, check the package file
807 tmpdir=$(mktemp -d)
808 cd $tmpdir
809 cpio -F "$pkg_file" -i receipt >/dev/null 2>&1
810 RSUM_OLD=$(unset RSUM; . receipt; echo $RSUM)
811 cd - >/dev/null
812 rm -r $tmpdir
813 else
814 unset RSUM_OLD
815 fi
818 #
819 # Removing unhandled old packages
820 #
822 if [ $ARCH == 'i486' -a -e $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg ]; then
823 action 'Removing old i486 package without arch specifier'
824 rm -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION.tazpkg
825 status
826 fi
828 # For example, if *-dev package contains *.a static libs, it will be either
829 # i486 or x86_64 arch; otherwise it will be "any" arch. This transition
830 # may be done back and forth depending on if you disable static libs or not.
831 case $arch in
832 any)
833 if [ -e $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg ]; then
834 action "Removing old $ARCH package because it arch-less now"
835 rm -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-$ARCH.tazpkg
836 status
837 fi
838 ;;
839 *)
840 if [ -e $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-any.tazpkg ]; then
841 action "Removing old arch-less package because it $ARCH now"
842 rm -f $PKGS/$PACKAGE-$VERSION$EXTRAVERSION-any.tazpkg
843 status
844 fi
845 ;;
846 esac
848 # Find and remove old package only if "release checksum" has changed
850 pi="$PKGS/packages-$ARCH.info"
851 touch $pi
853 if [ "$RSUM" != "$RSUM_OLD" ]; then
854 old_file=$(awk -F$'\t' -vname="$PACKAGE" -varch="$arch" '{
855 if ($1 == name) printf("%s-%s-%s.tazpkg", $1, $2, arch);
856 }' $pi) # <name>-<version><extra_version>-<arch>.tazpkg
857 if [ -f "$PKGS/$old_file" ]; then
858 action 'Removing old package "%s"' "$old_file"
859 rm -f "$PKGS/$old_file"
860 status
861 fi
862 # package changed, substitute old package for new one
863 mv -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION-$arch.tazpkg $PKGS
864 _ 'The release checksum has changed.'
865 else
866 # package not changed, remove new package
867 rm -f $pkgdir/taz/$PACKAGE-$VERSION$EXTRAVERSION-$arch.tazpkg
868 _ 'The release checksum has not changed.'
869 fi
872 #
873 # Package isn't broken anymore
874 #
876 touch $broken
877 sed -i "/^${thispkg}$/d" $broken
880 #
881 # Update packages database every time after successful build
882 #
884 # packages-arch.info (unsorted, located near to packages)
885 unset_receipt; . $pack/receipt
886 SIZES=$(echo $PACKED_SIZE $UNPACKED_SIZE | sed 's|\.0||g')
887 DEPENDS=$(echo $DEPENDS) # remove newlines, tabs and multiple spaces from variable
888 case $arch in
889 i?86) arch_code='3';; # 3 for 32-bit
890 x86_64) arch_code='6';; # 6 for 64-bit
891 any) arch_code='0';; # 0 for any arch
892 esac
894 sed -i "/^$PACKAGE\t/d" $pi # remove old entry
895 cat >> $pi <<EOT
896 $PACKAGE $VERSION$EXTRAVERSION $CATEGORY $SHORT_DESC $WEB_SITE $TAGS $SIZES $DEPENDS $rsum $PROVIDE $arch_code
897 EOT
899 # files.list (uncompressed, unsorted, located in $cache)
900 fl="$cache/files.list"
901 touch $fl
902 sed -i "/^$PACKAGE: /d" $fl
903 sed "s/^/$PACKAGE: \0/" $pack/files.list >> $fl
905 footer "$(_ 'Package "%s" created' "$tazpkg")"
906 }
909 packit "$1"