]> CyberLeo.Net >> Repos - CDN/Mosi.git/blob - script/makeworld
script/makeworld: build with GENERIC kernconf if none provided
[CDN/Mosi.git] / script / makeworld
1 #!/bin/sh
2
3 # Load shlib and modules
4 _root="$(dirname "${0}")"; . "${_root}/lib/env.sh"
5 want log
6
7 pebkac() {
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>)"
13   echo "  -s <srctree>    Override source tree selection"
14   echo "  -h              Help!"
15   echo "  -v              Verbose (show build log in real time)"
16   echo ""
17   echo "If, for some reason, you wish to spread out builds across multiple"
18   echo "invocations, these might come in handy:"
19   echo "  -p              Prepare chroot environment"
20   echo "  -d              Don't prepare or clean up chroot during run"
21   echo "  -q              Clean up chroot environment"
22   echo ""
23   echo "Available make targets:"
24   for make_tgt in ${make_tgts}
25   do
26     echo "  ${make_tgt}"
27   done
28   exit 1
29 }
30
31 # Prepare chroot for build
32 prepare() {
33   [ "${CHROOT_DIRTY}" -a ! "${CHROOT_PREPARE}" ] && return 0
34   # Verify environment sanity
35   [ -d "${build}" ] && omg "${build}: directory exists; purging" && cleanup
36   mount | grep -q "${build}" && wtf "Stuff is mounted under ${build}; cannot continue"
37   ls -1 "${seed}"/base.?? >/dev/null 2>&1 || wtf "Populate seed directory ${seed} first"
38   [ -f "${SRCS}/sys/conf/newvers.sh" ] || wtf "Need sources in ${SRCS} to build"
39
40   # Cleanup trap here, so that an abort during prepare can clean up properly
41   trap "cleanup" exit hup int term kill
42
43   meh "Preparing build chroot"
44   [ -d "${build}" ] && wtf "${build}: directory exists"
45   mkdir -p "${build}" || wtf
46   cat "${seed}"/base.?? | tar xCf "${build}" - || wtf
47   mkdir -p "${build}/usr/obj" || wtf
48
49   meh "Mounting chroot filesystems"
50   mkdir -p "${world}/log"
51   mkdir -p "${world}/obj"
52   mkdir -p "${world}/root"
53   mount -t devfs devfs "${build}/dev" || wtf
54   # Mount /usr/src as a union, so that changes to it will not affect the underlying tree
55   # unionfs suffers from deadlocks; don't use it
56   mount -t nullfs -r "${SRCS}" "${build}/usr/src" || wtf
57   mount -t nullfs "${world}/obj" "${build}/usr/obj" || wtf
58   mount -t nullfs "${world}/root" "${build}/mnt" || wtf
59
60   if [ -d "${world}/config" ]
61   then
62     meh "Installing build-time configuration"
63     [ -f "${world}/config/${CONF}" ] && cp "${world}/config/${CONF}" "${SRCS}/sys/${ARCH}/conf/"
64     [ -f "${world}/config/make.conf" ] && cp "${world}/config/make.conf" "${build}/etc/"
65     [ -f "${world}/config/src.conf" ] && cp "${world}/config/src.conf" "${build}/etc/"
66   fi
67   return 0
68 }
69
70 # Cleanup chroot
71 cleanup() {
72   [ "${BUILD_VERBOSE}" ] || exec 1>&3
73   [ "${CHROOT_DIRTY}" -a ! "${CHROOT_CLEAN}" ] && return 0
74   meh "Cleaning up"
75   umount -f "${build}/mnt"
76   umount -f "${build}/usr/obj"
77   umount -f "${build}/usr/src"
78   umount -f "${build}/dev"
79   mount | grep -q "${build}/" && wtf "Stuff is still mounted under ${build}; not removing"
80   chflags -R noschg "${build}"
81   rm -Rf "${build}"
82   trap "" exit hup int term kill
83   return 0
84 }
85
86 # Root directory of makeworld
87 ROOT="$(realpath "$(dirname "${0}")/..")"
88
89 # Location of worlds
90 WORLDS="${ROOT}/worlds"
91
92 # Compute make -j<cpus*2>
93 make_cpus="$(sysctl -n hw.ncpu)"
94 make_jobs="$(( ${make_cpus} * 2 ))"
95 make_tgts="buildworld buildkernel distrib-dirs installworld installkernel distribution"
96
97 # Defaults
98 ARCH="$(uname -m)"
99 CONF="GENERIC"
100 MAKEOPTS="-j${make_jobs}"
101 SRCS=""
102 CHROOT_PREPARE=""
103 CHROOT_DIRTY=""
104 CHROOT_CLEAN=""
105 BUILD_VERBOSE=""
106
107 while getopts "m:a:c:hpdq" opt
108 do
109   case "${opt}" in
110     m) MAKEOPTS="${MAKEOPTS} ${OPTARG}" ;;
111     a) ARCH="${OPTARG}" ;;
112     c) CONF="${OPTARG}" ;;
113     s) SRCS="${OPTARG}" ;;
114     p) CHROOT_PREPARE="TRUE" ;;
115     d) CHROOT_DIRTY="TRUE" ;;
116     q) CHROOT_CLEAN="TRUE" ;;
117     v) BUILD_VERBOSE="TRUE" ;;
118     h) pebkac ;;
119     [?]) pebkac "Unrecognized option ${opt}" ;;
120   esac
121 done
122 shift $(( $OPTIND - 1 ))
123
124 # Should be root after this point
125 want root
126
127 # Build make target sequence
128 sequence="${*:-${make_tgts}}"
129
130 # Target world directory
131 world="${WORLDS}/${ARCH}/${CONF}"
132 # Source chroot seed directory
133 seed="${ROOT}/seed/base/$(uname -m)"
134 # Root directory for chroot
135 build="${world}/chroot"
136
137 if [ -z "${SRCS}" ]
138 then
139   # Locate a usable source tree
140   # Pick world/src over /usr/src if it exists at all, even if it is not usable, to provide warning of bad configs
141   SRCS="${world}/src"
142   [ -L "${SRCS}" -o -d "${SRCS}" ] || SRCS=/usr/src
143 fi
144 SRCS="$(realpath "${SRCS}")"
145
146 # If kernel config matching CONF does not exist, assume GENERIC
147 if [ -e "${world}/config/${CONF}" ]
148 then
149   KERNCONF="${CONF}"
150 else
151   KERNCONF=GENERIC
152 fi
153
154 # Environment for chroot build
155 env="
156 USER=root
157 HOME=/root
158 PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
159 SHELL=/bin/sh
160 "
161
162 date="$(date +%Y%m%d)"
163
164 # Check if target config exists
165 [ -d "${world}" ] || wtf "${ARCH}/${CONF} doesn't exist"
166
167 if [ "${CHROOT_PREPARE}" ]
168 then
169   prepare
170   trap "" exit
171   meh "Chroot prepared"
172   exit
173 fi
174
175 if [ "${CHROOT_CLEAN}" ]
176 then
177   cleanup
178   meh "Chroot cleaned"
179   exit
180 fi
181
182 meh "Making world for ${ARCH}/${CONF}"
183
184 meh "Targets: ${sequence}"
185
186 prepare
187
188 meh "Seed: ${seed}"
189 meh "Srctree: ${SRCS}"
190 meh "Config: ${ARCH}/${CONF}"
191 [ "${KERNCONF}" != "${CONF}" ] && meh "Kernel config: ${KERNCONF}"
192 meh "Builddir: ${build}"
193 meh "make ${MAKEOPTS}"
194 meh "DESTDIR=${world}/root"
195
196 for step in ${sequence}
197 do
198   build_log="${world}/log/${date}-${step}.log"
199   meh "==> Step: ${step} -> ${build_log}"
200   [ "${BUILD_VERBOSE}" ] || exec 3>&1 > /dev/null
201   script "${build_log}" env -i ${env} chroot "${build}" sh -c \
202     "cd /usr/src; time make ${MAKEOPTS} ${step} TARGET=${ARCH} KERNCONF=${KERNCONF} DESTDIR=/mnt"
203   res=$?
204   [ "${BUILD_VERBOSE}" ] || exec 1>&3
205   [ "${res}" -gt 0 ] && wtf "chroot-cmd ${step} failed; check log"
206 done
207
208 # Copy the config files into the target, to keep a record of the build options
209 [ -f "${world}/config/${CONF}" ] && cp "${world}/config/${CONF}" "${world}/root/boot/kernel/"
210 [ -f "${world}/config/make.conf" ] && cp "${world}/config/make.conf" "${world}/root/etc/"
211 [ -f "${world}/config/src.conf" ] && cp "${world}/config/src.conf" "${world}/root/etc/"