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