build.sh 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #!/bin/bash
  2. set -e -u
  3. # misc constants
  4. readonly ALL_ARCHES='i686 x86_64'
  5. readonly EFI_IMG_KBYTES=80000
  6. readonly LOG_COLOR='\033[01;34m'
  7. readonly ERR_COLOR='\033[00;31m'
  8. readonly END_COLOR='\033[00m'
  9. # edition-specific data
  10. declare -ar VALID_INITS=('openrc' 'systemd')
  11. declare -ar VALID_WMDES=('cli' 'lxde' 'mate' 'mini')
  12. # environment
  13. data_dir=/usr/share/parabolaiso/data
  14. releng_dir=$(readlink -f ${0%/*})
  15. initcpio_dir=${releng_dir}/../../parabolaiso/initcpio
  16. packages_dir=${releng_dir}/packages
  17. [ "$(which mkparabolaiso 2> /dev/null)" ] || export PATH=$PATH:"${releng_dir}/../../parabolaiso"
  18. # CLI option defaults
  19. iso_arch='x86_64'
  20. iso_init='systemd'
  21. iso_wmde='cli'
  22. enable_tts_brltty='false'
  23. enable_offline_install='false'
  24. iso_version=$(date +%Y.%m.%d)
  25. iso_label="PARA_$(date +%Y%m)"
  26. iso_dirname='parabola'
  27. pacman_conf_in=${releng_dir}/pacman.conf
  28. work_dir=./work
  29. out_dir=./out
  30. verbose=''
  31. # computed vars, pending CLI options
  32. edition_init='' # deferred
  33. edition_wmde='' # deferred
  34. iso_edition='' # deferred
  35. archs='' # deferred
  36. launch_msg='' # deferred
  37. iso_title='' # deferred
  38. release_id='' # deferred
  39. iso_filename='' # deferred
  40. arch='' # deferred
  41. pacman_conf='' # deferred
  42. _usage ()
  43. {
  44. echo "usage ${0} [options]"
  45. echo
  46. echo " General options:"
  47. echo " -A <iso_arch> Target architecture - one of: [ 'dual' , 'i686' , 'x86_64' ]"
  48. echo " Default: ${iso_arch}"
  49. echo " -I <iso_init> Init system - one of: [ 'openrc' , 'systemd' ]"
  50. echo " Default: ${iso_init}"
  51. echo " -W <iso_wmde> Graphical environment - one of: [ 'cli' , 'lxde' , 'mini' ]"
  52. echo " Default: ${iso_wmde}"
  53. echo " -S Enable speech and braille."
  54. echo " Default: '${enable_tts_brltty}'"
  55. echo " -O Enable offline install."
  56. echo " Default: '' (net-install only)"
  57. echo " -V <iso_version> Release version string"
  58. echo " Default: ${iso_version}"
  59. echo " -L <iso_label> Set the iso volume label"
  60. echo " Default: ${iso_label}"
  61. echo " -D <iso_dirname> Set the name of the directory inside the ISO"
  62. echo " Default: ${iso_dirname}"
  63. echo " -C Specify the pacman.conf file used for chroot install."
  64. echo " Default: '${pacman_conf_in}'"
  65. echo " -w <work_dir> Set the working directory"
  66. echo " Default: ${work_dir}"
  67. echo " -o <out_dir> Set the output directory"
  68. echo " Default: ${out_dir}"
  69. echo " -v Enable verbose output"
  70. echo " -h This help message"
  71. exit ${1}
  72. }
  73. LOG_STEP() { printf "${LOG_COLOR}%s${END_COLOR}\n" "$(echo -e $*)" ; }
  74. LOG_ERROR() { printf "${ERR_COLOR}%s${END_COLOR}\n" "$(echo -e $*)" ; }
  75. # Helper function to run make_*() only one time per architecture.
  76. run_once() {
  77. local buid_stamp="build.${1}_${arch}"
  78. if [[ ! -e ${work_dir}/${buid_stamp} ]]; then
  79. LOG_STEP "runnning build step: '${buid_stamp}'"
  80. $1
  81. touch ${work_dir}/${buid_stamp}
  82. fi
  83. }
  84. # Setup custom pacman.conf to cache packages on the target filesystem.
  85. make_pacman_conf() {
  86. local stash_dir=${work_dir}/isorepo-${arch}
  87. local isorepo_dir=${work_dir}/${arch}/root-image/isorepo/
  88. # restore package cache from previous build
  89. if [[ -d ${stash_dir} ]]; then
  90. echo "restoring package cache from ${stash_dir}"
  91. mkdir -p ${isorepo_dir}
  92. mv ${stash_dir}/* ${isorepo_dir} || true
  93. fi
  94. cp ${pacman_conf_in} ${pacman_conf}
  95. # enable [isorepo]
  96. sed -i -E 's|^#?\s*CacheDir.+|CacheDir = '${isorepo_dir}'|g' ${pacman_conf}
  97. # enable [nonsystemd] for openrc ISOs
  98. if [[ "${iso_init}" == 'openrc' ]]
  99. then sed -i 'N ; s|^#\[nonsystemd\].*#Include|\[nonsystemd\]\nInclude|' ${pacman_conf}
  100. fi
  101. }
  102. # Base installation, plus needed packages (root-image)
  103. make_basefs() {
  104. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} init
  105. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "memtest86+ mkinitcpio-nfs-utils nbd" install
  106. }
  107. # Additional packages (root-image)
  108. make_packages() {
  109. local _base_packages_msg="standard packages as declared in the following files:"
  110. local _extra_packages_msg="non-graphical packages as declared in the following files:"
  111. # standard package lists
  112. local _install_base_lists=$( ls ${packages_dir}/packages-{all,${iso_init}}.{all,${arch}} 2> /dev/null || true)
  113. local _cache_base_lists=$( ls ${packages_dir}/cache-{all,${iso_init}}.{all,${arch}} 2> /dev/null || true)
  114. # extra package lists
  115. local _install_extra_lists=$(ls ${packages_dir}/packages-gui.{all,${arch}} 2> /dev/null || true)
  116. local _cache_extra_lists=$( ls ${packages_dir}/cache-gui.{all,${arch}} 2> /dev/null || true)
  117. # init-specific extra package lists
  118. local _install_init_lists=$( ls ${packages_dir}/packages-${iso_init}-gui.{all,${arch}} 2> /dev/null || true)
  119. local _cache_init_lists=$( ls ${packages_dir}/cache-${iso_init}-gui.{all,${arch}} 2> /dev/null || true)
  120. # wmde-specific extra package lists
  121. local _install_wmde_lists=$( ls ${packages_dir}/packages-${iso_wmde}.{all,${arch}} 2> /dev/null || true)
  122. local _cache_wmde_lists=$( ls ${packages_dir}/cache-${iso_wmde}.{all,${arch}} 2> /dev/null || true)
  123. _install_base_lists=${_install_base_lists// /}
  124. _cache_base_lists=${_cache_base_lists// /}
  125. _install_extra_lists=${_install_extra_lists// /}
  126. _cache_extra_lists=${_cache_extra_lists// /}
  127. _install_init_lists=${_install_init_lists// /}
  128. _cache_init_lists=${_cache_init_lists// /}
  129. _install_wmde_lists=${_install_wmde_lists// /}
  130. _cache_wmde_lists=${_cache_wmde_lists// /}
  131. # collect standard packages
  132. local _install_base_packages=$( [ "${_install_base_lists}" ] && grep -hv ^# ${_install_base_lists})
  133. local _cache_base_packages=$( [ "${_cache_base_lists}" ] && grep -hv ^# ${_cache_base_lists})
  134. # collect extra packages
  135. local _install_basegui_packages=$([ "${_install_extra_lists}" ] && grep -hv ^# ${_install_extra_lists})
  136. local _cache_basegui_packages=$( [ "${_cache_extra_lists}" ] && grep -hv ^# ${_cache_extra_lists})
  137. # collect init-specific extra packages
  138. local _install_init_packages=$( [ "${_install_init_lists}" ] && grep -hv ^# ${_install_init_lists})
  139. local _cache_init_packages=$( [ "${_cache_init_lists}" ] && grep -hv ^# ${_cache_init_lists})
  140. # collect wmde-specific extra packages
  141. local _install_wmde_packages=$( [ "${_install_wmde_lists}" ] && grep -hv ^# ${_install_wmde_lists})
  142. local _cache_wmde_packages=$( [ "${_cache_wmde_lists}" ] && grep -hv ^# ${_cache_wmde_lists})
  143. if [[ "${iso_wmde}" != 'cli' && "${iso_wmde}" != 'mini' ]]; then
  144. _install_wmde_lists="${_install_extra_lists} ${_install_init_lists} ${_install_wmde_lists}"
  145. _cache_wmde_lists="${_cache_extra_lists} ${_cache_init_lists} ${_cache_wmde_lists}"
  146. _install_wmde_packages="${_install_basegui_packages} ${_install_init_packages} ${_install_wmde_packages}"
  147. _cache_wmde_packages="${_cache_basegui_packages} ${_cache_init_packages} ${_cache_wmde_packages}"
  148. fi
  149. _install_wmde_lists=${_install_wmde_lists// /}
  150. _cache_wmde_lists=${_cache_wmde_lists// /}
  151. _install_base_packages=${_install_base_packages// /}
  152. _cache_base_packages=${_cache_base_packages// /}
  153. _install_wmde_packages=${_install_wmde_packages// /}
  154. _cache_wmde_packages=${_cache_wmde_packages// /}
  155. # display results
  156. local _install_packages="${_install_base_packages} ${_install_wmde_packages}"
  157. local _cache_packages="${_cache_base_packages} ${_cache_wmde_packages}"
  158. _install_packages=${_install_packages// /}
  159. _cache_packages=${_cache_packages// /}
  160. [ "${_install_base_packages}" ] && echo "Installing ${_base_packages_msg}" && echo "${_install_base_lists}" | sed "s/.*\//\t/"
  161. [ "${_cache_base_packages}" ] && echo "Caching ${_base_packages_msg}" && echo "${_cache_base_lists}" | sed "s/.*\//\t/"
  162. [ "${_install_wmde_packages}" ] && echo "Installing ${_extra_packages_msg}" && echo "${_install_wmde_lists}" | sed "s/.*\//\t/"
  163. [ "${_cache_wmde_packages}" ] && echo "Caching ${_extra_packages_msg}" && echo "${_cache_wmde_lists}" | sed "s/.*\//\t/"
  164. # install packages
  165. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "${_install_packages}" install
  166. # create live environment local repo or stash package cache
  167. if [[ "$enable_offline_install" == 'true' ]]; then
  168. if [[ -n "${_cache_packages}" ]]; then
  169. # download any cache packages and prune obsolete packages
  170. echo 'downloading "cache-only" packages'
  171. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -p "${_cache_packages}" cache
  172. fi
  173. # create 'isorepo' for offline install
  174. echo "creating 'isorepo' for offline install"
  175. pushd ${work_dir}/${arch}/root-image/isorepo > /dev/null
  176. setarch ${arch} repo-add --new isorepo.db.tar.gz ./*
  177. popd > /dev/null
  178. else
  179. # stash package cache for next build
  180. echo "stashing package cache to ${work_dir}/isorepo-${arch}"
  181. mkdir -p ${work_dir}/isorepo-${arch}/
  182. mv ${work_dir}/${arch}/root-image/isorepo/* ${work_dir}/isorepo-${arch}/
  183. rmdir ${work_dir}/${arch}/root-image/isorepo
  184. fi
  185. }
  186. # Copy mkinitcpio parabolaiso hooks and build initramfs (root-image)
  187. make_setup_mkinitcpio() {
  188. local _hook
  189. for _hook in parabolaiso parabolaiso_shutdown parabolaiso_pxe_common parabolaiso_pxe_nbd parabolaiso_pxe_http parabolaiso_pxe_nfs parabolaiso_loop_mnt; do
  190. cp ${initcpio_dir}/hooks/${_hook} ${work_dir}/${arch}/root-image/usr/lib/initcpio/hooks
  191. cp ${initcpio_dir}/install/${_hook} ${work_dir}/${arch}/root-image/usr/lib/initcpio/install
  192. done
  193. cp ${initcpio_dir}/install/parabolaiso_kms ${work_dir}/${arch}/root-image/usr/lib/initcpio/install
  194. cp ${initcpio_dir}/hooks/parabolaiso_shutdown ${work_dir}/${arch}/root-image/usr/lib/initcpio
  195. cp ${releng_dir}/mkinitcpio.conf ${work_dir}/${arch}/root-image/etc/mkinitcpio-parabolaiso.conf
  196. [[ "${arch}" != 'i686' ]] && sed -i 's|pcmcia||' ${work_dir}/${arch}/root-image/etc/mkinitcpio-parabolaiso.conf
  197. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} -C ${pacman_conf} -D ${iso_dirname} -r 'mkinitcpio -c /etc/mkinitcpio-parabolaiso.conf -k /boot/vmlinuz-linux-libre -g /boot/parabolaiso.img' run
  198. }
  199. # Customize installation (root-image)
  200. make_customize_root_image() {
  201. cp -af ${releng_dir}/root-image ${work_dir}/${arch}
  202. echo "Customizing root image"
  203. ISO_TITLE="${iso_title}" \
  204. ISO_INIT="${iso_init}" \
  205. ISO_WMDE="${iso_wmde}" \
  206. ISO_ARCH="${iso_arch}" \
  207. ENABLE_OFFLINE_INSTALL="${enable_offline_install}" \
  208. ENABLE_TTS_BRLTTY="${enable_tts_brltty}" \
  209. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/${arch} \
  210. -C ${pacman_conf} \
  211. -D ${iso_dirname} \
  212. -r /root/customize_root_image.sh \
  213. run
  214. rm ${work_dir}/${arch}/root-image/root/customize_root_image*
  215. }
  216. # Prepare kernel/initramfs ${iso_dirname}/boot/
  217. make_boot() {
  218. mkdir -p ${work_dir}/iso/${iso_dirname}/boot/${arch}
  219. cp ${work_dir}/${arch}/root-image/boot/parabolaiso.img ${work_dir}/iso/${iso_dirname}/boot/${arch}/parabolaiso.img
  220. cp ${work_dir}/${arch}/root-image/boot/vmlinuz-linux-libre ${work_dir}/iso/${iso_dirname}/boot/${arch}/vmlinuz
  221. }
  222. # Add other aditional/extra files to ${iso_dirname}/boot/
  223. make_boot_extra() {
  224. cp ${work_dir}/${arch}/root-image/boot/memtest86+/memtest.bin ${work_dir}/iso/${iso_dirname}/boot/memtest
  225. cp ${work_dir}/${arch}/root-image/usr/share/licenses/common/GPL2/license.txt ${work_dir}/iso/${iso_dirname}/boot/memtest.COPYING
  226. }
  227. # Prepare /${iso_dirname}/boot/syslinux
  228. make_syslinux() {
  229. mkdir -p ${work_dir}/iso/${iso_dirname}/boot/syslinux
  230. for _cfg in ${releng_dir}/syslinux/*.cfg; do
  231. sed "s|%PARABOLAISO_LABEL%|${iso_label}|g;
  232. s|%INSTALL_DIR%|${iso_dirname}|g" ${_cfg} > ${work_dir}/iso/${iso_dirname}/boot/syslinux/${_cfg##*/}
  233. done
  234. cp ${releng_dir}/syslinux/syslinux-splash-${iso_init}.png ${work_dir}/iso/${iso_dirname}/boot/syslinux/splash.png
  235. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/*.c32 ${work_dir}/iso/${iso_dirname}/boot/syslinux
  236. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/lpxelinux.0 ${work_dir}/iso/${iso_dirname}/boot/syslinux
  237. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/memdisk ${work_dir}/iso/${iso_dirname}/boot/syslinux
  238. mkdir -p ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt
  239. gzip -c -9 ${work_dir}/${arch}/root-image/usr/share/hwdata/pci.ids > ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt/pciids.gz
  240. gzip -c -9 ${work_dir}/${arch}/root-image/usr/lib/modules/*-gnu-*/modules.alias > ${work_dir}/iso/${iso_dirname}/boot/syslinux/hdt/modalias.gz
  241. # inject edition title into boot menu
  242. sed -i "s|_EDITION_TITLE_|${iso_title}|" ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_head.cfg
  243. # prune orphan boot entries for single-architecture ISO
  244. if [[ "${archs}" == 'i686' ]]; then
  245. rm ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_*64*.cfg
  246. elif [[ "${archs}" == 'x86_64' ]]; then
  247. rm ${work_dir}/iso/${iso_dirname}/boot/syslinux/parabolaiso_*32*.cfg
  248. fi
  249. }
  250. # Prepare /isolinux
  251. make_isolinux() {
  252. mkdir -p ${work_dir}/iso/isolinux
  253. sed "s|%INSTALL_DIR%|${iso_dirname}|g" ${releng_dir}/isolinux/isolinux.cfg > ${work_dir}/iso/isolinux/isolinux.cfg
  254. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/isolinux.bin ${work_dir}/iso/isolinux/
  255. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/isohdpfx.bin ${work_dir}/iso/isolinux/
  256. cp ${work_dir}/${arch}/root-image/usr/lib/syslinux/bios/ldlinux.c32 ${work_dir}/iso/isolinux/
  257. }
  258. # Prepare /EFI
  259. make_efi() {
  260. mkdir -p ${work_dir}/iso/EFI/boot
  261. if [[ "${iso_init}" == 'systemd' ]]; then
  262. cp ${work_dir}/x86_64/root-image/usr/lib/systemd/boot/efi/systemd-bootx64.efi ${work_dir}/iso/EFI/boot/bootx64.efi
  263. fi
  264. mkdir -p ${work_dir}/iso/loader/entries
  265. cp ${releng_dir}/efiboot/loader/loader.conf ${work_dir}/iso/loader/
  266. cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v2-x86_64.conf ${work_dir}/iso/loader/entries/
  267. cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v1-x86_64.conf ${work_dir}/iso/loader/entries/
  268. sed "s|%PARABOLAISO_LABEL%|${iso_label}|g;
  269. s|%INSTALL_DIR%|${iso_dirname}|g" \
  270. ${releng_dir}/efiboot/loader/entries/parabolaiso-x86_64-usb.conf > ${work_dir}/iso/loader/entries/parabolaiso-x86_64.conf
  271. # EFI Shell 2.0 for UEFI 2.3+ ( http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=UEFI_Shell )
  272. cp ${data_dir}/Shell.efi ${work_dir}/iso/EFI/shellx64_v2.efi
  273. # EFI Shell 1.0 for non UEFI 2.3+ ( http://sourceforge.net/apps/mediawiki/tianocore/index.php?title=Efi-shell )
  274. cp ${data_dir}/Shell_Full.efi ${work_dir}/iso/EFI/shellx64_v1.efi
  275. }
  276. # Prepare efiboot.img::/EFI for "El Torito" EFI boot mode
  277. make_efiboot() {
  278. # Cleanup in case of previous aborted run
  279. while mount | grep ${work_dir}/efiboot > /dev/null; do umount ${work_dir}/efiboot; sleep 1; done;
  280. rm ${work_dir}/iso/EFI/parabolaiso/efiboot.img 2> /dev/null || true
  281. # create EFI image
  282. mkdir -p ${work_dir}/iso/EFI/parabolaiso
  283. truncate -s ${EFI_IMG_KBYTES}K ${work_dir}/iso/EFI/parabolaiso/efiboot.img
  284. mkfs.vfat -n PARABOLAEFI ${work_dir}/iso/EFI/parabolaiso/efiboot.img
  285. mkdir -p ${work_dir}/efiboot
  286. mkdir -p ${work_dir}/efiboot-staging
  287. modprobe loop
  288. mount ${work_dir}/iso/EFI/parabolaiso/efiboot.img ${work_dir}/efiboot
  289. mkdir -p ${work_dir}/efiboot-staging/EFI/parabolaiso
  290. cp ${work_dir}/iso/${iso_dirname}/boot/x86_64/vmlinuz ${work_dir}/efiboot-staging/EFI/parabolaiso/vmlinuz.efi
  291. cp ${work_dir}/iso/${iso_dirname}/boot/x86_64/parabolaiso.img ${work_dir}/efiboot-staging/EFI/parabolaiso/parabolaiso.img
  292. mkdir -p ${work_dir}/efiboot-staging/EFI/boot
  293. if [[ "${iso_init}" == 'systemd' ]]; then
  294. cp ${work_dir}/x86_64/root-image/usr/lib/systemd/boot/efi/systemd-bootx64.efi ${work_dir}/efiboot-staging/EFI/boot/bootx64.efi
  295. fi
  296. mkdir -p ${work_dir}/efiboot-staging/loader/entries
  297. cp ${releng_dir}/efiboot/loader/loader.conf ${work_dir}/efiboot-staging/loader/
  298. cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v2-x86_64.conf ${work_dir}/efiboot-staging/loader/entries/
  299. cp ${releng_dir}/efiboot/loader/entries/uefi-shell-v1-x86_64.conf ${work_dir}/efiboot-staging/loader/entries/
  300. sed "s|%PARABOLAISO_LABEL%|${iso_label}|g;
  301. s|%INSTALL_DIR%|${iso_dirname}|g" \
  302. ${releng_dir}/efiboot/loader/entries/parabolaiso-x86_64-cd.conf > ${work_dir}/efiboot-staging/loader/entries/parabolaiso-x86_64.conf
  303. cp ${work_dir}/iso/EFI/shellx64_v2.efi ${work_dir}/efiboot-staging/EFI/
  304. cp ${work_dir}/iso/EFI/shellx64_v1.efi ${work_dir}/efiboot-staging/EFI/
  305. local efi_kbytes=$(($(du -ks ${work_dir}/efiboot-staging | cut -f 1) + 32))
  306. if [[ ${efi_kbytes} -lt $(( ${EFI_IMG_KBYTES} )) ]]; then
  307. echo "Populating EFI image (${efi_kbytes}KB)"
  308. cp -rT ${work_dir}/efiboot-staging ${work_dir}/efiboot
  309. rm -rf ${work_dir}/efiboot-staging
  310. umount ${work_dir}/efiboot
  311. else
  312. echo "Error: Not enough space on EFI image (${EFI_IMG_KBYTES}KB - need ${efi_kbytes}KB)"
  313. umount ${work_dir}/efiboot
  314. exit 1
  315. fi
  316. }
  317. # Copy aitab
  318. make_aitab() {
  319. mkdir -p ${work_dir}/iso/${iso_dirname}
  320. cp ${releng_dir}/aitab ${work_dir}/iso/${iso_dirname}/aitab
  321. }
  322. # Build all filesystem images specified in aitab (.fs.sfs .sfs)
  323. make_prepare() {
  324. cp -a -l -f ${work_dir}/${arch}/root-image ${work_dir}/
  325. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/ -D ${iso_dirname} -C ${pacman_conf} pkglist
  326. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/ -D ${iso_dirname} -C ${pacman_conf} prepare
  327. rm -rf ${work_dir}/root-image
  328. # rm -rf ${work_dir}/${arch}/root-image (if low space, this helps)
  329. }
  330. # Build ISO
  331. make_iso() {
  332. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/ -D ${iso_dirname} checksum
  333. setarch ${arch} mkparabolaiso ${verbose} -w ${work_dir}/ -D ${iso_dirname} -L ${iso_label} -o ${out_dir}/ iso ${iso_filename}
  334. }
  335. ## prepare state ##
  336. # collect CLI options
  337. while getopts 'A:I:W:SOV:L:D:C:w:o:vh' arg; do
  338. case "${arg}" in
  339. A) iso_arch="${OPTARG}" ;;
  340. I) iso_init="${OPTARG}" ;;
  341. W) iso_wmde="${OPTARG}" ;;
  342. S) enable_tts_brltty='true' ;;
  343. O) enable_offline_install='true' ;;
  344. V) iso_version="${OPTARG}" ;;
  345. L) iso_label="${OPTARG}" ;;
  346. D) iso_dirname="${OPTARG}" ;;
  347. C) pacman_conf_in="${OPTARG}" ;;
  348. w) work_dir="${OPTARG}" ;;
  349. o) out_dir="${OPTARG}" ;;
  350. v) verbose="-v" ;;
  351. h) _usage 0 ;;
  352. *)
  353. echo "Invalid argument '${arg}'"
  354. _usage 1
  355. ;;
  356. esac
  357. done
  358. # compute build configuration
  359. edition_init=$( case "${iso_init}" in 'openrc') echo 'OpenRC' ;; 'systemd') echo 'SystemD' ;; esac )
  360. edition_wmde=${iso_wmde^^}
  361. iso_edition=${edition_init}/${edition_wmde}
  362. case "${iso_arch}" in
  363. 'i686'|'x86_64')
  364. archs=${iso_arch}
  365. launch_msg="Building single-architecture ${iso_edition} ISO for ${archs}"
  366. ;;
  367. *)
  368. archs=${ALL_ARCHES}
  369. iso_arch='dual'
  370. launch_msg="Building multi-architecture ${iso_edition} ISO for ${archs}"
  371. ;;
  372. esac
  373. if [[ "$enable_offline_install" == 'true' ]]; then
  374. iso_type='complete'
  375. launch_msg="${launch_msg} (offline install enabled)"
  376. else
  377. iso_type='netinstall'
  378. launch_msg="${launch_msg} (net install only)"
  379. fi
  380. iso_title="Parabola GNU/Linux-libre Live - ${iso_edition} Edition ${iso_version}"
  381. release_id=${iso_arch}-${iso_init}-${iso_wmde}-${iso_version}
  382. iso_filename=parabola-${release_id}-${iso_type}.iso
  383. [[ "${archs}" == 'i686' ]] && arch='i686' || arch='x86_64'
  384. pacman_conf=${work_dir}/pacman.conf
  385. out_dir=${out_dir}/${release_id}
  386. ## sanity checks ##
  387. # sanitize mkparabolaiso args
  388. iso_init=${iso_init// /}
  389. iso_wmde=${iso_wmde// /}
  390. iso_arch=${iso_arch// /}
  391. iso_version=${iso_version// /}
  392. iso_label=${iso_label// /}
  393. iso_dirname=${iso_dirname// /}
  394. enable_offline_install=${enable_offline_install// /}
  395. enable_tts_brltty=${enable_tts_brltty// /}
  396. pacman_conf_in=${pacman_conf_in// /}
  397. work_dir=${work_dir// /}
  398. out_dir=${out_dir// /}
  399. iso_filename=${iso_filename// /}
  400. pacman_conf=${pacman_conf// /}
  401. # validate build environment
  402. if [[ "$(uname -m)" != 'x86_64' ]] || ! grep 'ID_LIKE="*arch' /usr/lib/os-release > /dev/null; then
  403. LOG_ERROR "This script needs to be run on an x86_64 ArchLinux derrivative."
  404. exit 1
  405. elif [[ ${EUID} -ne 0 ]]; then
  406. LOG_ERROR "This script needs to be run with root privileges."
  407. exit 1
  408. elif ! pacman --version | grep libalpm > /dev/null; then
  409. LOG_ERROR "This script needs the 'pacman' package manager to be installed."
  410. exit 1
  411. elif [[ "${archs}" =~ 'x86_64' ]] && ! pacman -Qi parabolaiso-data > /dev/null; then
  412. LOG_ERROR "x86_64 ISOs require the 'parabolaiso-data' package to be installed."
  413. exit 1
  414. elif ! echo "${VALID_INITS[@]}" | tr " " "\n" | grep -E "^${iso_init}$" > /dev/null || \
  415. ! echo "${VALID_WMDES[@]}" | tr " " "\n" | grep -E "^${iso_wmde}$" > /dev/null ; then
  416. LOG_ERROR "Invalid init/wm combination: '${iso_edition}'."
  417. exit 1
  418. fi
  419. # detect previously completed build
  420. prefix=${work_dir}/build.make_
  421. is_done=1
  422. single_pass_build_steps='boot_extra syslinux isolinux aitab iso'
  423. for build_step in $single_pass_build_steps
  424. do [ -f "${prefix}${build_step}_${arch}" ] || is_done=0
  425. done
  426. multi_pass_build_steps='pacman_conf basefs packages setup_mkinitcpio customize_root_image boot prepare'
  427. for build_step in $multi_pass_build_steps
  428. do for arch in ${archs}
  429. do [ -f "${prefix}${build_step}_${arch}" ] || is_done=0
  430. done
  431. done
  432. if ! (($is_done)); then LOG_STEP "${launch_msg}"; else LOG_STEP "Nothing to do"; exit; fi;
  433. ## build ISO ##
  434. # prepare environment
  435. chown -R 0:0 "${releng_dir}/root-image/"
  436. mkdir -p "$(realpath ${work_dir})" # allow symlink
  437. # prepare target filesystems
  438. for arch in ${archs}; do
  439. run_once make_pacman_conf
  440. run_once make_basefs
  441. run_once make_packages
  442. run_once make_setup_mkinitcpio
  443. run_once make_customize_root_image
  444. done
  445. # prepare kernels and initrds
  446. for arch in ${archs}; do
  447. run_once make_boot
  448. done
  449. # prepare ISO
  450. run_once make_boot_extra
  451. run_once make_syslinux
  452. run_once make_isolinux
  453. # prepare EFI
  454. if [[ "$(echo ${archs} | grep x86_64)" ]]; then
  455. run_once make_efi
  456. run_once make_efiboot
  457. fi
  458. # prepare SFSs
  459. run_once make_aitab
  460. for arch in ${archs}; do
  461. run_once make_prepare
  462. done
  463. # build ISO
  464. run_once make_iso
  465. LOG_STEP "done - ISO: '${iso_filename}' created successfully"