3 # Load shlib and modules
4 _root="$(dirname "${0}")"; . "${_root}/lib/env.sh"
8 [ "${*}" ] && printf "%s\n\n" "${*}"
9 echo "Usage: $(basename "${0}") -m <makeopts> -a <arch> -c <conf> <target, ...>"
10 echo " -m <makeopts> Provide additional flags to make"
11 echo " -a <arch> World architecture (i386, amd64)"
12 echo " -c <conf> World configuration (in worlds/<arch>/<conf>)"
15 echo "If, for some reason, you wish to spread out builds across multiple"
16 echo "invocations, these might come in handy:"
17 echo " -p Prepare chroot environment"
18 echo " -d Don't prepare or clean up chroot during run"
19 echo " -q Clean up chroot environment"
21 echo "Available make targets:"
22 for make_tgt in ${make_tgts}
29 # Prepare chroot for build
31 [ "${CHROOT_DIRTY}" -a ! "${CHROOT_PREPARE}" ] && return 0
32 # Verify environment sanity
33 [ -d "${build}" ] && omg "${build}: directory exists; purging" && cleanup
34 mount | grep -q "${build}" && wtf "Stuff is mounted under ${build}; cannot continue"
35 ls -1 "${seed}"/base.?? >/dev/null 2>&1 || wtf "Populate seed directory ${seed} first"
36 [ -f /usr/src/sys/conf/newvers.sh ] || wtf "Need sources in /usr/src to build"
38 # Cleanup trap here, so that an abort during prepare can clean up properly
39 trap "cleanup" exit hup int term kill
41 meh "Preparing build chroot"
42 [ -d "${build}" ] && wtf "${build}: directory exists"
43 mkdir -p "${build}" || wtf
44 cat "${seed}"/base.?? | tar xCf "${build}" - || wtf
45 mkdir -p "${build}/usr/obj" || wtf
47 meh "Mounting chroot filesystems"
48 mkdir -p "${world}/obj"
49 mkdir -p "${world}/root"
50 mount -t devfs devfs "${build}/dev" || wtf
51 # Mount /usr/src as a union, so that changes to it will not affect the underlying tree
52 # unionfs suffers from deadlocks; don't use it
53 mount -t nullfs -r /usr/src "${build}/usr/src" || wtf
54 mount -t nullfs "${world}/obj" "${build}/usr/obj" || wtf
55 mount -t nullfs "${world}/root" "${build}/mnt" || wtf
57 if [ -d "${world}/config" ]
59 meh "Installing build-time configuration"
60 [ -f "${world}/config/${CONF}" ] && cp "${world}/config/${CONF}" "/usr/src/sys/${ARCH}/conf/"
61 [ -f "${world}/config/make.conf" ] && cp "${world}/config/make.conf" "${build}/etc/"
62 [ -f "${world}/config/src.conf" ] && cp "${world}/config/src.conf" "${build}/etc/"
69 [ "${CHROOT_DIRTY}" -a ! "${CHROOT_CLEAN}" ] && return 0
71 umount -f "${build}/mnt"
72 umount -f "${build}/usr/obj"
73 umount -f "${build}/usr/src"
74 umount -f "${build}/dev"
75 mount | grep -q "${build}/" && wtf "Stuff is still mounted under ${build}; not removing"
76 chflags -R noschg "${build}"
78 trap "" exit hup int term kill
82 # Root directory of makeworld
83 ROOT="$(realpath "$(dirname "${0}")/..")"
86 WORLDS="${ROOT}/worlds"
88 # Compute make -j<cpus*2>
89 make_cpus="$(sysctl -n hw.ncpu)"
90 make_jobs="$(( ${make_cpus} * 2 ))"
91 make_tgts="buildworld buildkernel distrib-dirs installworld installkernel distribution"
96 MAKEOPTS="-j${make_jobs}"
98 while getopts "m:a:c:hpdq" opt
101 m) MAKEOPTS="${MAKEOPTS} ${OPTARG}" ;;
102 a) ARCH="${OPTARG}" ;;
103 c) CONF="${OPTARG}" ;;
104 p) CHROOT_PREPARE="TRUE" ;;
105 d) CHROOT_DIRTY="TRUE" ;;
106 q) CHROOT_CLEAN="TRUE" ;;
108 [?]) pebkac "Unrecognized option ${opt}" ;;
111 shift $(( $OPTIND - 1 ))
113 # Should be root after this point
116 # Build make target sequence
117 sequence="${*:-${make_tgts}}"
119 # Target world directory
120 world="${WORLDS}/${ARCH}/${CONF}"
121 # Source chroot seed directory
122 seed="${ROOT}/seed/base/$(uname -m)"
123 # Root directory for chroot
124 build="${world}/chroot"
126 # Environment for chroot build
130 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
134 date="$(date +%Y%m%d)"
136 # Check if target config exists
137 [ -d "${world}" ] || wtf "${ARCH}/${CONF} doesn't exist"
139 if [ "${CHROOT_PREPARE}" ]
143 meh "Chroot prepared"
147 if [ "${CHROOT_CLEAN}" ]
154 meh "Making world for ${ARCH}/${CONF}"
159 meh "Config: ${ARCH}/${CONF}"
160 meh "Builddir: ${build}"
161 meh "make ${MAKEOPTS}"
162 meh "DESTDIR=${world}/root"
164 for step in ${sequence}
166 meh "==> Step: ${step}"
167 script "${world}/${date}-${step}.log" env -i ${env} chroot "${build}" sh -c \
168 "cd /usr/src; time make ${MAKEOPTS} ${step} TARGET=${ARCH} KERNCONF=${CONF} DESTDIR=/mnt" || wtf "chroot-cmd ${step}"
171 # Copy the config files into the target, to keep a record of the build options
172 [ -f "${world}/config/${CONF}" ] && cp "${world}/config/${CONF}" "${build}/boot/kernel/"
173 [ -f "${world}/config/make.conf" ] && cp "${world}/config/make.conf" "${build}/etc/"
174 [ -f "${world}/config/src.conf" ] && cp "${world}/config/src.conf" "${build}/etc/"