5 # Email : hayao@fascone.net
7 # (c) 2019-2020 Fascode Network.
11 # The main script that runs the build
16 script_path="$(readlink -f ${0%/*})"
20 # Do not change this variable.
21 # To change the settings permanently, edit the config file.
27 iso_label="ALTER_$(date +%Y%m)"
28 iso_publisher='Fascode Network <https://fascode.net>'
29 iso_application="${os_name} Live/Rescue CD"
30 iso_version=$(date +%Y.%m.%d)
35 mkalteriso_option="-v"
37 # AlterLinux additional settings
41 theme_name="alter-logo"
42 theme_pkg="plymouth-theme-alter-logo-git"
52 mkalteriso="${script_path}/system/mkalteriso"
58 "arch-install-scripts"
76 # Pacman configuration file used only when building
77 build_pacman_conf=${script_path}/system/pacman-${arch}.conf
81 [[ -f "${script_path}"/config ]] && source "${script_path}"/config
88 # usage: echo_color -b <backcolor> -t <textcolor> -d <decoration> [Text]
111 # You can specify multiple decorations with ;.
112 # 0 => All attributs off (ノーマル)
114 # 4 => Underscore (下線)
116 # 7 => Reverse video on (色反転)
130 while getopts 'b:t:d:n' arg; do
132 b) backcolor="${OPTARG}" ;;
133 t) textcolor="${OPTARG}" ;;
134 d) decotypes="${OPTARG}" ;;
135 n) echo_opts="-n -e" ;;
139 shift $((OPTIND - 1))
141 echo ${echo_opts} "\e[$([[ -v backcolor ]] && echo -n "${backcolor}"; [[ -v textcolor ]] && echo -n ";${textcolor}"; [[ -v decotypes ]] && echo -n ";${decotypes}")m${@}\e[m"
145 # Show an INFO message
152 while getopts 'n' arg; do
154 n) echo_opts="${echo_opts} -n" ;;
157 shift $((OPTIND - 1))
158 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '32' 'Info') ${@}"
162 # Show an Warning message
169 while getopts 'n' arg; do
171 n) echo_opts="${echo_opts} -n" ;;
174 shift $((OPTIND - 1))
175 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '33' 'Warning') ${@}" >&2
179 # Show an debug message
186 while getopts 'n' arg; do
188 n) echo_opts="${echo_opts} -n" ;;
191 shift $((OPTIND - 1))
192 if [[ ${debug} = true ]]; then
193 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '35' 'Debug') ${@}"
198 # Show an ERROR message then exit with status
200 # $2: exit code number (with 0 does not exit)
208 while getopts 'n' arg; do
210 n) echo_opts="${echo_opts} -n" ;;
213 shift $((OPTIND - 1))
214 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '31' 'Error') ${1}" >&2
215 if [[ -n "${_error}" ]]; then
222 echo "usage ${0} [options] [channel]"
224 echo " General options:"
225 echo " -b Enable boot splash"
226 echo " Default: disable"
227 echo " -c <comp_type> Set SquashFS compression type (gzip, lzma, lzo, xz, zstd)"
228 echo " Default: ${sfs_comp}"
229 echo " -g <gpg_key> Set gpg key"
230 echo " Default: ${gpg_key}"
231 echo " -j Enable Japanese mode."
232 echo " Default: disable"
233 echo " -k <kernel> Set special kernel type."
234 echo " core means normal linux kernel"
235 echo " Default: ${kernel}"
236 echo " -l Enable post-build cleaning."
237 echo " Default: disable"
238 echo " -o <out_dir> Set the output directory"
239 echo " Default: ${out_dir}"
240 echo " -p <password> Set a live user password"
241 echo " Default: ${password}"
242 echo " -t <options> Set compressor-specific options."
243 echo " Default: empty"
244 echo " -u <username> Set user name."
245 echo " Default: ${username}"
246 echo " -w <work_dir> Set the working directory"
247 echo " Default: ${work_dir}"
248 echo " -x Enable debug mode."
249 echo " Default: disable"
250 echo " -h This help message and exit."
252 echo "You can switch between installed packages, files included in images, etc. by channel."
255 for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
256 if [[ -n $(ls "${script_path}"/channels/${i}) ]]; then
257 if [[ ! ${i} = "share" ]]; then
258 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
259 if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
260 channel_list="${channel_list[@]} ${i}"
263 channel_list="${channel_list[@]} ${i}"
268 channel_list="${channel_list[@]} rebuild"
269 for _channel in ${channel_list[@]}; do
270 if [[ -f "${script_path}/channels/${_channel}/description.txt" ]]; then
271 description=$(cat "${script_path}/channels/${_channel}/description.txt")
272 elif [[ "${_channel}" = "rebuild" ]]; then
273 description="Rebuild using the settings of the previous build."
275 description="This channel does not have a description.txt."
277 if [[ $(echo "${_channel}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
278 echo -ne " $(echo ${_channel} | sed 's/\.[^\.]*$//')"
279 for i in $( seq 1 $(( 23 - ${#_channel} )) ); do
283 echo -ne " ${_channel}"
284 for i in $( seq 1 $(( 19 - ${#_channel} )) ); do
288 echo -ne "${description}\n"
296 # Check the value of a variable that can only be set to true or false.
299 case $(eval echo '$'${1}) in
301 *) _msg_error "The value ${boot_splash} set is invalid" "1";;
305 check_bool boot_splash
307 check_bool bash_debug
314 # Helper function to run make_*() only one time.
316 if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then
317 _msg_debug "Running $1 ..."
319 touch "${work_dir}/build.${1}_${arch}"
321 _msg_debug "Skipped because ${1} has already been executed."
327 # Delete the file if it exists.
328 # For directories, rm -rf is used.
329 # If the file does not exist, skip it.
330 # remove <file> <file> ...
335 for _file in "${_list[@]}"; do
336 _msg_debug "Removeing ${_file}"
337 if [[ -f ${_file} ]]; then
339 elif [[ -d ${_file} ]]; then
346 # Preparation for build
348 # Check architecture for each channel
349 if [[ -z $(cat ${script_path}/channels/${channel_name}/architecture | grep -h -v ^'#' | grep -x "${arch}") ]]; then
350 _msg_error "${channel_name} channel does not support current architecture (${arch})." "1"
354 # Create a working directory.
355 [[ ! -d "${work_dir}" ]] && mkdir -p "${work_dir}"
359 if [[ -n $(ls -a "${work_dir}" 2> /dev/null | grep -xv ".." | grep -xv ".") ]] && [[ ! "${rebuild}" = true ]]; then
360 _msg_info "Deleting the contents of ${work_dir}..."
361 remove "${work_dir%/}"/*
368 local out_file="${work_dir}/build_options"
370 echo "#!/usr/bin/env bash" > "${out_file}"
371 echo "# Build options are stored here." >> "${out_file}"
373 echo -n "${i}=" >> "${out_file}"
374 echo -n '"' >> "${out_file}"
375 eval echo -n '$'{${i}} >> "${out_file}"
376 echo '"' >> "${out_file}"
379 if [[ ${rebuild} = false ]]; then
380 # If there is pacman.conf for each channel, use that for building
381 if [[ -f "${script_path}/channels/${channel_name}/pacman-${arch}.conf" ]]; then
382 build_pacman_conf="${script_path}/channels/${channel_name}/pacman-${arch}.conf"
386 # If there is config for each channel. load that.
387 if [[ -f "${script_path}/channels/${channel_name}/config" ]]; then
388 source "${script_path}/channels/${channel_name}/config"
389 _msg_debug "The settings have been overwritten by the ${script_path}/channels/${channel_name}/config."
415 username mkalteriso \
420 source "${work_dir}/build_options"
422 # Delete the lock file.
423 # remove "$(ls ${work_dir}/* | grep "build.make")"
429 for mount in $(mount | awk '{print $3}' | grep $(realpath ${work_dir})); do
430 _msg_info "Unmounting ${mount}"
435 # Generate iso file name.
436 if [[ "${japanese}" = true ]]; then
437 if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
438 iso_filename="${iso_name}-$(echo ${channel_name} | sed 's/\.[^\.]*$//')-jp-${iso_version}-${arch}.iso"
440 iso_filename="${iso_name}-${channel_name}-jp-${iso_version}-${arch}.iso"
443 if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
444 iso_filename="${iso_name}-$(echo ${channel_name} | sed 's/\.[^\.]*$//')-${iso_version}-${arch}.iso"
446 iso_filename="${iso_name}-${channel_name}-${iso_version}-${arch}.iso"
455 local check_failed=false
457 installed_pkg=($(pacman -Q | awk '{print $1}'))
458 installed_ver=($(pacman -Q | awk '{print $2}'))
463 for i in $(seq 0 $(( ${#installed_pkg[@]} - 1 ))); do
464 if [[ "${installed_pkg[${i}]}" = ${1} ]]; then
465 ver=$(pacman -Sp --print-format '%v' --config ${build_pacman_conf} ${1} 2> /dev/null)
466 if [[ "${installed_ver[${i}]}" = "${ver}" ]]; then
469 elif [[ -z ${ver} ]]; then
482 if [[ ${debug} = false ]]; then
483 _msg_info "Checking dependencies ..."
485 for pkg in ${dependence[@]}; do
486 _msg_debug -n "Checking ${pkg} ..."
487 case $(check_pkg ${pkg}) in
489 [[ "${debug}" = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n"
490 _msg_warn "${pkg} is not the latest package."
491 _msg_warn "Local: $(pacman -Q ${pkg} 2> /dev/null | awk '{print $2}') Latest: $(pacman -Sp --print-format '%v' --config ${build_pacman_conf} ${pkg} 2> /dev/null)"
494 "not") _msg_error "${pkg} is not installed." ; check_failed=true ;;
495 "norepo") _msg_warn "${pkg} is not a repository package." ;;
496 "installed") [[ ${debug} = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n" ;;
500 if [[ "${check_failed}" = true ]]; then
506 if [[ -z $(lsmod | awk '{print $1}' | grep -x "loop") ]]; then
515 if [[ "${boot_splash}" = true ]]; then
516 _msg_info "Boot splash is enabled."
517 _msg_info "Theme is used ${theme_name}."
519 _msg_info "Use the ${kernel} kernel."
520 _msg_info "Live username is ${username}."
521 _msg_info "Live user password is ${password}."
522 _msg_info "The compression method of squashfs is ${sfs_comp}."
523 if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
524 _msg_info "Use the $(echo ${channel_name} | sed 's/\.[^\.]*$//') channel."
526 _msg_info "Use the ${channel_name} channel."
528 [[ "${japanese}" = true ]] && _msg_info "Japanese mode has been activated."
529 _msg_info "Build with architecture ${arch}."
531 if [[ ${noconfirm} = false ]]; then
532 echo "Press Enter to continue or Ctrl + C to cancel."
541 # Setup custom pacman.conf with current cache directories.
544 _cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g'))
545 sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${_cache_dirs[@]})|g" ${build_pacman_conf} > ${work_dir}/pacman.conf
548 # Base installation, plus needed packages (airootfs)
550 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" init
551 # ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "haveged intel-ucode amd-ucode memtest86+ mkinitcpio-nfs-utils nbd zsh efitools" install
552 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "bash haveged intel-ucode amd-ucode mkinitcpio-nfs-utils nbd efitools" install
555 if [[ "${boot_splash}" = true ]]; then
556 if [[ -n "${theme_pkg}" ]]; then
557 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "plymouth ${theme_pkg}" install
559 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "plymouth" install
564 if [[ ! "${kernel}" = "core" ]]; then
565 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "linux-${kernel} linux-${kernel}-headers broadcom-wl-dkms" install
567 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "linux linux-headers broadcom-wl" install
571 # Additional packages (airootfs)
573 # インストールするパッケージのリストを読み込み、配列pkglistに代入します。
584 #-- Detect package list to load --#
585 # Append the file in the share directory to the file to be read.
587 # Package list for Japanese
588 jplist="${script_path}/channels/share/packages.${arch}/jp.${arch}"
590 # Package list for non-Japanese
591 nojplist="${script_path}/channels/share/packages.${arch}/non-jp.${arch}"
593 if [[ "${japanese}" = true ]]; then
594 _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
596 _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${jplist}"))
600 # Add the files for each channel to the list of files to read.
602 # Package list for Japanese
603 jplist="${script_path}/channels/${channel_name}/packages.${arch}/jp.${arch}"
605 # Package list for non-Japanese
606 nojplist="${script_path}/channels/${channel_name}/packages.${arch}/non-jp.${arch}"
608 if [[ "${japanese}" = true ]]; then
609 # If Japanese is enabled, add it to the list of files to read other than non-jp.
610 _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
612 # If Japanese is disabled, add it to the list of files to read other than jp.
613 _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv ${jplist}))
617 #-- Read package list --#
618 # Read the file and remove comments starting with # and add it to the list of packages to install.
619 for _file in ${_loadfilelist[@]}; do
620 _msg_debug "Loaded package file ${_file}."
621 pkglist=( ${pkglist[@]} "$(grep -h -v ^'#' ${_file})" )
623 if [[ ${debug} = true ]]; then
627 # Exclude packages from the share exclusion list
628 excludefile="${script_path}/channels/share/packages.${arch}/exclude"
629 if [[ -f "${excludefile}" ]]; then
630 excludelist=( $(grep -h -v ^'#' "${excludefile}") )
633 _pkglist=(${pkglist[@]})
635 for _pkg in ${_pkglist[@]}; do
636 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
637 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
638 pkglist=(${pkglist[@]} "${_pkg}")
643 if [[ -n "${excludelist[@]}" ]]; then
644 _msg_debug "The following packages have been removed from the installation list."
645 _msg_debug "Excluded packages: ${excludelist[@]}"
648 # Exclude packages from the exclusion list for each channel
649 excludefile="${script_path}/channels/${channel_name}/packages.${arch}/exclude"
650 if [[ -f "${excludefile}" ]]; then
651 excludelist=( $(grep -h -v ^'#' "${excludefile}") )
654 _pkglist=(${pkglist[@]})
656 for _pkg in ${_pkglist[@]}; do
657 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
658 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
659 pkglist=(${pkglist[@]} "${_pkg}")
665 # Sort the list of packages in abc order.
668 for _pkg in ${pkglist[@]}; do
677 #for _pkg in ${pkglist[@]}; do
680 # echo "${pkglist[@]}"
690 # Create a list of packages to be finally installed as packages.list directly under the working directory.
691 echo "# The list of packages that is installed in live cd." > ${work_dir}/packages.list
692 echo "#" >> ${work_dir}/packages.list
693 echo >> ${work_dir}/packages.list
694 for _pkg in ${pkglist[@]}; do
695 echo ${_pkg} >> ${work_dir}/packages.list
698 # Install packages on airootfs
699 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -p "${pkglist[@]}" install
702 # Customize installation (airootfs)
703 make_customize_airootfs() {
704 # Overwrite airootfs with customize_airootfs.
711 if [[ -d "${_dir}" ]]; then
712 cp -af "${_dir}"/* "${work_dir}/${arch}/airootfs"
717 copy_airootfs "${script_path}/channels/share/airootfs.share"
718 copy_airootfs "${script_path}/channels/share/airootfs.${arch}"
719 copy_airootfs "${script_path}/channels/${channel_name}/airootfs.share"
720 copy_airootfs "${script_path}/channels/${channel_name}/airootfs.${arch}"
722 # Replace /etc/mkinitcpio.conf if Plymouth is enabled.
723 if [[ "${boot_splash}" = true ]]; then
724 cp "${script_path}/mkinitcpio/mkinitcpio-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio.conf"
727 # Code to use common pacman.conf in archiso.
728 # cp "${script_path}/pacman.conf" "${work_dir}/${arch}/airootfs/etc"
729 # cp "${build_pacman_conf}" "${work_dir}/${arch}/airootfs/etc"
731 # Get the optimal mirror list.
732 if [[ "${japanese}" = true ]]; then
733 # Use Japanese optimized mirror list when Japanese is enabled.
734 curl -o "${work_dir}/${arch}/airootfs/etc/pacman.d/mirrorlist" 'https://www.archlinux.org/mirrorlist/?country=JP&protocol=http&use_mirror_status=on'
736 curl -o "${work_dir}/${arch}/airootfs/etc/pacman.d/mirrorlist" 'https://www.archlinux.org/mirrorlist/?country=all&protocol=http&use_mirror_status=on'
739 # lynx -dump -nolist 'https://wiki.archlinux.org/index.php/Installation_Guide?action=render' >> ${work_dir}/${arch}/airootfs/root/install.txt
742 # customize_airootfs.sh options
743 # -b : Enable boot splash.
744 # -d : Enable debug mode.
745 # -i <inst_dir> : Set install dir
746 # -j : Enable Japanese.
747 # -k <kernel> : Set kernel name.
748 # -o <os name> : Set os name.
749 # -p <password> : Set password.
750 # -s <shell> : Set user shell.
751 # -t : Set plymouth theme.
752 # -u <username> : Set live user name.
753 # -x : Enable bash debug mode.
754 # -r : Enable rebuild.
757 # Generate options of customize_airootfs.sh.
758 local addition_options
761 if [[ ${boot_splash} = true ]]; then
762 if [[ -z ${theme_name} ]]; then
763 addition_options="${addition_options} -b"
765 addition_options="${addition_options} -b -t ${theme_name}"
768 if [[ ${debug} = true ]]; then
769 addition_options="${addition_options} -d"
771 if [[ ${bash_debug} = true ]]; then
772 addition_options="${addition_options} -x"
774 if [[ ${japanese} = true ]]; then
775 addition_options="${addition_options} -j"
777 if [[ ${rebuild} = true ]]; then
778 addition_options="${addition_options} -r"
781 share_options="-p '${password}' -k '${kernel}' -u '${username}' -o '${os_name}' -i '${install_dir}' -s '${usershell}' -a '${arch}'"
785 if [[ -f ${work_dir}/${arch}/airootfs/root/customize_airootfs.sh ]]; then
786 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
788 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then
789 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
791 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
792 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
793 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
794 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh"
797 # Execute customize_airootfs.sh.
798 if [[ -z ${addition_options} ]]; then
799 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
800 -w "${work_dir}/${arch}" \
801 -C "${work_dir}/pacman.conf" \
802 -D "${install_dir}" \
803 -r "/root/customize_airootfs.sh ${share_options}" \
805 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
806 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
807 -w "${work_dir}/${arch}" \
808 -C "${work_dir}/pacman.conf" \
809 -D "${install_dir}" \
810 -r "/root/customize_airootfs_${channel_name}.sh ${share_options}" \
812 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
813 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
814 -w "${work_dir}/${arch}" \
815 -C "${work_dir}/pacman.conf" \
816 -D "${install_dir}" \
817 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options}" \
821 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
822 -w "${work_dir}/${arch}" \
823 -C "${work_dir}/pacman.conf" \
824 -D "${install_dir}" \
825 -r "/root/customize_airootfs.sh ${share_options} ${addition_options}" \
828 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
829 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
830 -w "${work_dir}/${arch}" \
831 -C "${work_dir}/pacman.conf" \
832 -D "${install_dir}" \
833 -r "/root/customize_airootfs_${channel_name}.sh ${share_options} ${addition_options}" \
835 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
836 arch=${arch} ${mkalteriso} ${mkalteriso_option} \
837 -w "${work_dir}/${arch}" \
838 -C "${work_dir}/pacman.conf" \
839 -D "${install_dir}" \
840 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options} ${addition_options}" \
846 # Delete customize_airootfs.sh.
847 remove "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
848 remove "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
851 # Copy mkinitcpio archiso hooks and build initramfs (airootfs)
852 make_setup_mkinitcpio() {
854 mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
855 mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/install"
856 for _hook in "archiso" "archiso_shutdown" "archiso_pxe_common" "archiso_pxe_nbd" "archiso_pxe_http" "archiso_pxe_nfs" "archiso_loop_mnt"; do
857 cp "${script_path}/system/initcpio/hooks/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
858 cp "${script_path}/system/initcpio/install/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
860 sed -i "s|/usr/lib/initcpio/|/etc/initcpio/|g" "${work_dir}/${arch}/airootfs/etc/initcpio/install/archiso_shutdown"
861 cp "${script_path}/system/initcpio/install/archiso_kms" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
862 cp "${script_path}/system/initcpio/archiso_shutdown" "${work_dir}/${arch}/airootfs/etc/initcpio"
863 if [[ "${boot_splash}" = true ]]; then
864 cp "${script_path}/mkinitcpio/mkinitcpio-archiso-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
866 cp "${script_path}/mkinitcpio/mkinitcpio-archiso.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
869 if [[ "${gpg_key}" ]]; then
870 gpg --export "${gpg_key}" >"${work_dir}/gpgkey"
871 exec 17<>$"{work_dir}/gpgkey"
874 if [[ ! ${kernel} = "core" ]]; then
875 ARCHISO_GNUPG_FD=${gpg_key:+17} arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -r "mkinitcpio -c /etc/mkinitcpio-archiso.conf -k /boot/vmlinuz-linux-${kernel} -g /boot/archiso.img" run
877 ARCHISO_GNUPG_FD=${gpg_key:+17} arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman.conf" -D "${install_dir}" -r 'mkinitcpio -c /etc/mkinitcpio-archiso.conf -k /boot/vmlinuz-linux -g /boot/archiso.img' run
880 if [[ "${gpg_key}" ]]; then
885 # Prepare kernel/initramfs ${install_dir}/boot/
887 mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}"
888 cp "${work_dir}/${arch}/airootfs/boot/archiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img"
890 if [[ ! "${kernel}" = "core" ]]; then
891 cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel}" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}"
893 cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz"
897 # Add other aditional/extra files to ${install_dir}/boot/
899 # In AlterLinux, memtest has been removed.
900 # cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest"
901 # cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" "${work_dir}/iso/${install_dir}/boot/memtest.COPYING"
902 cp "${work_dir}/${arch}/airootfs/boot/intel-ucode.img" "${work_dir}/iso/${install_dir}/boot/intel_ucode.img"
903 cp "${work_dir}/${arch}/airootfs/usr/share/licenses/intel-ucode/LICENSE" "${work_dir}/iso/${install_dir}/boot/intel_ucode.LICENSE"
904 cp "${work_dir}/${arch}/airootfs/boot/amd-ucode.img" "${work_dir}/iso/${install_dir}/boot/amd_ucode.img"
905 cp "${work_dir}/${arch}/airootfs/usr/share/licenses/amd-ucode/LICENSE" "${work_dir}/iso/${install_dir}/boot/amd_ucode.LICENSE"
908 # Prepare /${install_dir}/boot/syslinux
910 if [[ ! ${kernel} = "core" ]]; then
911 _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel} | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
913 _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
915 mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux"
917 for _cfg in ${script_path}/syslinux/${arch}/*.cfg; do
918 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
919 s|%OS_NAME%|${os_name}|g;
920 s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}"
923 if [[ ${boot_splash} = true ]]; then
924 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
925 s|%OS_NAME%|${os_name}|g;
926 s|%INSTALL_DIR%|${install_dir}|g" \
927 "${script_path}/syslinux/${arch}/pxe-plymouth/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
929 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
930 s|%OS_NAME%|${os_name}|g;
931 s|%INSTALL_DIR%|${install_dir}|g" \
932 "${script_path}/syslinux/${arch}/sys-plymouth/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
934 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
935 s|%OS_NAME%|${os_name}|g;
936 s|%INSTALL_DIR%|${install_dir}|g" \
937 "${script_path}/syslinux/${arch}/pxe/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
939 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
940 s|%OS_NAME%|${os_name}|g;
941 s|%INSTALL_DIR%|${install_dir}|g" \
942 "${script_path}/syslinux/${arch}/sys/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
945 if [[ -f "${script_path}/channels/${channel_name}/splash.png" ]]; then
946 cp "${script_path}/channels/${channel_name}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
948 cp "${script_path}/syslinux/${arch}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
950 cp "${work_dir}"/${arch}/airootfs/usr/lib/syslinux/bios/*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux"
951 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux"
952 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux"
953 mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt"
954 gzip -c -9 "${work_dir}/${arch}/airootfs/usr/share/hwdata/pci.ids" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/pciids.gz"
955 gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz"
960 mkdir -p "${work_dir}/iso/isolinux"
962 sed "s|%INSTALL_DIR%|${install_dir}|g" \
963 "${script_path}/system/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg"
964 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/"
965 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/"
966 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/"
971 mkdir -p "${work_dir}/iso/EFI/boot"
972 cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/HashTool.efi" "${work_dir}/iso/EFI/boot/"
973 if [[ "${arch}" = "x86_64" ]]; then
974 cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/PreLoader.efi" "${work_dir}/iso/EFI/boot/bootx64.efi"
975 cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/iso/EFI/boot/loader.efi"
978 mkdir -p "${work_dir}/iso/loader/entries"
979 cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/iso/loader/"
980 cp "${script_path}/efiboot/loader/entries/uefi-shell-v2-${arch}.conf" "${work_dir}/iso/loader/entries/"
981 cp "${script_path}/efiboot/loader/entries/uefi-shell-v1-${arch}.conf" "${work_dir}/iso/loader/entries/"
983 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
984 s|%OS_NAME%|${os_name}|g;
985 s|%INSTALL_DIR%|${install_dir}|g" \
986 "${script_path}/efiboot/loader/entries/usb/archiso-${arch}-usb-${kernel}.conf" > "${work_dir}/iso/loader/entries/archiso-${arch}.conf"
988 # EFI Shell 2.0 for UEFI 2.3+
989 curl -o "${work_dir}/iso/EFI/shellx64_v2.efi" "https://raw.githubusercontent.com/tianocore/edk2/UDK2018/ShellBinPkg/UefiShell/X64/Shell.efi"
990 # EFI Shell 1.0 for non UEFI 2.3+
991 curl -o "${work_dir}/iso/EFI/shellx64_v1.efi" "https://raw.githubusercontent.com/tianocore/edk2/UDK2018/EdkShellBinPkg/FullShell/X64/Shell_Full.efi"
994 # Prepare efiboot.img::/EFI for "El Torito" EFI boot mode
996 mkdir -p "${work_dir}/iso/EFI/archiso"
997 truncate -s 64M "${work_dir}/iso/EFI/archiso/efiboot.img"
998 mkfs.fat -n ARCHISO_EFI "${work_dir}/iso/EFI/archiso/efiboot.img"
1000 mkdir -p "${work_dir}/efiboot"
1001 mount "${work_dir}/iso/EFI/archiso/efiboot.img" "${work_dir}/efiboot"
1003 mkdir -p "${work_dir}/efiboot/EFI/archiso"
1005 if [[ ! ${kernel} = "core" ]]; then
1006 cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}" "${work_dir}/efiboot/EFI/archiso/vmlinuz-linux-${kernel}.efi"
1008 cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz" "${work_dir}/efiboot/EFI/archiso/vmlinuz.efi"
1011 cp "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img" "${work_dir}/efiboot/EFI/archiso/archiso.img"
1013 cp "${work_dir}/iso/${install_dir}/boot/intel_ucode.img" "${work_dir}/efiboot/EFI/archiso/intel_ucode.img"
1014 cp "${work_dir}/iso/${install_dir}/boot/amd_ucode.img" "${work_dir}/efiboot/EFI/archiso/amd_ucode.img"
1016 mkdir -p "${work_dir}/efiboot/EFI/boot"
1017 cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/HashTool.efi" "${work_dir}/efiboot/EFI/boot/"
1019 if [[ "${arch}" = "x86_64" ]]; then
1020 cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/PreLoader.efi" "${work_dir}/efiboot/EFI/boot/bootx64.efi"
1021 cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/efiboot/EFI/boot/loader.efi"
1024 mkdir -p "${work_dir}/efiboot/loader/entries"
1025 cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/"
1026 cp "${script_path}/efiboot/loader/entries/uefi-shell-v2-${arch}.conf" "${work_dir}/efiboot/loader/entries/"
1027 cp "${script_path}/efiboot/loader/entries/uefi-shell-v1-${arch}.conf" "${work_dir}/efiboot/loader/entries/"
1029 #${script_path}/efiboot/loader/entries/archiso-${arch}-cd.conf
1031 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1032 s|%OS_NAME%|${os_name}|g;
1033 s|%INSTALL_DIR%|${install_dir}|g" \
1034 "${script_path}/efiboot/loader/entries/cd/archiso-${arch}-cd-${kernel}.conf" > "${work_dir}/efiboot/loader/entries/archiso-${arch}.conf"
1036 cp "${work_dir}/iso/EFI/shellx64_v2.efi" "${work_dir}/efiboot/EFI/"
1037 cp "${work_dir}/iso/EFI/shellx64_v1.efi" "${work_dir}/efiboot/EFI/"
1039 umount -d "${work_dir}/efiboot"
1042 # Build airootfs filesystem image
1044 cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}"
1045 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" pkglist
1046 pacman -Q --sysroot "${work_dir}/airootfs" > "${work_dir}/packages-full.list"
1047 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} -c "${sfs_comp}" -t "${sfs_comp_opt}" prepare
1048 remove "${work_dir}/airootfs"
1050 if [[ "${cleaning}" = true ]]; then
1051 remove "${work_dir}/${arch}/airootfs"
1057 arch=${arch} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" -A "${iso_application}" -o "${out_dir}" iso "${iso_filename}"
1059 if [[ ${cleaning} = true ]]; then
1060 remove "$(ls ${work_dir}/* | grep "build.make")"
1061 remove "${work_dir}/pacman.conf"
1062 remove "${work_dir}/efiboot"
1063 remove "${work_dir}/iso"
1064 remove "${work_dir}/${arch}"
1065 remove "${work_dir}/packages.list"
1066 remove "${work_dir}/packages-full.list"
1067 remove "${work_dir}/build_options"
1068 if [[ -z $(ls $(realpath "${work_dir}")/* ) ]]; then
1069 remove ${work_dir}/*
1072 _msg_info "The password for the live user and root is ${password}."
1077 while getopts 'w:o:g:p:c:t:hbk:xs:jlu:d-:' arg; do
1079 p) password="${OPTARG}" ;;
1080 w) work_dir="${OPTARG}" ;;
1081 o) out_dir="${OPTARG}" ;;
1082 g) gpg_key="${OPTARG}" ;;
1084 # compression format check.
1085 if [[ ${OPTARG} = "gzip" || ${OPTARG} = "lzma" || ${OPTARG} = "lzo" || ${OPTARG} = "lz4" || ${OPTARG} = "xz" || ${OPTARG} = "zstd" ]]; then
1086 sfs_comp="${OPTARG}"
1088 _msg_error "Invalid compressors ${arg}" "1"
1091 t) sfs_comp_opt=${OPTARG} ;;
1092 b) boot_splash=true ;;
1094 if [[ -n $(cat ${script_path}/system/kernel_list | grep -h -v ^'#' | grep -x "${OPTARG}") ]]; then
1097 _msg_error "Invalid kernel ${OPTARG}" "1"
1101 if [[ -f "${OPTARG}" ]]; then
1104 _msg_error "Invalid configuration file ${OPTARG}." "1"
1114 u) username="${OPTARG}" ;;
1119 noconfirm) noconfirm=true ;;
1121 _msg_error "Invalid argument '${OPTARG}'"
1127 _msg_error "Invalid argument '${arg}'"
1135 if [[ ${EUID} -ne 0 ]]; then
1136 _msg_warn "This script must be run as root." >&2
1137 # echo "Use -h to display script details." >&2
1139 _msg_warn "Re-run 'sudo ${0} ${@}'"
1145 # Show config message
1146 [[ -f "${script_path}"/config ]] && _msg_debug "The settings have been overwritten by the "${script_path}"/config."
1150 if [[ "${bash_debug}" = true ]]; then
1153 mkalteriso_option="${mkalteriso_option} -x"
1160 shift $((OPTIND - 1))
1162 if [[ -n "${1}" ]]; then
1166 # check_channel <channel name>
1171 for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
1172 if [[ -n $(ls "${script_path}"/channels/${i}) ]]; then
1173 if [[ ! ${i} = "share" ]]; then
1174 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1175 if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
1176 channel_list="${channel_list[@]} ${i}"
1179 channel_list="${channel_list[@]} ${i}"
1184 for i in ${channel_list[@]}; do
1185 if [[ $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1186 if [[ $(echo ${i} | sed 's/\.[^\.]*$//') = ${1} ]]; then
1191 if [[ ${i} = ${1} ]]; then
1197 if [[ "${channel_name}" = "rebuild" ]]; then
1206 if [[ $(check_channel "${channel_name}") = false ]]; then
1207 _msg_error "Invalid channel ${channel_name}" "1"
1210 if [[ -d "${script_path}"/channels/${channel_name}.add ]]; then
1211 channel_name="${channel_name}.add"
1212 elif [[ ${channel_name} = rebuild ]]; then
1213 if [[ -f "${work_dir}/build_options" ]]; then
1214 if [[ ! $(( OPTIND - 1 )) = 0 ]]; then
1215 if [[ $(( OPTIND - 1 )) = 1 ]] && [[ ${debug} = true ]]; then
1218 _msg_error "Options cannot be specified for the rebuild channel.All options will use the previous settings." "1"
1224 _msg_error "The previous build information is not in the working directory." "1"
1228 _msg_debug "channel path is ${script_path}/channels/${channel_name}"
1236 run_once make_pacman_conf
1237 run_once make_basefs
1238 run_once make_packages
1239 run_once make_customize_airootfs
1240 run_once make_setup_mkinitcpio
1242 run_once make_boot_extra
1243 run_once make_syslinux
1244 run_once make_isolinux
1246 run_once make_efiboot
1247 run_once make_prepare