CRUX-ARM : Home

Home :: Documentation :: Download :: Development :: Community :: Ports :: Packages :: Bugs :: Links :: About :: Donors
moved ChangeLog to NEWS
[pkgutils-cross.git] / pkgmk.in
CommitLineData
9ac667e6
SR
1#!/bin/bash
2#
3# pkgutils
4#
5# Copyright (c) 2000-2005 Per Liden
6#
7# This program is free software; you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program; if not, write to the Free Software
19# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20# USA.
21#
22
23info() {
24 echo "=======> $1"
25}
26
27warning() {
28 info "WARNING: $1"
29}
30
31error() {
32 info "ERROR: $1"
33}
34
35get_filename() {
36 local FILE="`echo $1 | sed 's|^.*://.*/||g'`"
37
38 if [ "$FILE" != "$1" ]; then
39 FILE="$PKGMK_SOURCE_DIR/$FILE"
40 fi
41
42 echo $FILE
43}
44
45check_pkgfile() {
46 if [ ! "$name" ]; then
47 error "Variable 'name' not specified in $PKGMK_PKGFILE."
48 exit 1
49 elif [ ! "$version" ]; then
50 error "Variable 'version' not specified in $PKGMK_PKGFILE."
51 exit 1
52 elif [ ! "$release" ]; then
53 error "Variable 'release' not specified in $PKGMK_PKGFILE."
54 exit 1
55 elif [ "`type -t build`" != "function" ]; then
56 error "Function 'build' not specified in $PKGMK_PKGFILE."
57 exit 1
58 fi
59}
60
61check_directory() {
62 if [ ! -d $1 ]; then
63 error "Directory '$1' does not exist."
64 exit 1
65 elif [ ! -w $1 ]; then
66 error "Directory '$1' not writable."
67 exit 1
68 elif [ ! -x $1 ] || [ ! -r $1 ]; then
69 error "Directory '$1' not readable."
70 exit 1
71 fi
72}
73
74download_file() {
75 info "Downloading '$1'."
76
77 if [ ! "`type -p wget`" ]; then
78 error "Command 'wget' not found."
79 exit 1
80 fi
81
82 LOCAL_FILENAME=`get_filename $1`
83 LOCAL_FILENAME_PARTIAL="$LOCAL_FILENAME.partial"
84 DOWNLOAD_CMD="--passive-ftp --no-directories --tries=3 --waitretry=3 \
85 --directory-prefix=$PKGMK_SOURCE_DIR --output-document=$LOCAL_FILENAME_PARTIAL $1"
86
87 if [ -f "$LOCAL_FILENAME_PARTIAL" ]; then
88 info "Partial download found, trying to resume"
89 RESUME_CMD="-c"
90 fi
91
92 while true; do
93 wget $RESUME_CMD $DOWNLOAD_CMD
94 error=$?
95 if [ $error != 0 ] && [ "$RESUME_CMD" ]; then
96 info "Partial download failed, restarting"
97 rm -f "$LOCAL_FILENAME_PARTIAL"
98 RESUME_CMD=""
99 else
100 break
101 fi
102 done
103
104 if [ $error != 0 ]; then
105 error "Downloading '$1' failed."
106 exit 1
107 fi
108
109 mv -f "$LOCAL_FILENAME_PARTIAL" "$LOCAL_FILENAME"
110}
111
112download_source() {
113 local FILE LOCAL_FILENAME
114
115 for FILE in ${source[@]}; do
116 LOCAL_FILENAME=`get_filename $FILE`
117 if [ ! -e $LOCAL_FILENAME ]; then
118 if [ "$LOCAL_FILENAME" = "$FILE" ]; then
119 error "Source file '$LOCAL_FILENAME' not found (can not be downloaded, URL not specified)."
120 exit 1
121 else
122 if [ "$PKGMK_DOWNLOAD" = "yes" ]; then
123 download_file $FILE
124 else
125 error "Source file '$LOCAL_FILENAME' not found (use option -d to download)."
126 exit 1
127 fi
128 fi
129 fi
130 done
131}
132
133unpack_source() {
134 local FILE LOCAL_FILENAME COMMAND
135
136 for FILE in ${source[@]}; do
137 LOCAL_FILENAME=`get_filename $FILE`
138 case $LOCAL_FILENAME in
139 *.tar.gz|*.tar.Z|*.tgz)
140 COMMAND="tar -C $SRC --use-compress-program=gzip -xf $LOCAL_FILENAME" ;;
141 *.tar.bz2)
142 COMMAND="tar -C $SRC --use-compress-program=bzip2 -xf $LOCAL_FILENAME" ;;
143 *.zip)
144 COMMAND="unzip -qq -o -d $SRC $LOCAL_FILENAME" ;;
145 *)
146 COMMAND="cp $LOCAL_FILENAME $SRC" ;;
147 esac
148
149 echo "$COMMAND"
150
151 $COMMAND
152
153 if [ $? != 0 ]; then
154 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
155 rm -rf $PKGMK_WORK_DIR
156 fi
157 error "Building '$TARGET' failed."
158 exit 1
159 fi
160 done
161}
162
163make_md5sum() {
164 local FILE LOCAL_FILENAMES
165
166 if [ "$source" ]; then
167 for FILE in ${source[@]}; do
168 LOCAL_FILENAMES="$LOCAL_FILENAMES `get_filename $FILE`"
169 done
170
171 md5sum $LOCAL_FILENAMES | sed -e 's| .*/| |' | sort -k 2
172 fi
173}
174
175make_footprint() {
176 pkginfo --footprint $TARGET | \
177 sed "s|\tlib/modules/`uname -r`/|\tlib/modules/<kernel-version>/|g" | \
178 sort -k 3
179}
180
181check_md5sum() {
182 local FILE="$PKGMK_WORK_DIR/.tmp"
183
184 cd $PKGMK_ROOT
185
186 if [ -f $PKGMK_MD5SUM ]; then
187 make_md5sum > $FILE.md5sum
188 sort -k 2 $PKGMK_MD5SUM > $FILE.md5sum.orig
189 diff -w -t -U 0 $FILE.md5sum.orig $FILE.md5sum | \
190 sed '/^@@/d' | \
191 sed '/^+++/d' | \
192 sed '/^---/d' | \
193 sed 's/^+/NEW /g' | \
194 sed 's/^-/MISSING /g' > $FILE.md5sum.diff
195 if [ -s $FILE.md5sum.diff ]; then
196 error "Md5sum mismatch found:"
197 cat $FILE.md5sum.diff
198
199 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
200 rm -rf $PKGMK_WORK_DIR
201 fi
202
203 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
204 error "Md5sum not ok."
205 exit 1
206 fi
207
208 error "Building '$TARGET' failed."
209 exit 1
210 fi
211 else
212 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
213 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
214 rm -rf $PKGMK_WORK_DIR
215 fi
216 info "Md5sum not found."
217 exit 1
218 fi
219
220 warning "Md5sum not found, creating new."
221 make_md5sum > $PKGMK_MD5SUM
222 fi
223
224 if [ "$PKGMK_CHECK_MD5SUM" = "yes" ]; then
225 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
226 rm -rf $PKGMK_WORK_DIR
227 fi
228 info "Md5sum ok."
229 exit 0
230 fi
231}
232
233strip_files() {
234 local FILE FILTER
235
236 cd $PKG
237
238 if [ -f $PKGMK_ROOT/$PKGMK_NOSTRIP ]; then
239 FILTER="grep -v -f $PKGMK_ROOT/$PKGMK_NOSTRIP"
240 else
241 FILTER="cat"
242 fi
243
244 find . -type f -printf "%P\n" | $FILTER | while read FILE; do
245 if file -b "$FILE" | grep '^.*ELF.*executable.*not stripped$' &> /dev/null; then
246 strip --strip-all "$FILE"
247 elif file -b "$FILE" | grep '^.*ELF.*shared object.*not stripped$' &> /dev/null; then
248 strip --strip-unneeded "$FILE"
249 elif file -b "$FILE" | grep '^current ar archive$' &> /dev/null; then
250 strip --strip-debug "$FILE"
251 fi
252 done
253}
254
255compress_manpages() {
256 local FILE DIR TARGET
257
258 cd $PKG
259
260 find . -type f -path "*/man/man*/*" | while read FILE; do
261 if [ "$FILE" = "${FILE%%.gz}" ]; then
262 gzip -9 "$FILE"
263 fi
264 done
265
266 find . -type l -path "*/man/man*/*" | while read FILE; do
267 TARGET=`readlink -n "$FILE"`
268 TARGET="${TARGET##*/}"
269 TARGET="${TARGET%%.gz}.gz"
270 rm -f "$FILE"
271 FILE="${FILE%%.gz}.gz"
272 DIR=`dirname "$FILE"`
273
274 if [ -e "$DIR/$TARGET" ]; then
275 ln -sf "$TARGET" "$FILE"
276 fi
277 done
278}
279
280check_footprint() {
281 local FILE="$PKGMK_WORK_DIR/.tmp"
282
283 cd $PKGMK_ROOT
284
285 if [ -f $TARGET ]; then
286 make_footprint > $FILE.footprint
287 if [ -f $PKGMK_FOOTPRINT ]; then
288 sort -k 3 $PKGMK_FOOTPRINT > $FILE.footprint.orig
289 diff -w -t -U 0 $FILE.footprint.orig $FILE.footprint | \
290 sed '/^@@/d' | \
291 sed '/^+++/d' | \
292 sed '/^---/d' | \
293 sed 's/^+/NEW /g' | \
294 sed 's/^-/MISSING /g' > $FILE.footprint.diff
295 if [ -s $FILE.footprint.diff ]; then
296 error "Footprint mismatch found:"
297 cat $FILE.footprint.diff
298 BUILD_SUCCESSFUL="no"
299 fi
300 else
301 warning "Footprint not found, creating new."
302 mv $FILE.footprint $PKGMK_FOOTPRINT
303 fi
304 else
305 error "Package '$TARGET' was not found."
306 BUILD_SUCCESSFUL="no"
307 fi
308}
309
310build_package() {
311 local BUILD_SUCCESSFUL="no"
312
313 export PKG="$PKGMK_WORK_DIR/pkg"
314 export SRC="$PKGMK_WORK_DIR/src"
315 umask 022
316
317 cd $PKGMK_ROOT
318 rm -rf $PKGMK_WORK_DIR
319 mkdir -p $SRC $PKG
320
321 if [ "$PKGMK_IGNORE_MD5SUM" = "no" ]; then
322 check_md5sum
323 fi
324
325 if [ "$UID" != "0" ]; then
326 warning "Packages should be built as root."
327 fi
328
329 info "Building '$TARGET'."
330
331 unpack_source
332
333 cd $SRC
334 (set -e -x ; build)
335
336 if [ $? = 0 ]; then
337 if [ "$PKGMK_NO_STRIP" = "no" ]; then
338 strip_files
339 fi
340
341 compress_manpages
342
343 cd $PKG
344 info "Build result:"
345 tar czvvf $TARGET *
346
347 if [ $? = 0 ]; then
348 BUILD_SUCCESSFUL="yes"
349
350 if [ "$PKGMK_IGNORE_FOOTPRINT" = "yes" ]; then
351 warning "Footprint ignored."
352 else
353 check_footprint
354 fi
355 fi
356 fi
357
358 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
359 rm -rf $PKGMK_WORK_DIR
360 fi
361
362 if [ "$BUILD_SUCCESSFUL" = "yes" ]; then
363 info "Building '$TARGET' succeeded."
364 else
365 if [ -f $TARGET ]; then
366 touch -r $PKGMK_ROOT/$PKGMK_PKGFILE $TARGET &> /dev/null
367 fi
368 error "Building '$TARGET' failed."
369 exit 1
370 fi
371}
372
373install_package() {
374 local COMMAND
375
376 info "Installing '$TARGET'."
377
378 if [ "$PKGMK_INSTALL" = "install" ]; then
379 COMMAND="pkgadd $TARGET"
380 else
381 COMMAND="pkgadd -u $TARGET"
382 fi
383
384 cd $PKGMK_ROOT
385 echo "$COMMAND"
386 $COMMAND
387
388 if [ $? = 0 ]; then
389 info "Installing '$TARGET' succeeded."
390 else
391 error "Installing '$TARGET' failed."
392 exit 1
393 fi
394}
395
396recursive() {
397 local ARGS FILE DIR
398
399 ARGS=`echo "$@" | sed -e "s/--recursive//g" -e "s/-r//g"`
400
401 for FILE in `find $PKGMK_ROOT -name $PKGMK_PKGFILE | sort`; do
402 DIR="`dirname $FILE`/"
403 if [ -d $DIR ]; then
404 info "Entering directory '$DIR'."
405 (cd $DIR && $PKGMK_COMMAND $ARGS)
406 info "Leaving directory '$DIR'."
407 fi
408 done
409}
410
411clean() {
412 local FILE LOCAL_FILENAME
413
414 if [ -f $TARGET ]; then
415 info "Removing $TARGET"
416 rm -f $TARGET
417 fi
418
419 for FILE in ${source[@]}; do
420 LOCAL_FILENAME=`get_filename $FILE`
421 if [ -e $LOCAL_FILENAME ] && [ "$LOCAL_FILENAME" != "$FILE" ]; then
422 info "Removing $LOCAL_FILENAME"
423 rm -f $LOCAL_FILENAME
424 fi
425 done
426}
427
428update_footprint() {
429 if [ ! -f $TARGET ]; then
430 error "Unable to update footprint. File '$TARGET' not found."
431 exit 1
432 fi
433
434 make_footprint > $PKGMK_FOOTPRINT
435 touch $TARGET
436
437 info "Footprint updated."
438}
439
440build_needed() {
441 local FILE RESULT
442
443 RESULT="yes"
444 if [ -f $TARGET ]; then
445 RESULT="no"
446 for FILE in $PKGMK_PKGFILE ${source[@]}; do
447 FILE=`get_filename $FILE`
448 if [ ! -e $FILE ] || [ ! $TARGET -nt $FILE ]; then
449 RESULT="yes"
450 break
451 fi
452 done
453 fi
454
455 echo $RESULT
456}
457
458interrupted() {
459 echo ""
460 error "Interrupted."
461
462 if [ "$PKGMK_KEEP_WORK" = "no" ]; then
463 rm -rf $PKGMK_WORK_DIR
464 fi
465
466 exit 1
467}
468
469print_help() {
470 echo "usage: `basename $PKGMK_COMMAND` [options]"
471 echo "options:"
472 echo " -i, --install build and install package"
473 echo " -u, --upgrade build and install package (as upgrade)"
474 echo " -r, --recursive search for and build packages recursively"
475 echo " -d, --download download missing source file(s)"
476 echo " -do, --download-only do not build, only download missing source file(s)"
477 echo " -utd, --up-to-date do not build, only check if package is up to date"
478 echo " -uf, --update-footprint update footprint using result from last build"
479 echo " -if, --ignore-footprint build package without checking footprint"
480 echo " -um, --update-md5sum update md5sum"
481 echo " -im, --ignore-md5sum build package without checking md5sum"
482 echo " -cm, --check-md5sum do not build, only check md5sum"
483 echo " -ns, --no-strip do not strip executable binaries or libraries"
484 echo " -f, --force build package even if it appears to be up to date"
485 echo " -c, --clean remove package and downloaded files"
486 echo " -kw, --keep-work keep temporary working directory"
487 echo " -cf, --config-file <file> use alternative configuration file"
488 echo " -v, --version print version and exit "
489 echo " -h, --help print help and exit"
490}
491
492parse_options() {
493 while [ "$1" ]; do
494 case $1 in
495 -i|--install)
496 PKGMK_INSTALL="install" ;;
497 -u|--upgrade)
498 PKGMK_INSTALL="upgrade" ;;
499 -r|--recursive)
500 PKGMK_RECURSIVE="yes" ;;
501 -d|--download)
502 PKGMK_DOWNLOAD="yes" ;;
503 -do|--download-only)
504 PKGMK_DOWNLOAD="yes"
505 PKGMK_DOWNLOAD_ONLY="yes" ;;
506 -utd|--up-to-date)
507 PKGMK_UP_TO_DATE="yes" ;;
508 -uf|--update-footprint)
509 PKGMK_UPDATE_FOOTPRINT="yes" ;;
510 -if|--ignore-footprint)
511 PKGMK_IGNORE_FOOTPRINT="yes" ;;
512 -um|--update-md5sum)
513 PKGMK_UPDATE_MD5SUM="yes" ;;
514 -im|--ignore-md5sum)
515 PKGMK_IGNORE_MD5SUM="yes" ;;
516 -cm|--check-md5sum)
517 PKGMK_CHECK_MD5SUM="yes" ;;
518 -ns|--no-strip)
519 PKGMK_NO_STRIP="yes" ;;
520 -f|--force)
521 PKGMK_FORCE="yes" ;;
522 -c|--clean)
523 PKGMK_CLEAN="yes" ;;
524 -kw|--keep-work)
525 PKGMK_KEEP_WORK="yes" ;;
526 -cf|--config-file)
527 if [ ! "$2" ]; then
528 echo "`basename $PKGMK_COMMAND`: option $1 requires an argument"
529 exit 1
530 fi
531 PKGMK_CONFFILE="$2"
532 shift ;;
533 -v|--version)
534 echo "`basename $PKGMK_COMMAND` (pkgutils) $PKGMK_VERSION"
535 exit 0 ;;
536 -h|--help)
537 print_help
538 exit 0 ;;
539 *)
540 echo "`basename $PKGMK_COMMAND`: invalid option $1"
541 exit 1 ;;
542 esac
543 shift
544 done
545}
546
547main() {
548 local FILE TARGET
549
550 parse_options "$@"
551
552 if [ "$PKGMK_RECURSIVE" = "yes" ]; then
553 recursive "$@"
554 exit 0
555 fi
556
557 for FILE in $PKGMK_PKGFILE $PKGMK_CONFFILE; do
558 if [ ! -f $FILE ]; then
559 error "File '$FILE' not found."
560 exit 1
561 fi
562 . $FILE
563 done
564
565 check_directory "$PKGMK_SOURCE_DIR"
566 check_directory "$PKGMK_PACKAGE_DIR"
567 check_directory "`dirname $PKGMK_WORK_DIR`"
568
569 check_pkgfile
570
571 TARGET="$PKGMK_PACKAGE_DIR/$name#$version-$release.pkg.tar.gz"
572
573 if [ "$PKGMK_CLEAN" = "yes" ]; then
574 clean
575 exit 0
576 fi
577
578 if [ "$PKGMK_UPDATE_FOOTPRINT" = "yes" ]; then
579 update_footprint
580 exit 0
581 fi
582
583 if [ "$PKGMK_UPDATE_MD5SUM" = "yes" ]; then
584 download_source
585 make_md5sum > $PKGMK_MD5SUM
586 info "Md5sum updated."
587 exit 0
588 fi
589
590 if [ "$PKGMK_DOWNLOAD_ONLY" = "yes" ]; then
591 download_source
592 exit 0
593 fi
594
595 if [ "$PKGMK_UP_TO_DATE" = "yes" ]; then
596 if [ "`build_needed`" = "yes" ]; then
597 info "Package '$TARGET' is not up to date."
598 else
599 info "Package '$TARGET' is up to date."
600 fi
601 exit 0
602 fi
603
604 if [ "`build_needed`" = "no" ] && [ "$PKGMK_FORCE" = "no" ] && [ "$PKGMK_CHECK_MD5SUM" = "no" ]; then
605 info "Package '$TARGET' is up to date."
606 else
607 download_source
608 build_package
609 fi
610
611 if [ "$PKGMK_INSTALL" != "no" ]; then
612 install_package
613 fi
614
615 exit 0
616}
617
618trap "interrupted" SIGHUP SIGINT SIGQUIT SIGTERM
619
620export LC_ALL=POSIX
621
622readonly PKGMK_VERSION="#VERSION#"
623readonly PKGMK_COMMAND="$0"
624readonly PKGMK_ROOT="$PWD"
625
626PKGMK_CONFFILE="/etc/pkgmk.conf"
627PKGMK_PKGFILE="Pkgfile"
628PKGMK_FOOTPRINT=".footprint"
629PKGMK_MD5SUM=".md5sum"
630PKGMK_NOSTRIP=".nostrip"
631
632PKGMK_SOURCE_DIR="$PWD"
633PKGMK_PACKAGE_DIR="$PWD"
634PKGMK_WORK_DIR="$PWD/work"
635
636PKGMK_INSTALL="no"
637PKGMK_RECURSIVE="no"
638PKGMK_DOWNLOAD="no"
639PKGMK_DOWNLOAD_ONLY="no"
640PKGMK_UP_TO_DATE="no"
641PKGMK_UPDATE_FOOTPRINT="no"
642PKGMK_IGNORE_FOOTPRINT="no"
643PKGMK_FORCE="no"
644PKGMK_KEEP_WORK="no"
645PKGMK_UPDATE_MD5SUM="no"
646PKGMK_IGNORE_MD5SUM="no"
647PKGMK_CHECK_MD5SUM="no"
648PKGMK_NO_STRIP="no"
649PKGMK_CLEAN="no"
650
651main "$@"
652
653# End of file