update Thu Apr 15 06:37:02 PDT 2010
[pkgsrc.git] / pkgtools / pkg_comp / files / pkg_comp.sh
1 #!/bin/sh
2 #
3 # $NetBSD: pkg_comp.sh,v 1.37 2010/04/15 09:42:45 jmmv Exp $
4 #
5 # pkg_comp - Build packages inside a clean chroot environment
6 # Copyright (c) 2002, 2003, 2004, 2005 Julio M. Merino Vidal <jmmv@NetBSD.org>
7 #
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions
10 # are met:
11 # 1. Redistributions of source code must retain the above copyright
12 #    notice, this list of conditions and the following disclaimer.
13 # 2. Redistributions in binary form must reproduce the above copyright
14 #    notice, this list of conditions and the following disclaimer in
15 #    the documentation and/or other materials provided with the
16 #    distribution.
17 # 3. Neither the name of author nor the names of its contributors may
18 #    be used to endorse or promote products derived from this software
19 #    without specific prior written permission.
20 #
21 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 # POSSIBILITY OF SUCH DAMAGE.
32 #
33
34 ProgName="`basename $0`"
35
36 # ----------------------------------------------------------------------
37 # Default environment values and functions
38 # ----------------------------------------------------------------------
39
40 # USE_GCC3, CFLAGS, CPPFLAGS and CXXFLAGS are ommited from _MKCONF_VARS
41 # as they require special handling.
42 _MKCONF_VARS="WRKDIR_BASENAME MKOBJDIRS BSDSRCDIR WRKOBJDIR DISTDIR PACKAGES \
43               PKG_DEVELOPER CLEANDEPENDS LOCALBASE PKG_SYSCONFBASE \
44               CFLAGS CPPFLAGS CXXFLAGS USE_AUDIT_PACKAGES PKGVULNDIR \
45               USE_XPKGWEDGE PKGSRC_COMPILER \
46               LIBKVER_STANDALONE_PREFIX PKG_DBDIR"
47
48 _TEMPLATE_VARS="DESTDIR ROOTSHELL COPYROOTCFG BUILD_TARGET DISTRIBDIR SETS \
49                 SETS_X11 REAL_SRC REAL_SRC_OPTS REAL_PKGSRC \
50                 REAL_PKGSRC_OPTS REAL_DISTFILES REAL_DISTFILES_OPTS \
51                 REAL_PACKAGES REAL_PACKAGES_OPTS REAL_PKGVULNDIR \
52                 NETBSD_RELEASE MAKEROOT_HOOKS MOUNT_HOOKS UMOUNT_HOOKS \
53                 SYNC_UMOUNT AUTO_TARGET AUTO_PACKAGES BUILD_PACKAGES \
54                 REAL_CCACHE LIBKVER_STANDALONE_PREFIX"
55
56 _BUILD_RESUME=
57
58 # env_clean
59 #
60 #   Sets all variables that may appear in the config file to the null
61 #   string, so that we know the environment is in a consistent state.
62 #
63 env_clean()
64 {
65     MKCONF_VARS=""
66     TEMPLATE_VARS=""
67     for var in ${_MKCONF_VARS} ${_TEMPLATE_VARS}; do
68         eval $var=\"\"
69     done
70 }
71
72 # env_setdefaults
73 #
74 #   Sets several reasonable defaults for many variables we will use.
75 #   Also checks for deprecated variables and warns the user about them.
76 #   To be called after reading the configuration file.
77 #
78 env_setdefaults()
79 {
80     MKCONF_VARS="$MKCONF_VARS ${_MKCONF_VARS}"
81     TEMPLATE_VARS="$TEMPLATE_VARS ${_TEMPLATE_VARS}"
82
83     # Default values for variables that will be written to mk.conf.
84     : ${WRKDIR_BASENAME:=default}
85     : ${MKOBJDIRS:=yes}
86     : ${BSDSRCDIR:=/usr/src}
87     : ${WRKOBJDIR:=/pkg_comp/obj/pkgsrc}
88     : ${DISTDIR:=/pkg_comp/distfiles}
89     : ${PACKAGES:=/pkg_comp/packages}
90     : ${PKG_DEVELOPER:=yes}
91     : ${CLEANDEPENDS:=yes}
92     : ${LOCALBASE:=/usr/pkg}
93     : ${PKG_SYSCONFBASE:=/usr/pkg/etc}
94     : ${CFLAGS:=}
95     : ${CPPFLAGS:=}
96     : ${CXXFLAGS:=}
97     : ${USE_GCC3:=no}
98     : ${USE_AUDIT_PACKAGES:=yes}
99     : ${PKGVULNDIR:=/usr/pkg/share}
100     : ${USE_XPKGWEDGE:=yes}
101     : ${PKGSRC_COMPILER:=gcc}
102     : ${PKG_DBDIR:=/var/db/pkg}
103
104     # Default values for global variables used in the script.
105     : ${DESTDIR:=/var/chroot/pkg_comp/default}
106     : ${ROOTSHELL:=/bin/ksh}
107     : ${COPYROOTCFG:=no}
108     : ${AUTO_TARGET:=package}
109     : ${BUILD_TARGET:=package}
110     : ${DISTRIBDIR:=/var/pub/NetBSD}
111     : ${SETS:=base.tgz comp.tgz etc.tgz kern-GENERIC.tgz text.tgz}
112     : ${SETS_X11:=xbase.tgz xcomp.tgz xetc.tgz xfont.tgz xserver.tgz}
113     : ${REAL_SRC:=/usr/src}
114     : ${REAL_SRC_OPTS:=-t null -o ro}
115     : ${REAL_PKGSRC:=/usr/pkgsrc}
116     : ${REAL_PKGSRC_OPTS:=-t null -o ro}
117     : ${REAL_DISTFILES:=/usr/pkgsrc/distfiles}
118     : ${REAL_DISTFILES_OPTS:=-t null -o rw}
119     : ${REAL_PACKAGES:=/usr/pkgsrc/packages}
120     : ${REAL_PACKAGES_OPTS:=-t null -o rw}
121     : ${REAL_PKGVULNDIR:=/usr/pkgsrc/distfiles}
122     : ${NETBSD_RELEASE:=no}
123     : ${LIBKVER_STANDALONE_PREFIX:=/libkver}
124     : ${MAKEROOT_HOOKS:=}
125     : ${MOUNT_HOOKS:=}
126     : ${UMOUNT_HOOKS:=}
127     : ${SYNC_UMOUNT:=no}
128     : ${REAL_CCACHE:=}
129
130     if [ -n "${MAKE_PACKAGES}" ]; then
131         warn "MAKE_PACKAGES is deprecated; use {AUTO,BUILD}_PACKAGES instead."
132         : ${AUTO_PACKAGES:=${MAKE_PACKAGES}}
133         : ${BUILD_PACKAGES:=${MAKE_PACKAGES}}
134     fi
135
136     if [ -n "${MOUNT_SCRIPT}" ]; then
137         warn "MOUNT_SCRIPT is deprecated; use MOUNT_HOOKS instead."
138         : ${MOUNT_HOOKS:=${MOUNT_SCRIPT}}
139     fi
140
141     if [ -n "${UMOUNT_SCRIPT}" ]; then
142         warn "UMOUNT_SCRIPT is deprecated; use UMOUNT_HOOKS instead."
143         : ${UMOUNT_HOOKS:=${UMOUNT_SCRIPT}}
144     fi
145 }
146
147 # ----------------------------------------------------------------------
148 # Misc functions
149 # ----------------------------------------------------------------------
150
151 # err msg
152 #
153 #   Shows the given error message and exit.
154 #
155 err()
156 {
157     echo "$ProgName: $1" 1>&2
158     exit 1
159 }
160
161 # warn msg
162 #
163 #   Shows the given warning message.
164 #
165 warn()
166 {
167     echo "$ProgName: $1" 1>&2
168 }
169
170 # usage
171 #
172 #   Shows an usage message and exits.
173 #
174 usage()
175 {
176     echo "usage: $ProgName [-(c|C) conf_file] [-Nn] target [pkg_names]" 1>&2
177     exit 1
178 }
179
180 # copy_vulnerabilities
181 #
182 #   If USE_AUDIT_PACKAGES is set to 'yes', this function copies the
183 #   system-wide pkg-vulnerabilities file inside the sandbox.
184 #
185 copy_vulnerabilities()
186 {
187     if [ "$USE_AUDIT_PACKAGES" = "yes" ]; then
188         echo "PKG_COMP ==> Installing new \`pkg-vulnerabilities' file"
189         if [ ! -f "$REAL_PKGVULNDIR/pkg-vulnerabilities" ]; then
190             echo "$REAL_PKGVULNDIR/pkg-vulnerabilities not found."
191         else
192             mkdir -p $DESTDIR/$PKGVULNDIR
193             cp $REAL_PKGVULNDIR/pkg-vulnerabilities $DESTDIR/$PKGVULNDIR
194         fi
195     fi
196 }
197
198 # init_script filename
199 #
200 #   Create a script that will be used within the sandbox and write some
201 #   common content to it.
202 #
203 init_script()
204 {
205     rm -f $1
206     cat >$1 <<EOF
207 #!/bin/sh
208 # Generated by pkg_comp on `date`
209
210 if [ -f ${LIBKVER_STANDALONE_PREFIX}/lib/libkver.so ]; then
211     LD_PRELOAD=${LIBKVER_STANDALONE_PREFIX}/lib/libkver.so; export LD_PRELOAD
212 fi
213
214 EOF
215 }
216
217 # ----------------------------------------------------------------------
218 # Filesystem functions
219 # ----------------------------------------------------------------------
220
221 # fsmount
222 #
223 #   Mounts all sandboxed filesystems, if they are not mounted yet.
224 #
225 fsmount()
226 {
227     echo "PKG_COMP ==> Mounting sandboxed filesystems"
228     if [ -f $fsstate ]; then
229         count=`cat $fsstate`
230         count=$(($count + 1))
231         echo "$count" > $fsstate
232         echo "Already mounted (maybe by another pkg_comp process?)"
233         return
234     else
235         echo "1" > $fsstate
236     fi
237
238     if [ -n "$REAL_SRC" ]; then
239         if [ ! -d "$REAL_SRC" ]; then
240             echo " failed."
241             fsumount
242             err "REAL_SRC $REAL_SRC disappeared"
243         fi
244         mount $REAL_SRC_OPTS $REAL_SRC $DESTDIR/usr/src
245     fi
246
247     if [ -n "$REAL_PKGSRC" ]; then
248         if [ ! -d "$REAL_PKGSRC" ]; then
249             echo " failed."
250             fsumount
251             err "REAL_PKGSRC $REAL_PKGSRC disappeared"
252         fi
253         mount $REAL_PKGSRC_OPTS $REAL_PKGSRC $DESTDIR/usr/pkgsrc
254     fi
255
256     if [ -n "$REAL_DISTFILES" ]; then
257         if [ ! -d "$REAL_DISTFILES" ]; then
258             echo " failed."
259             fsumount
260             err "REAL_DISTFILES $REAL_DISTFILES disappeared"
261         fi
262         mount $REAL_DISTFILES_OPTS $REAL_DISTFILES $DESTDIR/pkg_comp/distfiles
263     fi
264
265     if [ -n "$REAL_PACKAGES" ]; then
266         if [ ! -d "$REAL_PACKAGES" ]; then
267             echo " failed."
268             fsumount
269             err "REAL_PACKAGES $REAL_PACKAGES disappeared"
270         fi
271         mount $REAL_PACKAGES_OPTS $REAL_PACKAGES $DESTDIR/pkg_comp/packages
272     fi
273
274     if [ -n "${REAL_CCACHE}" ]; then
275         if [ ! -d "${REAL_CCACHE}" ]; then
276             echo " failed."
277             fsumount
278             err "REAL_CCACHE ${REAL_CCACHE} disappeared"
279         fi
280         mount -t null -o rw ${REAL_CCACHE} ${DESTDIR}/pkg_comp/ccache
281     fi
282
283     touch $fsstate
284
285     if [ -n "${MOUNT_HOOKS}" ]; then
286         echo "Executing mount hooks."
287         for h in ${MOUNT_HOOKS}; do
288             ${h} ${DESTDIR} mount
289         done
290     fi
291 }
292
293 # fsumount
294 #
295 #   Unmounts all sandboxed filesystems, if they are not in use any more.
296 #
297 fsumount()
298 {
299     echo "PKG_COMP ==> Unmounting sandboxed filesystems"
300
301     if [ ! -f $fsstate ]; then
302         echo "None mounted."
303         return
304     fi
305
306     count=`cat $fsstate`
307     if [ $count -gt 1 ]; then
308         count=$(($count - 1))
309         echo "$count" > $fsstate
310         echo "Still in use (maybe by another pkg_comp process?)"
311         return
312     fi
313
314     if [ -n "${UMOUNT_HOOKS}" ]; then
315         echo "Executing umount hooks."
316         for h in ${UMOUNT_HOOKS}; do
317             ${h} ${DESTDIR} umount
318         done
319     fi
320
321     fsfailed=no
322
323     if [ -n "$REAL_SRC" -a -d "$REAL_SRC" ]; then
324         umount $DESTDIR/usr/src || fsfailed=yes
325     fi
326
327     if [ -n "$REAL_PKGSRC" -a -d "$REAL_PKGSRC" ]; then
328         umount $DESTDIR/usr/pkgsrc || fsfailed=yes
329     fi
330
331     if [ -n "$REAL_DISTFILES" -a -d "$REAL_DISTFILES" ]; then
332         umount $DESTDIR/pkg_comp/distfiles || fsfailed=yes
333     fi
334
335     if [ -n "$REAL_PACKAGES" -a -d "$REAL_PACKAGES" ]; then
336         umount $DESTDIR/pkg_comp/packages || fsfailed=yes
337     fi
338
339     if [ -n "${REAL_CCACHE}" -a -d "${REAL_CCACHE}" ]; then
340         umount ${DESTDIR}/pkg_comp/ccache || fsfailed=yes
341     fi
342
343     if [ "$SYNC_UMOUNT" != "no" ]; then
344         printf "Syncing: 1"
345         sync ; sleep 1
346         printf " 2"
347         sync ; sleep 1
348         printf " 3"
349         sync ; sleep 1
350         echo " done."
351     fi
352
353     if [ "$fsfailed" = "yes" ]; then
354         err "FATAL: failed to umount all filesystems"
355     else
356         rm $fsstate
357     fi
358 }
359
360 # ----------------------------------------------------------------------
361 # maketemplate target
362 # ----------------------------------------------------------------------
363
364 # pkg_maketemplate
365 #
366 #   Generates a sample configuration file based on the list of variables
367 #   given in TEMPLATE_VARS and MKCONF_VARS.
368 #
369 pkg_maketemplate()
370 {
371     if [ -f "$conffile" ]; then
372         err "$conffile already exists"
373     fi
374
375     mkdir -p $confdir
376     cat > $conffile <<EOF
377 # -*- sh -*-
378 #
379 # pkg_comp - configuration file
380 # See pkg_comp(8) for a detailed description of each variable.
381 #
382
383 EOF
384
385     echo "# Variables used internally by pkg_comp." >> $conffile
386     for var in `echo $TEMPLATE_VARS | tr ' ' '\n' | sort`; do
387         eval val=\""\$$var"\"
388         echo "$var=\"$val\"" >> $conffile
389     done
390
391     echo >> $conffile
392     echo "# Default variables written to the generated mk.conf." >> $conffile
393     for var in `echo $MKCONF_VARS | tr ' ' '\n' | sort`; do
394         eval val=\""\$$var"\"
395         echo "$var=\"$val\"" >> $conffile
396     done
397
398     echo "pkg_comp: $conffile created.  Edit the file by hand now."
399 }
400
401 # ----------------------------------------------------------------------
402 # makeroot target
403 # ----------------------------------------------------------------------
404
405 # pkg_makeroot
406 #
407 #   The 'makeroot' target.  This creates a new sandbox and then issues
408 #   some stuff to be called only when using this specific target.
409 #
410 pkg_makeroot()
411 {
412     makeroot
413
414     [ "$nflag" = "no" -a -n "$INSTALL_PACKAGES" ] &&
415         pkg_install $INSTALL_PACKAGES
416
417     [ "$nflag" = "no" -a -n "$BUILD_PACKAGES" ] &&
418         build_and_install $BUILD_PACKAGES
419 }
420
421 # makeroot
422 #
423 #   Creates a new sandbox.  This is independent from 'makeroot' and
424 #   'auto' targets.
425 #
426 makeroot()
427 {
428     # Check for directories that will be null mounted.
429     if [ -n "$REAL_SRC" -a ! -d "$REAL_SRC" ]; then
430         err "REAL_SRC $REAL_SRC does not exist"
431     fi
432
433     if [ -n "$REAL_PKGSRC" -a ! -d "$REAL_PKGSRC" ]; then
434         err "REAL_PKGSRC $REAL_PKGSRC does not exist"
435     fi
436
437     if [ -n "$REAL_DISTFILES" -a ! -d "$REAL_DISTFILES" ]; then
438         err "REAL_DISTFILES $REAL_DISTFILES does not exist"
439     fi
440
441     if [ -n "$REAL_PACKAGES" -a ! -d "$REAL_PACKAGES" ]; then
442         err "REAL_PACKAGES $REAL_PACKAGES does not exist"
443     fi
444
445     if echo ${PKGSRC_COMPILER} | grep ccache >/dev/null 2>&1 && \
446         [ -z "${REAL_CCACHE}" ]; then
447         warn "PKGSRC_COMPILER contains 'ccache' but REAL_CCACHE is unset"
448     elif [ -n "${REAL_CCACHE}" -a ! -d "${REAL_CCACHE}" ]; then
449         err "REAL_CCACHE ${REAL_CCACHE} does not exist"
450     fi
451
452     # Check for required directories.
453     if [ ! -d $DISTRIBDIR ]; then
454         err "DISTRIBDIR $DISTRIBDIR does not exist"
455     fi
456
457     if [ -d $DESTDIR ]; then
458         err "DESTDIR $DESTDIR already exists"
459     fi
460
461     if [ "$SETS_X11" = "no" ]; then
462         allsets="$SETS"
463     else
464         allsets="$SETS $SETS_X11"
465     fi
466
467     for s in $allsets; do
468         if [ ! -f $DISTRIBDIR/binary/sets/$s ]; then
469             err "$DISTRIBDIR/binary/sets/$s does not exist"
470         fi
471     done
472
473     echo "PKG_COMP ==> Creating sandbox \`${DESTDIR}'"
474
475     mkdir -p $DESTDIR
476     cd $DESTDIR
477
478     for s in $allsets; do
479         echo "Extracting $s..."
480         tar xzpf $DISTRIBDIR/binary/sets/$s
481     done
482
483     [ -f ${DESTDIR}/netbsd ] || touch ${DESTDIR}/netbsd
484
485     echo "Making device nodes..."
486     cd $DESTDIR/dev
487     ./MAKEDEV all
488     cd $DESTDIR
489
490     echo "Setting root's environment..."
491     chroot $DESTDIR chpass -s $ROOTSHELL
492     if [ "$COPYROOTCFG" = "yes" ]; then
493         cp /root/.* $DESTDIR/root >/dev/null 2>&1
494     fi
495     if [ -n "${REAL_CCACHE}" ]; then
496         # This is a workaround for older versions of ccache.mk that do not
497         # pass the CCACHE_DIR variable down to ccache.
498         ( cd ${DESTDIR}/root && ln -fs ../pkg_comp/ccache .ccache )
499     fi
500
501     echo "Setting up initial configuration..."
502
503     mkdir -p $DESTDIR/usr/src
504     mkdir -p $DESTDIR/usr/pkgsrc
505     mkdir -p $DESTDIR/pkg_comp/distfiles
506     mkdir -p $DESTDIR/pkg_comp/packages
507     mkdir -p $DESTDIR/pkg_comp/tmp
508     mkdir -p $DESTDIR/pkg_comp/obj/pkgsrc
509     [ -n "${REAL_CCACHE}" ] && mkdir -p ${DESTDIR}/pkg_comp/ccache
510     ( cd $DESTDIR && ln -s pkg_comp p )
511
512     # Set sh configuration
513     echo "umask 022" >> $DESTDIR/etc/profile
514     echo "ENV=/etc/shrc" >> $DESTDIR/etc/profile
515     echo "export PS1=\"pkg_comp:`basename $conffile`# \"" >> $DESTDIR/etc/shrc
516     echo "set -o emacs" >> $DESTDIR/etc/shrc
517     echo "export PKG_DBDIR=\"${PKG_DBDIR}\"" >> ${DESTDIR}/etc/shrc
518
519     # Set csh configuration
520     echo "umask 022" >> $DESTDIR/etc/csh.login
521     echo "set prompt=\"pkg_comp:`basename $conffile`# \"" >> $DESTDIR/etc/csh.login
522     echo "set prompt=\"pkg_comp:`basename $conffile`# \"" >> $DESTDIR/etc/csh.cshrc
523     echo "setenv PKG_DBDIR \"${PKG_DBDIR}\"" >> ${DESTDIR}/etc/csh.cshrc
524
525     cp /etc/resolv.conf $DESTDIR/etc/resolv.conf
526
527     makeroot_mkconf
528
529     echo "PKG_DBDIR=${PKG_DBDIR}" >> ${DESTDIR}/etc/pkg_install.conf
530
531     # From now on, filesystems may be mounted, so we need to trap
532     # signals to umount them.
533     trap "echo \"*** Process aborted ***\" ; fsumount ; exit 1" INT QUIT
534
535     makeroot_libkver
536     [ "$Nflag" = "no" ] && makeroot_digest
537
538     if [ "$USE_GCC3" = "yes" -a "$Nflag" = "no" ]; then
539         if [ -z "`echo $BUILD_PACKAGES $INSTALL_PACKAGES | grep gcc3`" ]; then
540             AVOID_GCC3=yes build_and_install lang/gcc3
541         fi
542     fi
543
544     makeroot_x11
545
546     if [ -n "${MAKEROOT_HOOKS}" ]; then
547         echo "Executing makeroot hooks."
548         for h in ${MAKEROOT_HOOKS}; do
549             ${h} ${DESTDIR} makeroot
550         done
551     fi
552 }
553
554 # makeroot_mkconf
555 #
556 #   Generates a mk.conf file inside the sandbox, based on the content
557 #   of MKCONF_VARS and EXTRAMK.  Also handles some special stuff.
558 #
559 makeroot_mkconf()
560 {
561     file="$DESTDIR/etc/mk.conf"
562
563     cat >> $file <<EOF
564 #
565 # /etc/mk.conf
566 # File automatically generated by pkg_comp on `date`
567 #
568 .ifdef BSD_PKG_MK
569
570 EOF
571
572     for var in $MKCONF_VARS; do
573         eval val=\""\$$var"\"
574         echo "$var ?= $val" >> $file
575     done
576
577     if [ -n "$EXTRAMK" ]; then
578         for mkfile in $EXTRAMK; do
579             if [ ! -f "$mkfile" ]; then
580                 err "Cannot find $mkfile"
581             else
582                 cat $mkfile >> $file
583             fi
584         done
585     fi
586
587     if [ "$USE_AUDIT_PACKAGES" != "yes" ]; then
588         echo "ALLOW_VULNERABLE_PACKAGES ?= YES" >> $file
589     fi
590
591     if [ "$USE_GCC3" = "yes" ]; then
592         cat >>$file <<EOF
593 .if !defined(AVOID_GCC3) && exists(/usr/pkg/share/examples/gcc-3.3/mk.conf)
594 USE_GCC3 = yes
595 CFLAGS += $CFLAGS
596 CPPFLAGS += $CPPFLAGS
597 CXXFLAGS += $CXXFLAGS
598 .include "/usr/pkg/share/examples/gcc-3.3/mk.conf"
599 .endif
600 EOF
601     else
602         cat >>$file <<EOF
603 CFLAGS += $CFLAGS
604 CPPFLAGS += $CPPFLAGS
605 CXXFLAGS += $CXXFLAGS
606
607 .endif # BSD_PKG_MK
608 EOF
609     fi
610 }
611
612 # makeroot_digest
613 #
614 #   Ensure digest is always installed, specially because PKGSRC_COMPILER
615 #   may contain 'ccache' or 'distcc'.
616 #
617 makeroot_digest()
618 {
619     ( PKGSRC_COMPILER=gcc; export PKGSRC_COMPILER; \
620       build_and_install pkgtools/digest )
621 }
622
623 # makeroot_libkver
624 #
625 #   If NETBSD_RELEASE is set to a version string, installs libkver
626 #   inside the sandbox and configures it.
627 #
628 makeroot_libkver()
629 {
630     local prefix script statfile
631
632     if [ "$NETBSD_RELEASE" != "no" ]; then
633         _BUILD_TARGET="$BUILD_TARGET"
634         BUILD_TARGET="standalone-install"
635         build_and_install pkgtools/libkver
636         BUILD_TARGET="$_BUILD_TARGET"
637         echo "LD_PRELOAD=${LIBKVER_STANDALONE_PREFIX}/lib/libkver.so; export LD_PRELOAD" >> $DESTDIR/etc/shrc
638         echo "setenv LD_PRELOAD ${LIBKVER_STANDALONE_PREFIX}/lib/libkver.so" >> $DESTDIR/etc/csh.login
639         echo "setenv LD_PRELOAD ${LIBKVER_STANDALONE_PREFIX}/lib/libkver.so" >> $DESTDIR/etc/csh.cshrc
640         ln -s "$NETBSD_RELEASE" $DESTDIR/libkver_osrelease
641     fi
642 }
643
644 # makeroot_x11
645 #
646 #   If X11 is enabled, installs x11-links inside the sandbox.
647 #   If USE_XPKGWEDGE is yes, configures xpkgwedge too (but does not
648 #   install it; pkgsrc will take care of that when needed).
649 #
650 makeroot_x11()
651 {
652     if [ "$SETS_X11" != "no" ]; then
653         if [ "$USE_XPKGWEDGE" = "yes" ]; then
654             echo "export XAPPLRESDIR=${LOCALBASE}/lib/X11/app-defaults" >> $DESTDIR/etc/profile
655             echo "setenv XAPPLRESDIR ${LOCALBASE}/lib/X11/app-defaults" >> $DESTDIR/etc/csh.login
656         fi
657         [ "$Nflag" = "no" ] && build_and_install pkgtools/x11-links
658     fi
659 }
660
661 # ----------------------------------------------------------------------
662 # auto target
663 # ----------------------------------------------------------------------
664
665 # pkg_auto pkgs
666 #
667 #   The 'auto' target.
668 #
669 pkg_auto()
670 {
671     local pkgs rfile target
672
673     pkgs="${*:-${AUTO_PACKAGES}}"
674     rfile=${DESTDIR}/pkg_comp/tmp/auto.list
675     target="${AUTO_TARGET}"
676
677     [ -z "${REAL_PACKAGES}" ] && err "this is useless without REAL_PACKAGES"
678     [ -z "${pkgs}" ] &&
679         err "this is useless without AUTO_PACKAGES nor package names"
680
681     if [ "$1" = resume ]; then
682         [ -f ${rfile} ] || err "there is no auto build to resume"
683         pkgs=`cat ${rfile}`
684     elif [ -f ${rfile} ]; then
685         err "there is an stopped auto build; removeroot first or resume it"
686     else
687         makeroot
688
689         [ "$nflag" = "no" -a -n "$INSTALL_PACKAGES" ] &&
690             pkg_install $INSTALL_PACKAGES
691
692         echo ${pkgs} | tr ' ' '\n' > ${rfile}
693     fi
694
695     checkroot
696     _BUILD_RESUME=${rfile} BUILD_TARGET=${target} pkg_build ${pkgs}
697     pkg_removeroot
698 }
699
700 # ----------------------------------------------------------------------
701 # build target
702 # ----------------------------------------------------------------------
703
704 # pkg_build pkgs
705 #
706 #   The build target.  Also used as a helper function within this script
707 #   to build several packages when needed.
708 #
709 pkg_build()
710 {
711     local failed invalid p pkgs script statfile
712
713     pkgs="$*"
714
715     # Check if all packages exist
716     invalid=""
717     for p in $pkgs; do
718         if [ ! -d $REAL_PKGSRC/$p ]; then
719             invalid="$invalid $p"
720         fi
721     done
722     if [ -n "$invalid" ]; then
723         err "invalid packages:$invalid"
724     fi
725
726     # Build them
727     fsmount
728     check_pkg_install    # executes copy_vulnerabilities too
729     failed=""
730     for p in $pkgs; do
731         echo "PKG_COMP ==> Building and installing $p"
732         prefix=$(mktemp $DESTDIR/pkg_comp/tmp/pkg_comp-XXXXXX)
733         rm $prefix
734         script="$prefix.sh"
735         statfile="$prefix.stat"
736         init_script $script
737         cat >> $script <<EOF
738 cd /usr/pkgsrc/$p
739 make $BUILD_TARGET
740 if [ \$? != 0 ]; then
741     touch /pkg_comp/tmp/`basename $statfile`
742 fi
743 make clean
744 EOF
745         chmod +x $script
746         chroot $DESTDIR /pkg_comp/tmp/`basename $script`
747         rm $script
748         if [ -f $statfile ]; then
749             failed="$failed $p"
750             rm $statfile
751         elif [ -n "${_BUILD_RESUME}" ]; then
752             grep -v "^${p}\$" < ${_BUILD_RESUME} > ${_BUILD_RESUME}.new
753             mv ${_BUILD_RESUME}.new ${_BUILD_RESUME}
754         fi
755     done
756     fsumount
757     if [ -n "$failed" ]; then
758         echo "PKG_COMP ==> Build error summary"
759         echo "Build failed for:"
760         for p in $failed; do
761             echo "    $p"
762         done
763     fi
764 }
765
766 # check_pkg_install
767 #
768 #   Ensure that the version of pkg_install inside the sandbox is new
769 #   enough to work with pkgsrc.  If not, rebuild it.
770 #
771 check_pkg_install()
772 {
773     local script
774
775     copy_vulnerabilities
776
777     # We assume filesystems are mounted!
778
779     echo "PKG_COMP ==> Checking if pkg_install is up to date"
780     script=$(mktemp $DESTDIR/pkg_comp/tmp/pkg_comp-XXXXXX).sh
781     init_script $script
782     cat >> $script <<EOF
783 cd /usr/pkgsrc/pkgtools/pkg_comp
784 fail=\$(make show-var VARNAME=PKG_FAIL_REASON)
785 if echo \$fail | grep "package tools installed on this system are out of date" >/dev/null; then
786     echo "PKG_COMP ==> pkg_install is out of date; rebuilding"
787     cd /usr/pkgsrc/pkgtools/pkg_install
788     make && make install && make clean
789 fi
790 EOF
791     chmod +x $script
792     chroot $DESTDIR /pkg_comp/tmp/`basename $script`
793     rm $script
794 }
795
796 # build_and_install pkg
797 #
798 #   Builds a package and ensures it gets installed.  The use of destdir to
799 #   build packages may cause a package to get built but not installed,
800 #   which is not OK for this script.  This is for internal usage only.
801 #
802 build_and_install()
803 {
804     pkg=${1}
805     fsmount
806     if pkg_build ${pkg}; then
807         script=$(mktemp ${DESTDIR}/pkg_comp/tmp/pkg_comp-XXXXXX).sh
808         init_script ${script}
809         cat >>${script} <<EOF
810 cd /usr/pkgsrc/${pkg}
811 pkgname=\$(make show-var VARNAME=PKGNAME)
812 if pkg_info -E \${pkgname} 2>/dev/null; then
813     :
814 else
815     echo "PKG_COMP ==> Forcing installation of \${pkgname}"
816     cd /pkg_comp/packages/All
817     pkg_add \${pkgname}
818 fi
819 EOF
820         chmod +x ${script}
821         chroot ${DESTDIR} /pkg_comp/tmp/$(basename ${script})
822         rm ${script}
823     fi
824     fsumount
825 }
826
827 # ----------------------------------------------------------------------
828 # install target
829 # ----------------------------------------------------------------------
830
831 # pkg_install pkgs
832 #
833 #   The install target.  Also used as a helper function within this
834 #   script to install several packages when needed.
835 #
836 pkg_install()
837 {
838     local failed pkgs stat
839
840     pkgs="$*"
841
842     [ -z "$REAL_PACKAGES" ] && err "REAL_PACKAGES is not set"
843
844     copy_vulnerabilities
845
846     fsmount
847     failed=""
848     for p in $(cd ${REAL_PACKAGES}/All && echo ${pkgs}); do
849         echo "PKG_COMP ==> Installing binary package: $p"
850         stat=$DESTDIR/pkg_comp/tmp/install.sh
851         init_script $stat
852         cat >> $stat <<EOF
853 cd /pkg_comp/packages/All
854 pkg_add $p
855 EOF
856         chmod +x $stat
857         chroot $DESTDIR /pkg_comp/tmp/install.sh || failed="$failed $p"
858         rm $stat
859     done
860     fsumount
861     [ -n "$failed" ] && echo "Installation failed for:$failed"
862 }
863
864 # ----------------------------------------------------------------------
865 # chroot target
866 # ----------------------------------------------------------------------
867
868 # pkg_chroot cmd
869 #
870 #   The 'chroot' target.
871 #
872 pkg_chroot()
873 {
874     local prefix script exitstatus
875
876     [ -d $DESTDIR ] || err "$DESTDIR does not exist"
877
878     copy_vulnerabilities
879
880     fsmount
881     echo "PKG_COMP ==> Entering sandbox \`$DESTDIR'"
882     prefix=$(mktemp $DESTDIR/pkg_comp/tmp/pkg_comp-XXXXXX)
883     rm $prefix
884     script="$prefix.sh"
885     init_script $script
886     if [ $# -eq 0 ]; then
887         cat >> $script <<EOF
888 ENV=/etc/shrc $ROOTSHELL
889 EOF
890     else
891         cat >> $script <<EOF
892 $*
893 EOF
894     fi
895     chmod +x $script
896     ENV=/etc/shrc chroot $DESTDIR /pkg_comp/tmp/`basename $script`
897     exitstatus=$?
898     echo
899     rm $script
900     fsumount
901     return $exitstatus
902 }
903
904 # ----------------------------------------------------------------------
905 # removeroot target
906 # ----------------------------------------------------------------------
907
908 # pkg_removeroot
909 #
910 #   The 'removeroot' target.
911 #
912 pkg_removeroot()
913 {
914     [ -f $fsstate ] && err "filesystems may still be mounted; cannot remove"
915     echo "PKG_COMP ==> Removing sandbox \`${DESTDIR}'"
916     rm -rf $DESTDIR
917 }
918
919 # ----------------------------------------------------------------------
920 # Main program
921 # ----------------------------------------------------------------------
922
923 confdir="$HOME/pkg_comp"
924
925 # Parse options
926 args=`getopt c:C:nN $*`
927 if [ $? != 0 ]; then
928     usage
929 fi
930 set -- $args
931 conffile=
932 nflag=no
933 Nflag=no
934 while [ $# -gt 0 ]; do
935     case "$1" in
936         -c)
937             [ -n "$conffile" ] && usage
938             conffile="$confdir/$2.conf"
939             shift
940             ;;
941         -C)
942             [ -n "$conffile" ] && usage
943             conffile="$2"
944             shift
945             ;;
946         -n)
947             nflag=yes
948             ;;
949         -N)
950             nflag=yes
951             Nflag=yes
952             ;;
953         --)
954             shift; break
955             ;;
956     esac
957     shift
958 done
959
960 if [ $# -lt 1 ]; then
961     usage
962 fi
963
964 if [ -z "$conffile" ]; then
965     conffile="$confdir/default.conf"
966 fi
967
968 case "$1" in
969     pkg_*)
970         target=chroot
971         ;;
972     *)
973         target="$1"
974         shift
975         ;;
976 esac
977 args="$*"
978
979 # readconf
980 #
981 #   Reads the configuration file and ensures that the environment is in
982 #   a consistent state.
983 #
984 readconf()
985 {
986     if [ -f $conffile ]; then
987         [ `id -u` -ne 0 ] && err "must be run as root"
988         env_clean
989         . $conffile
990         env_setdefaults
991     else
992         err "$conffile does not exist"
993     fi
994
995     fsstate="$DESTDIR/pkg_comp/tmp/mount.stat"
996 }
997
998 # checkroot
999 #
1000 #   Checks that the sandbox is initialized, that it's a valid directory
1001 #   and configures a signal trap for SIGINT and SIGQUIT.
1002 #
1003 checkroot()
1004 {
1005     if [ ! -d "$DESTDIR" ]; then
1006         err "sandbox not initialized; use makeroot first."
1007     fi
1008     if [ "$DESTDIR" = "/" ]; then
1009         err "DESTDIR cannot be /"
1010     fi
1011
1012     # From now on, filesystems may be mounted, so we need to trap
1013     # signals to umount them.
1014     trap "echo \"*** Process aborted ***\" ; fsumount ; exit 1" INT QUIT
1015 }
1016
1017 case "$target" in
1018     maketemplate)
1019         env_clean
1020         env_setdefaults
1021         pkg_maketemplate
1022         exit 0
1023         ;;
1024     makeroot)
1025         readconf
1026         pkg_makeroot
1027         exit 0
1028         ;;
1029     build)
1030         readconf
1031         checkroot
1032         pkg_build $args
1033         exit 0
1034         ;;
1035     install)
1036         readconf
1037         checkroot
1038         pkg_install $args
1039         exit 0
1040         ;;
1041     chroot)
1042         readconf
1043         checkroot
1044         pkg_chroot $args
1045         exit $?
1046         ;;
1047     removeroot)
1048         readconf
1049         checkroot
1050         pkg_removeroot
1051         ;;
1052     auto)
1053         readconf
1054         pkg_auto $args
1055         ;;
1056     *)
1057         err "unknown target \`$target'"
1058         ;;
1059 esac
1060
1061 exit 0
1062
1063 # vim: expandtab:softtabstop=4:shiftwidth=4