cookutils view modules/compressor @ rev 1020

cook: handle rsum more stable, fix working with sets when copy() isn't used; modules/compressor: find executables and libs beyond [/usr]?/[s]?bin/; modules/deps: don't process *.la files by default; doc/receipts-v2.md: add chapter 'Dependency tracking'.
author Aleksej Bobylev <al.bobylev@gmail.com>
date Sat Dec 23 15:03:39 2017 +0200 (2017-12-23)
parents 553a90d99a5b
children ee2f3d4790a4
line source
1 #!/bin/sh
2 #
3 # compressor - module of the SliTaz Cook
4 # Copyright (C) SliTaz GNU/Linux - GNU GPL v3
5 #
7 . /usr/lib/slitaz/libcook.sh
9 # Compressor cache stuff
11 comp_cache_root='/home/slitaz/cache/cook'
12 mkdir -p "$comp_cache_root"
13 cache_stat=$(mktemp)
15 # Cache notes.
16 # Do not do the same job twice. Getting the file from the cache is much faster
17 # than compressing the file one more time. In addition, this cache is trying not
18 # to take extra space using the hardlinks. Although the files from the cache
19 # without reference to itself should be removed periodically.
24 #
25 # Functions
26 #
29 # tazpkg install command
31 tpi() {
32 tazpkg -gi --quiet --local --cookmode $1
33 }
36 # Working with time (with hundredths precision)
38 get_time() {
39 cut -d" " -f2 /proc/uptime
40 }
42 calc_time() {
43 # L10n: 's' is for seconds, 'm' is for minutes
44 awk -va="$1" -vb="$(get_time)" -vs="$(_ 's')" -vm="$(_ 'm')" '
45 BEGIN{
46 time = b - a;
47 if (time < 30)
48 printf("%.2f%s\n", time, s);
49 else
50 printf("%.2f%s ~ %.0f%s\n", time, s, time / 60, m);
51 }'
52 }
55 # Compressor mini summary
57 comp_summary() {
58 # "$time0" "$size0" "$size1" "$log_file"
59 status
60 [ "$2" -eq 0 ] && return
61 saving=$(awk -va="$2" -vb="$3" 'BEGIN{ printf("%.0f\n", (a - b) / 1024) }')
62 cache_msg=''
63 if [ -s "$cache_stat" ]; then
64 cache_msg=$(_n ' Cache hit: %d/%d.' "$(fgrep '+' $cache_stat | wc -l)" "$(wc -l < $cache_stat)")
65 echo -n > $cache_stat
66 fi
67 _ ' Time: %s. Size: %s B -> %s B. Save: %s KB.%s' \
68 "$(calc_time $1)" "$2" "$3" "$saving" "$cache_msg"
70 if [ -s "$4" ]; then
71 _ 'Cleaner warnings and errors:'
72 awk '{printf " %s\n", $0;}' "$4"
73 echo
74 fi
75 # Clean log
76 [ ! -f "$4" ] || rm "$4"
77 }
80 # Find ELF files
82 find_elf() {
83 local i ifs="$IFS"
84 IFS=$'\n'
85 find $fs -type f \
86 | while read i; do
87 # output of `readelf -h <file> is human-readable information,
88 # we interested in the next line:
89 # Type: EXEC (Executable file)
90 # or
91 # Type: DYN (Shared object file)
92 if [ "$(readelf -h "$i" 2>/dev/null \
93 | sed -n '/Type:/ s|.*: *\([^ ]*\) .*|\1|p')" == "$1" ]; then
94 echo "$i" # $1 = { EXEC | DYN }
95 fi
96 done
97 IFS="$ifs"
98 }
101 # Calculating different sizes
103 sizes() {
104 local ifs="$IFS"; IFS=$'\n'
105 case $1 in
106 man) find $install/usr/share/man -type f -exec ls -l \{\} \; ;;
107 png) find $install -type f -name '*.png' -exec ls -l \{\} \; ;;
108 svg) find $install -type f -name '*.svg' -exec ls -l \{\} \; ;;
109 xml) find $install -type f \( -name '*.ui' -o -name '*.glade' \) -exec ls -l \{\} \; ;;
110 des) find $install -type f -name '*.desktop' -exec ls -l \{\} \; ;;
111 mo1) find $install -type f -name '*.mo' -exec ls -l \{\} \; ;;
112 loc) find $install/usr/share/i18n/locales -type f -exec ls -l \{\} \; ;;
113 mo2) find $fs/usr/share/locale -type f -name '*.mo' -exec ls -l \{\} \; ;;
114 gz) find $install -type f -name '*.gz' ! -path '*/share/man/*' -exec ls -l \{\} \; ;;
115 zip) find $install -type f -name '*.zip' -exec ls -l \{\} \; ;;
116 strip)
117 {
118 find_elf EXEC
119 find_elf DYN
120 find $fs -type f \( -name '*.a' -o -name '*.pyc' -o -name '*.pyo' \
121 -o -name '.packlist' -o -name '*.pm' -o -name '*.pl' -o -name '*.pod' \)
122 } \
123 | xargs ls -l
124 ;;
125 esac | awk '{s+=$5}END{print s}'
126 IFS="$ifs"
127 }
130 # Query cache for already existing compressed file; substitute original file with the cached
131 # compressed one if so.
132 # $1: cache section (gz, mangz, png, etc.); $2: path to original file
134 query_cache() {
135 md5=$(md5sum "$2")
136 cachefile="$comp_cache_root/$1/${md5%% *}"
137 echo "$cachefile"
138 if [ -f "$cachefile" ]; then
139 ln -f "$cachefile" "$2"
140 echo '+' >> "$cache_stat"
141 else
142 echo '-' >> "$cache_stat"
143 false
144 fi
145 }
148 # Store compressed file to the cache
149 # $1: path to cache entry to be stored; $2: path to compressed file to be stored
151 store_cache() {
152 mkdir -p "${1%/*}"
153 mv "$2" "$1"
154 ln "$1" "$2"
155 }
158 # Function to compress all man pages
159 # Compressing can be disabled with COOKOPTS="!manz"
161 compress_manpages() {
162 time0=$(get_time)
163 [ "${COOKOPTS/!manz/}" != "$COOKOPTS" ] && return
164 manpath="$install/usr/share/man"
165 [ -d "$manpath" ] || return
166 size0=$(sizes man); [ -z "$size0" ] && return
168 tpi advancecomp-static
170 action 'Compressing man pages...'
172 # We'll use only Gzip compression, so decompress other formats first
173 find $manpath -type f -name '*.bz2' -exec bunzip2 \{\} \;
174 find $manpath -type f -name '*.xz' -exec unxz \{\} \;
176 # Fast compress with gzip
177 find $manpath -type f ! -name '*.gz' -exec gzip \{\} \;
179 # Fix symlinks
180 for i in $(find $manpath -type l); do
181 dest=$(readlink $i | sed 's|\.[gbx]z2*$||')
182 link=$(echo $i | sed 's|\.[gbx]z2*$||')
183 rm $i; ln -s $dest.gz $link.gz
184 done
186 # Recompress with advdef (it can't compress, only recompress)
187 cleaner_log="$(mktemp)"
188 IFS=$'\n'
189 for i in $(find $manpath -type f); do
190 if ! cached_path=$(query_cache mangz "$i"); then
191 cp -a "$i" "$i.orig$$" # save the original if something goes wrong
192 out="$(advdef -z4q "$i")"
193 if [ -n "$out" ]; then
194 echo "$i:"$'\n'"$out"$'\n' >> "$cleaner_log"
195 mv -f "$i.orig$$" "$i" # restore the original
196 else
197 store_cache "$cached_path" "$i"
198 rm -f "$i.orig$$" # clean
199 fi
200 fi
201 done
203 comp_summary "$time0" "$size0" "$(sizes man)" "$cleaner_log"
204 }
207 # Function to recompress all gzip archives
208 # Recompressing can be disabled with COOKOPTS="!gz"
210 recompress_gz() {
211 time0=$(get_time)
212 [ "${COOKOPTS/!gz/}" != "$COOKOPTS" ] && return
213 size0=$(sizes gz); [ -z "$size0" ] && return
215 tpi advancecomp-static
217 action 'Recompressing gzip files...'
219 # Recompress with advdef
220 cleaner_log="$(mktemp)"
221 IFS=$'\n'
222 for i in $(find $install -type f -name '*.gz' ! -path '*/share/man/*'); do
223 if ! cached_path=$(query_cache gz "$i"); then
224 cp -a "$i" "$i.orig$$" # save the original if something goes wrong
225 out="$(advdef -z4q "$i")"
226 if [ -n "$out" ]; then
227 echo "$i:"$'\n'"$out"$'\n' >> "$cleaner_log"
228 mv -f "$i.orig$$" "$i" # restore the original
229 else
230 store_cache "$cached_path" "$i"
231 rm -f "$i.orig$$" # clean
232 fi
233 fi
234 done
236 comp_summary "$time0" "$size0" "$(sizes gz)" "$cleaner_log"
237 }
240 # Function to recompress all zip archives
241 # Recompressing can be disabled with COOKOPTS="!zip"
243 recompress_zip() {
244 time0=$(get_time)
245 [ "${COOKOPTS/!zip/}" != "$COOKOPTS" ] && return
246 size0=$(sizes zip); [ -z "$size0" ] && return
248 tpi advancecomp-static
250 action 'Recompressing zip files...'
252 # Recompress with advzip
253 cleaner_log="$(mktemp)"
254 IFS=$'\n'
255 for i in $(find $install -type f -name '*.zip'); do
256 if ! cached_path=$(query_cache zip "$i"); then
257 cp -a "$i" "$i.orig$$" # save the original if something goes wrong
258 out="$(advzip -z3qk "$i")" # '-4' is more than two orders slower; use '-3'
259 if [ -n "$out" ]; then
260 echo "$i:"$'\n'"$out"$'\n' >> "$cleaner_log"
261 mv -f "$i.orig$$" "$i" # restore the original
262 else
263 store_cache "$cached_path" "$i"
264 rm -f "$i.orig$$" # clean
265 fi
266 fi
267 done
269 comp_summary "$time0" "$size0" "$(sizes zip)" "$cleaner_log"
270 }
273 # Function used after compile_rules() to compress all png images
274 # Compressing can be disabled with COOKOPTS="!pngz"
276 compress_png() {
277 time0=$(get_time)
278 [ "${COOKOPTS/!pngz/}" != "$COOKOPTS" ] && return
279 size0=$(sizes png); [ -z "$size0" ] && return
281 use_pq=true
282 use_op=true
283 [ "${COOKOPTS/!pngquant/}" != "$COOKOPTS" ] && use_pq=false
284 [ "${COOKOPTS/!optipng/}" != "$COOKOPTS" ] && use_op=false
285 $use_pq && tpi pngquant-static
286 $use_op && tpi optipng-static
288 action 'Compressing png images...'
290 oplevel=$(echo $COOKOPTS | grep 'op[0-8]' | sed 's|.*op\([0-8]\).*|\1|')
291 [ -z "$oplevel" ] && oplevel='2'
293 cache_section="png$oplevel"
294 $use_pq && cache_section="${cache_section}p"
295 $use_op && cache_section="${cache_section}o"
297 [ "$oplevel" == '8' ] && oplevel='7 -zm1-9'
299 cleaner_log="$(mktemp)"
300 pq_opt='--skip-if-larger' # Sublime Text is mad about `if` in $(), so put it separately
301 IFS=$'\n'
302 for i in $(find $install -type f -name '*.png'); do
303 unset IFS iserror
304 if ! cached_path=$(query_cache $cache_section "$i"); then
305 cp -a "$i" "$i.orig$$" # save the original if something goes wrong
306 if $use_pq; then
307 out="$(pngquant -f $pq_opt --ext .png --speed 1 "$i" 2>&1)"
308 if [ -n "$out" ]; then
309 echo "$i (pngquant):"$'\n'"$out"$'\n' >> "$cleaner_log"
310 iserror='yes'
311 fi
312 fi
313 if $use_op && [ -z "$iserror" ]; then
314 out="$(optipng -quiet -strip all -o$oplevel "$i" 2>&1)"
315 if [ -n "$out" ]; then
316 echo "$i (optipng):"$'\n'"$out"$'\n' >> "$cleaner_log"
317 iserror='yes'
318 fi
319 fi
320 if [ -n "$iserror" ]; then
321 mv -f "$i.orig$$" "$i" # restore the original
322 else
323 store_cache "$cached_path" "$i"
324 rm -f "$i.orig$$" # clean
325 fi
326 fi
327 done
329 comp_summary "$time0" "$size0" "$(sizes png)" "$cleaner_log"
330 }
333 # Function used after compile_rules() to compress all svg images
334 # Compressing can be disabled with COOKOPTS="!svgz"
336 compress_svg() {
337 time0=$(get_time)
338 [ "${COOKOPTS/!svgz/}" != "$COOKOPTS" ] && return
339 size0=$(sizes svg); [ -z "$size0" ] && return
341 tpi svgcleaner
343 action 'Compressing svg images...'
345 [ "${COOKOPTS/!svgextra/}" == "$COOKOPTS" ] &&
346 opts="--apply-transform-to-paths yes --coordinates-precision 1 --paths-coordinates-precision 1"
348 cleaner_log="$(mktemp)"
349 for i in $(IFS=$'\n' find $install -type f -name '*.svg'); do
350 out="$(unset IFS; svgcleaner "$i" "$i" --copy-on-error --quiet \
351 --multipass --remove-unresolved-classes no $opts 2>&1)"
352 [ -z "$out" ] || echo "$i:"$'\n'"$out"$'\n' >> "$cleaner_log"
353 done
355 comp_summary "$time0" "$size0" "$(sizes svg)" "$cleaner_log"
356 }
359 # Function used after compile_rules() to shrink all *.ui and *.glade files:
360 # remove insignificant spaces and comments
361 # Compressing can be disabled with COOKOPTS="!uiz"
363 compress_ui() {
364 [ "${COOKOPTS/!uiz/}" != "$COOKOPTS" ] && return
365 [ -z "$(find $install -type f \( -name '*.ui' -o -name '*.glade' \) )" ] && return
367 tpi xmlstarlet
369 action 'Compressing ui files...'
371 size0=$(sizes xml)
372 time0=$(get_time)
373 temp_ui="$(mktemp)"
374 cleaner_log="$(mktemp)"
375 IFS=$'\n'
376 for ui in $(find $install -type f \( -name '*.ui' -o -name '*.glade' \) ); do
377 out="$(xmlstarlet c14n --without-comments "$ui" | xmlstarlet sel -B -t -c '*' > "$temp_ui")"
378 if [ -n "$out" ]; then
379 echo "$ui:"$'\n'"$out"$'\n' >> "$cleaner_log"
380 else
381 cat "$temp_ui" > "$ui"
382 fi
383 done
385 comp_summary "$time0" "$size0" "$(sizes xml)" "$cleaner_log"
386 rm "$temp_ui"
387 }
390 # Get list of supported locales...
392 get_supported_locales() {
393 lpc='/slitaz-i18n/stuff/locale-pack.conf'
394 if [ -e "$WOK$lpc" ]; then
395 # ... from package in the local wok
396 . "$WOK$lpc"
397 else
398 # ... from Hg
399 temp_conf=$(mktemp)
400 wget -q -O $temp_conf -T 10 "http://hg.slitaz.org/wok/raw-file/tip$lpc"
401 if [ -s $temp_conf ]; then
402 . $temp_conf
403 else
404 # Give up and use hardcoded list
405 LOCALE_PACK="ar ca cs da de el en es fi fr hr hu id is it ja nb nl nn pl pt \
406 pt_BR ro ru sl sv tr uk zh_CN zh_TW"
407 fi
408 rm $temp_conf
409 fi
410 echo $LOCALE_PACK
411 }
414 # Fix common errors and warnings in the .desktop files
415 # Fixing can be disabled with COOKOPTS="!fixdesktops"
417 fix_desktop_files() {
418 [ "${COOKOPTS/!fixdesktops/}" != "$COOKOPTS" ] && return
419 deskpath="$install/usr/share/applications"
420 [ -d "$deskpath" ] || return
421 [ -z "$(find $deskpath -type f -name '*.desktop')" ] && return
423 size0=$(sizes des)
424 time0=$(get_time)
426 if [ -n "$QA" -a -z "$(which desktop-file-validate)" ]; then
427 tpi desktop-file-validate-static
428 fi
430 # The variable $LOCALE is set in cook.conf and may be overridden in the receipt.
431 # Default value is "" (empty). That means for us that we'll use the full
432 # list of supported locales here.
433 [ -z "$LOCALE" ] && LOCALE=$(get_supported_locales)
435 IFS=$'\n'
436 for desktop in $(find $deskpath -type f -name '*.desktop'); do
437 cp "$desktop" "$desktop.orig"
439 # Sort out .desktop file (is prerequisite to correct working of `fix-desktop-file`)
440 sdft "$desktop" -i
442 # Fix common errors in .desktop file
443 fix-desktop-file "$desktop"
445 # Strip unsupported locales from .desktop file
446 [ "${COOKOPTS/!i18nz/}" == "$COOKOPTS" ] &&
447 sdft "$desktop" -i -k "$LOCALE"
449 # Extra-strip
450 [ "${COOKOPTS/!extradesktops/}" == "$COOKOPTS" ] &&
451 sdft "$desktop" -i -g -x -tf -r 'Keywords*' -o
453 if [ -n "$QA" ]; then
454 # Check the rest of errors, warnings and tips
455 _ 'QA: Checking %s...' "$(basename $desktop)"
456 busybox diff "$desktop.orig" "$desktop" | sed 's!^!|!'
457 desktop-file-validate "$desktop" | busybox fold -s
458 echo
459 fi
461 rm "$desktop.orig"
462 done
464 comp_summary "$time0" "$size0" "$(sizes des)" '/dev/null'
465 }
468 # Normalize all *.mo files: unconditionally convert to UTF-8; remove strings that are not really necessary
469 # to the translation (msgid = msgstr)
470 # Normalization can be disabled with COOKOPTS="!monorm"
472 normalize_mo() {
473 [ "${COOKOPTS/!monorm/}" != "$COOKOPTS" ] && return
474 [ -z "$(find $install -type f -name '*.mo')" ] && return
476 # Gettext functions: msgunfmt, msguniq, msgconv, msgfmt
477 tpi gettext
478 # Gconv modules (convert to UTF-8)
479 tpi glibc-locale
481 action 'Normalizing mo files...'
483 size0=$(sizes mo1)
484 time0=$(get_time)
486 # Process all existing *.mo files
487 cleaner_log="$(mktemp)"
488 IFS=$'\n'
489 for mo in $(find "$install" -type f -name '*.mo'); do
490 tmpfile="$(mktemp)"
492 # put ANY errors of {msgunfmt,msguniq,msgconv} to $out. FIXME?
493 out="$({ msgunfmt "$mo" | msguniq | msgconv -o "$tmpfile" -t 'UTF-8'; } 2>&1)"
494 if [ -n "$out" ]; then
495 # using literal $'\n' here instead of using `echo -e "...\n..."` because
496 # $out may contain escapes ('\r', '\v') that we should print as-is
497 echo "$mo:"$'\n'"$out"$'\n' >> "$cleaner_log"
498 continue # proceed to next file
499 fi
501 # add newline
502 echo >> "$tmpfile"
504 # get Plural-Forms
505 awk '
506 BEGIN { skip = ""; }
507 {
508 if (! skip) {
509 s = $0;
510 gsub(/^[^\"]*\"/, "", s);
511 gsub(/\"$/, "", s);
512 printf("%s", s);
513 }
514 if (! $0) skip = "yes";
515 }
516 ' "$tmpfile" | sed 's|\\n|\n|g' | grep "^Plural-Forms:" > "$tmpfile.pf"
518 if ! grep -q 'msgid_plural' "$tmpfile"; then
519 echo > "$tmpfile.pf"
520 fi
522 # main
523 awk -v pf="$(cat "$tmpfile.pf")" '
524 function clean() {
525 mode = msgctxt = msgid = msgid_plural = msgstr = msgstr0 = msgstr1 = msgstr2 = msgstr3 = msgstr4 = msgstr5 = "";
526 }
528 function getstring() {
529 # Skip unquoted words at the beginning (msgid, msgstr...) and get string from inside quotes
530 s = $0;
531 gsub(/^[^\"]*\"/, "", s);
532 gsub(/\"$/, "", s);
533 return s;
534 }
536 BEGIN {
537 printf("msgid \"\"\nmsgstr \"\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n");
538 if (pf)
539 printf("\"%s\\n\"\n", pf);
540 printf("\n");
541 skip = 1;
542 clean();
543 }
545 {
546 # Skip the entire header
547 if (!skip) {
548 if ($1 == "msgctxt" || $1 == "msgid" || $1 == "msgstr" || $1 == "msgid_plural")
549 mode = $1;
550 if ($1 == "msgstr[0]") mode = "msgstr0";
551 if ($1 == "msgstr[1]") mode = "msgstr1";
552 if ($1 == "msgstr[2]") mode = "msgstr2";
553 if ($1 == "msgstr[3]") mode = "msgstr3";
554 if ($1 == "msgstr[4]") mode = "msgstr4";
555 if ($1 == "msgstr[5]") mode = "msgstr5";
557 if (mode == "msgctxt") msgctxt = msgctxt getstring();
558 if (mode == "msgid") msgid = msgid getstring();
559 if (mode == "msgstr") msgstr = msgstr getstring();
560 if (mode == "msgid_plural") msgid_plural = msgid_plural getstring();
561 if (mode == "msgstr0") msgstr0 = msgstr0 getstring();
562 if (mode == "msgstr1") msgstr1 = msgstr1 getstring();
563 if (mode == "msgstr2") msgstr2 = msgstr2 getstring();
564 if (mode == "msgstr3") msgstr3 = msgstr3 getstring();
565 if (mode == "msgstr4") msgstr4 = msgstr4 getstring();
566 if (mode == "msgstr5") msgstr5 = msgstr5 getstring();
568 if (! $0) {
569 if (msgid != msgstr) {
570 if (msgctxt) printf("msgctxt \"%s\"\n", msgctxt);
571 printf("msgid \"%s\"\n", msgid);
572 if (msgid_plural) printf("msgid_plural \"%s\"\n", msgid_plural);
573 if (msgstr) printf("msgstr \"%s\"\n", msgstr);
574 if (msgstr0) printf("msgstr[0] \"%s\"\n", msgstr0);
575 if (msgstr1) printf("msgstr[1] \"%s\"\n", msgstr1);
576 if (msgstr2) printf("msgstr[2] \"%s\"\n", msgstr2);
577 if (msgstr3) printf("msgstr[3] \"%s\"\n", msgstr3);
578 if (msgstr4) printf("msgstr[4] \"%s\"\n", msgstr4);
579 if (msgstr5) printf("msgstr[5] \"%s\"\n", msgstr5);
580 printf("\n");
581 }
582 clean();
583 }
584 }
585 if ($0 == "") skip = "";
586 }
587 ' "$tmpfile" > "$tmpfile.awk"
589 out="$(msgfmt "$tmpfile.awk" -o "$tmpfile.mo" 2>&1)"
590 if [ -n "$out" ]; then
591 echo "$mo (msgfmt):"$'\n'"$out"$'\n' >> "$cleaner_log"
592 continue # proceed to next file
593 fi
595 if [ -s "$tmpfile.mo" ]; then
596 rm "$mo"; mv "$tmpfile.mo" "$mo"
597 else
598 _ 'Error processing %s' "$mo" >> "$cleaner_log"
599 echo >> "$cleaner_log"
600 [ -e "$tmpfile.mo" ] && rm "$tmpfile.mo"
601 fi
603 # Clean
604 rm "$tmpfile" "$tmpfile.pf" "$tmpfile.awk"
605 done
607 comp_summary "$time0" "$size0" "$(sizes mo1)" "$cleaner_log"
608 }
611 # Strip locale definitions: normalize whitespace and remove comments
612 # Stripping can be disabled with COOKOPTS="!locdef"
614 strip_locale_def() {
615 [ "${COOKOPTS/!locdef/}" != "$COOKOPTS" ] && return
616 [ ! -d "$install/usr/share/i18n/locales" ] && return
617 [ -z "$(find $install/usr/share/i18n/locales -type f)" ] && return
619 action 'Stripping locale definitions...'
620 size0=$(sizes loc)
621 time0=$(get_time)
623 for i in $(find $install/usr/share/i18n/locales -type f); do
624 sed -i 's| | |g; s| *| |g; s|^ ||; /^%/d' $i
625 done
627 comp_summary "$time0" "$size0" "$(sizes loc)"
628 }
631 # Find and strip: --strip-all (-s) or --strip-debug on static libs as well
632 # as removing unneeded files like in Python packages. Cross compiled binaries
633 # must be stripped with cross-tools aka $ARCH-slitaz-*-strip
634 # Stripping can be disabled with COOKOPTS="!strip"
636 strip_package() {
637 [ "${COOKOPTS/!strip/}" != "$COOKOPTS" ] && return
639 local i ifs="$IFS"
640 IFS=$'\n'
642 case "$ARCH" in
643 arm*|x86_64) export STRIP="$HOST_SYSTEM-strip" ;;
644 *) export STRIP='strip' ;;
645 esac
646 action 'Executing strip on all files...'
647 size0=0
648 size1=0
649 time0=$(get_time)
650 oldsize=$(sizes strip)
652 # Strip executable files & shared libraries
653 while read i; do
654 $STRIP -s "$i" 2>/dev/null
655 done <<EOT
656 $(find_elf EXEC; find_elf DYN)
657 EOT
659 # Strip static libraries
660 find $fs -name '*.a' -exec $STRIP -d '{}' 2>/dev/null \;
662 # Nullify timestamps of files in ar archives
663 # Skip empty 8-byte archives (hi, musl-libc package)
664 whereami=$(pwd)
665 find $fs -name '*.a' -type f -size +8c | \
666 while read i; do
667 tempdir=$(mktemp -d); cd $tempdir
668 ar -x $i; ar -crD $(basename $i) *
669 mv -f $tempdir/$(basename $i) $i
670 rm -rf $tempdir
671 done
672 cd $whereami; unset whereami
674 # Remove Python *.pyc and *.pyo
675 find $fs -type f \( -name '*.pyc' -o -name '*.pyo' \) -delete 2>/dev/null
677 # Remove both with the empty subfolders:
678 # 1. Perl perllocal.pod and .packlist (unconditionally)
679 local perlfiles="$(find $fs -type f \( -name 'perllocal.pod' -o -name '.packlist' \))"
680 # 2. Perl *.pod (if not disabled)
681 [ "${COOKOPTS/!rmpod/}" == "$COOKOPTS" ] &&
682 perlfiles="$perlfiles $(find $fs -type f -name '*.pod')"
683 echo "$perlfiles" | xargs rm -f 2>/dev/null
684 echo "$perlfiles" | awk 'BEGIN{FS=OFS="/"}{$NF="";print}' | xargs rmdir -p 2>/dev/null
686 # Strip documentation inside Perl files (*.pm and *.pl) (if not disabled)
687 [ "${COOKOPTS/!perlz/}" == "$COOKOPTS" ] &&
688 find $fs -type f \( -name '*.pm' -o -name '*.pl' \) -exec sed -i '/^=/,/^=cut/d' '{}' \;
690 newsize=$(sizes strip)
692 comp_summary "$time0" "$oldsize" "$newsize"
693 IFS="$ifs"
694 }
697 # Strip unsupported locales (.mo files)
699 strip_mo_i18n() {
700 [ "${COOKOPTS/!i18nz/}" != "$COOKOPTS" ] && return
702 [ ! -d "$fs/usr/share/locale" ] && return
703 [ -z "$(find $fs/usr/share/locale -type f -name '*.mo')" ] && return
705 action 'Thin out translation files...'
706 size0=$(sizes mo2)
707 time0=$(get_time)
709 # The variable $LOCALE is set in cook.conf and may be overridden in the receipt.
710 # Default value is "" (empty). That means for us that we'll use the full
711 # list of supported locales here.
712 [ -z "$LOCALE" ] && LOCALE=$(get_supported_locales)
714 # Existing locales
715 elocales=" $(ls -1 "$fs/usr/share/locale" | tr '\n' ' ') "
717 # Thin out the list of existing locales. At the end there will be only locales that need
718 # deleting (and the garbage like '_AU', _US', '_BR' leaving from 'en_AU', 'en_US', 'pt_BR'...)
719 for keep_locale in $LOCALE; do
720 elocales=${elocales//$keep_locale}
721 done
723 # Remove the unsupported locales
724 for rem_locale in $elocales; do
725 [ ! -d "$fs/usr/share/locale/$rem_locale" ] ||
726 rm -r "$fs/usr/share/locale/$rem_locale"
727 done
729 comp_summary "$time0" "$size0" "$(sizes mo2)"
730 }
735 case $1 in
736 install)
737 # Compressors working in the $install
738 case "$ARCH" in
739 arm*) ;;
740 *)
741 recompress_gz
742 recompress_zip
743 compress_manpages
744 compress_png
745 compress_svg
746 compress_ui
747 ;;
748 esac
750 fix_desktop_files
751 normalize_mo
752 strip_locale_def
753 ;;
754 fs)
755 # Compressors working in the $fs
756 strip_package
757 strip_mo_i18n
758 ;;
759 esac
761 # Clean
762 rm "$cache_stat"
763 find $comp_cache_root -type f -links -2 -delete