CRUX-ARM : Home

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