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