5 # Email : hayao@fascode.net
7 # (c) 2019-2020 Fascode Network.
11 # The main script that runs the build
18 # Do not change these values.
19 script_path="$( cd -P "$( dirname "$(readlink -f "$0")" )" && pwd )"
20 defaultconfig="${script_path}/default.conf"
22 customized_username=false
26 if [[ -f "${defaultconfig}" ]]; then
27 source "${defaultconfig}"
29 echo "${defaultconfig} was not found."
38 # usage: echo_color -b <backcolor> -t <textcolor> -d <decoration> [Text]
61 # You can specify multiple decorations with ;.
62 # 0 => All attributs off (ノーマル)
64 # 4 => Underscore (下線)
66 # 7 => Reverse video on (色反転)
70 local backcolor textcolor decotypes echo_opts arg OPTIND OPT
72 while getopts 'b:t:d:n' arg; do
74 b) backcolor="${OPTARG}" ;;
75 t) textcolor="${OPTARG}" ;;
76 d) decotypes="${OPTARG}" ;;
77 n) echo_opts="-n -e" ;;
81 if [[ "${nocolor}" = false ]]; then
82 echo ${echo_opts} "\e[$([[ -v backcolor ]] && echo -n "${backcolor}"; [[ -v textcolor ]] && echo -n ";${textcolor}"; [[ -v decotypes ]] && echo -n ";${decotypes}")m${*}\e[m"
84 echo ${echo_opts} "${@}"
89 # Show an INFO message
92 if [[ "${msgdebug}" = false ]]; then
97 local echo_opts="-e" arg OPTIND OPT
98 while getopts 'n' arg; do
100 n) echo_opts="${echo_opts} -n" ;;
103 shift $((OPTIND - 1))
104 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '32' 'Info') ${*}"
105 if [[ "${bash_debug}" = true ]]; then
113 # Show an Warning message
116 if [[ "${msgdebug}" = false ]]; then
121 local echo_opts="-e" arg OPTIND OPT
122 while getopts 'n' arg; do
124 n) echo_opts="${echo_opts} -n" ;;
127 shift $((OPTIND - 1))
128 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '33' 'Warning') ${*}" >&2
129 if [[ "${bash_debug}" = true ]]; then
137 # Show an debug message
140 if [[ "${msgdebug}" = false ]]; then
145 local echo_opts="-e" arg OPTIND OPT
146 while getopts 'n' arg; do
148 n) echo_opts="${echo_opts} -n" ;;
151 shift $((OPTIND - 1))
152 if [[ ${debug} = true ]]; then
153 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '35' 'Debug') ${*}"
155 if [[ "${bash_debug}" = true ]]; then
163 # Show an ERROR message then exit with status
165 # $2: exit code number (with 0 does not exit)
167 if [[ "${msgdebug}" = false ]]; then
172 local echo_opts="-e" arg OPTIND OPT
173 while getopts 'n' arg; do
175 n) echo_opts="${echo_opts} -n" ;;
178 shift $((OPTIND - 1))
179 echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '31' 'Error') ${1}" >&2
180 if [[ -n "${2:-}" ]]; then
183 if [[ "${bash_debug}" = true ]]; then
192 echo "usage ${0} [options] [channel]"
194 echo " General options:"
196 echo " -b | --boot-splash Enable boot splash"
197 echo " Default: disable"
198 echo " -j | --japanese Enable Japanese mode."
199 echo " Default: disable"
200 echo " -l | --cleanup Enable post-build cleaning."
201 echo " Default: disable"
202 echo " -d | --debug Enable debug messages."
203 echo " Default: disable"
204 echo " -x | --bash-debug Enable bash debug mode.(set -xv)"
205 echo " Default: disable"
206 echo " -h | --help This help message and exit."
208 echo " -a | --arch <arch> Set iso architecture."
209 echo " Default: ${arch}"
210 echo " -c | <comp_type> Set SquashFS compression type (gzip, lzma, lzo, xz, zstd)"
211 echo " Default: ${sfs_comp}"
212 echo " -g | --gpgkey <key> Set gpg key"
213 echo " Default: ${gpg_key}"
214 echo " -k | --kernel <kernel> Set special kernel type.See below for available kernels."
215 echo " Default: ${kernel}"
216 echo " -o | --out <out_dir> Set the output directory"
217 echo " Default: ${out_dir}"
218 echo " -p | --password <password> Set a live user password"
219 echo " Default: ${password}"
220 echo " -t | --comp-opts <options> Set compressor-specific options."
221 echo " Default: empty"
222 echo " -u | --user <username> Set user name."
223 echo " Default: ${username}"
224 echo " -w | --work <work_dir> Set the working directory"
225 echo " Default: ${work_dir}"
227 echo " --gitversion Add Git commit hash to image file version"
228 echo " --msgdebug Enables output debugging."
229 echo " --nocolor No output colored output."
230 echo " --noconfirm No check the settings before building."
231 echo " --noloopmod No check and load kernel module automatically."
232 echo " --nodepend No check package dependencies before building."
233 echo " --shmkalteriso Use the shell script version of mkalteriso."
235 echo "A list of kernels available for each architecture."
239 for list in ${script_path}/system/kernel_list-* ; do
240 echo " ${list#${script_path}/system/kernel_list-}:"
242 for kernel in $(grep -h -v ^'#' ${list} | sed "/^$/d"); do
248 echo "You can switch between installed packages, files included in images, etc. by channel."
251 for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
252 if [[ -n $(ls "${script_path}"/channels/${i}) ]]; then
253 if [[ ! ${i} = "share" ]]; then
254 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
255 if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
256 channel_list="${channel_list[@]} ${i}"
259 channel_list="${channel_list[@]} ${i}"
264 channel_list="${channel_list[@]} rebuild"
267 for _channel in ${channel_list[@]}; do
268 if [[ -f "${script_path}/channels/${_channel}/description.txt" ]]; then
269 description=$(cat "${script_path}/channels/${_channel}/description.txt")
270 elif [[ "${_channel}" = "rebuild" ]]; then
271 description="Rebuild using the settings of the previous build."
273 description="This channel does not have a description.txt."
275 if [[ $(echo "${_channel}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
276 echo -ne " $(echo ${_channel} | sed 's/\.[^\.]*$//')"
277 for i in $( seq 1 $(( ${blank} - ${#_channel} )) ); do
281 echo -ne " ${_channel}"
282 for i in $( seq 1 $(( ${blank} - 4 - ${#_channel} )) ); do
286 echo -ne "${description}\n"
289 if [[ -n "${1:-}" ]]; then
298 for mount in $(mount | awk '{print $3}' | grep $(realpath ${work_dir}) | tac); do
299 _msg_info "Unmounting ${mount}"
300 umount -lf "${mount}"
304 # Helper function to run make_*() only one time.
306 if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then
307 _msg_debug "Running $1 ..."
309 touch "${work_dir}/build.${1}_${arch}"
312 _msg_debug "Skipped because ${1} has already been executed."
318 # Delete the file if it exists.
319 # For directories, rm -rf is used.
320 # If the file does not exist, skip it.
321 # remove <file> <file> ...
323 local _list=($(echo "$@")) _file
324 for _file in "${_list[@]}"; do
325 if [[ -f ${_file} ]]; then
326 _msg_debug "Removeing ${_file}"
328 elif [[ -d ${_file} ]]; then
329 _msg_debug "Removeing ${_file}"
340 _msg_error "It was killed by the user."
341 _msg_error "The process may not have completed successfully."
346 # load_config [file1] [file2] ...
350 if [[ -f "${file}" ]]; then
352 _msg_debug "The settings have been overwritten by the ${file}"
358 # Display channel list
359 show_channel_list() {
361 for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
362 if [[ -n $(ls "${script_path}"/channels/${i}) ]] && [[ ! ${i} = "share" ]]; then
363 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
364 if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
377 # Preparation for build
380 if [[ "${shmkalteriso}" = false ]]; then
381 mkalteriso="${script_path}/system/mkalteriso"
383 _msg_info "Building mkalteriso..."
384 if [[ "${debug}" = true ]]; then
388 make mkalteriso > /dev/null 2>&1
390 cd - > /dev/null 2>&1
392 mkalteriso="${script_path}/system/mkalteriso.sh"
395 # Create a working directory.
396 [[ ! -d "${work_dir}" ]] && mkdir -p "${work_dir}"
400 if [[ -n $(ls -a "${work_dir}" 2> /dev/null | grep -xv ".." | grep -xv ".") ]] && [[ ! "${rebuild}" = true ]]; then
402 _msg_info "Deleting the contents of ${work_dir}..."
403 remove "${work_dir%/}"/*
407 # 強制終了時に作業ディレクトリを削除する
408 local trap_remove_work
415 trap 'trap_remove_work' 1 2 3 15
420 local out_file="${rebuildfile}"
422 echo "#!/usr/bin/env bash" > "${out_file}"
423 echo "# Build options are stored here." >> "${out_file}"
425 echo -n "${i}=" >> "${out_file}"
426 echo -n '"' >> "${out_file}"
427 eval echo -n '$'{${i}} >> "${out_file}"
428 echo '"' >> "${out_file}"
431 if [[ ${rebuild} = false ]]; then
432 # If there is pacman.conf for each channel, use that for building
433 if [[ -f "${script_path}/channels/${channel_name}/pacman-${arch}.conf" ]]; then
434 build_pacman_conf="${script_path}/channels/${channel_name}/pacman-${arch}.conf"
437 # If there is config for share channel. load that.
438 load_config "${script_path}/channels/share/config.any"
439 load_config ${script_path}/channels/share/config.${arch}
441 # If there is config for each channel. load that.
442 load_config "${script_path}/channels/${channel_name}/config.any"
443 load_config "${script_path}/channels/${channel_name}/config.${arch}"
446 if [[ "${customized_username}" = false ]]; then
447 username="${defaultusername}"
451 if [[ "${gitversion}" = true ]]; then
453 iso_version=${iso_version}-$(git rev-parse --short HEAD)
454 cd - > /dev/null 2>&1
457 # Generate iso file name.
459 if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
460 _channel_name="$(echo ${channel_name} | sed 's/\.[^\.]*$//')"
462 _channel_name="${channel_name}"
464 if [[ "${japanese}" = true ]]; then
465 _channel_name="${_channel_name}-jp"
467 if [[ "${nochname}" = true ]]; then
468 iso_filename="${iso_name}-${iso_version}-${arch}.iso"
470 iso_filename="${iso_name}-${_channel_name}-${iso_version}-${arch}.iso"
472 _msg_debug "Iso filename is ${iso_filename}"
474 # Save the value of the variable for use in rebuild.
509 customized_username \
514 load_config "${rebuildfile}"
515 _msg_debug "Iso filename is ${iso_filename}"
517 # Delete the lock file.
518 # remove "$(ls ${work_dir}/* | grep "build.make")"
523 for mount in $(mount | awk '{print $3}' | grep $(realpath ${work_dir})); do
524 _msg_info "Unmounting ${mount}"
529 if [[ "${nodepend}" = false ]] && [[ "${arch}" = $(uname -m) ]] ; then
533 local check_failed=false
536 installed_pkg=($(pacman -Q | awk '{print $1}'))
537 installed_ver=($(pacman -Q | awk '{print $2}'))
542 for i in $(seq 0 $(( ${#installed_pkg[@]} - 1 ))); do
543 if [[ "${installed_pkg[${i}]}" = ${1} ]]; then
544 ver=$(pacman -Sp --print-format '%v' --config ${build_pacman_conf} ${1} 2> /dev/null)
545 if [[ "${installed_ver[${i}]}" = "${ver}" ]]; then
548 elif [[ -z ${ver} ]]; then
560 if [[ ${debug} = false ]]; then
561 _msg_info "Checking dependencies ..."
565 for pkg in ${dependence[@]}; do
566 _msg_debug -n "Checking ${pkg} ..."
567 case $(check_pkg ${pkg}) in
569 [[ "${debug}" = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n"
570 _msg_warn "${pkg} is not the latest package."
571 _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)"
574 [[ "${debug}" = true ]] && echo
575 _msg_error "${pkg} is not installed." ; check_failed=true
578 [[ "${debug}" = true ]] && echo
579 _msg_warn "${pkg} is not a repository package."
581 "installed") [[ ${debug} = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n" ;;
585 if [[ "${check_failed}" = true ]]; then
590 # Load loop kernel module
591 if [[ "${noloopmod}" = false ]]; then
592 if [[ ! -d "/usr/lib/modules/$(uname -r)" ]]; then
593 _msg_error "The currently running kernel module could not be found."
594 _msg_error "Probably the system kernel has been updated."
595 _msg_error "Reboot your system to run the latest kernel." "1"
597 if [[ -z $(lsmod | awk '{print $1}' | grep -x "loop") ]]; then
606 _msg_info "mkalteriso path is ${mkalteriso}"
608 if [[ "${boot_splash}" = true ]]; then
609 _msg_info "Boot splash is enabled."
610 _msg_info "Theme is used ${theme_name}."
612 _msg_info "Use the ${kernel} kernel."
613 _msg_info "Live username is ${username}."
614 _msg_info "Live user password is ${password}."
615 _msg_info "The compression method of squashfs is ${sfs_comp}."
616 if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
617 _msg_info "Use the $(echo ${channel_name} | sed 's/\.[^\.]*$//') channel."
619 _msg_info "Use the ${channel_name} channel."
621 [[ "${japanese}" = true ]] && _msg_info "Japanese mode has been activated."
622 _msg_info "Build with architecture ${arch}."
624 if [[ ${noconfirm} = false ]]; then
625 echo "Press Enter to continue or Ctrl + C to cancel."
629 trap 'umount_trap' 1 2 3 15
633 # Setup custom pacman.conf with current cache directories.
635 _msg_debug "Use ${build_pacman_conf}"
637 _cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g'))
638 sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${_cache_dirs[@]})|g" ${build_pacman_conf} > "${work_dir}/pacman-${arch}.conf"
641 # Base installation (airootfs)
643 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" init
646 if [[ "${boot_splash}" = true ]]; then
647 if [[ -n "${theme_pkg}" ]]; then
648 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "plymouth ${theme_pkg}" install
650 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "plymouth" install
655 if [[ ! "${kernel}" = "core" ]]; then
656 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "linux-${kernel} linux-${kernel}-headers broadcom-wl-dkms" install
658 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "linux linux-headers broadcom-wl" install
662 # Additional packages (airootfs)
664 # インストールするパッケージのリストを読み込み、配列pkglistに代入します。
667 local _loadfilelist _pkg _file jplist excludefile excludelist _pkglist
669 #-- Detect package list to load --#
670 # Append the file in the share directory to the file to be read.
672 # Package list for Japanese
673 jplist="${script_path}/channels/share/packages.${arch}/jp.${arch}"
675 # Package list for non-Japanese
676 nojplist="${script_path}/channels/share/packages.${arch}/non-jp.${arch}"
678 if [[ "${japanese}" = true ]]; then
679 _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
681 _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${jplist}"))
685 # Add the files for each channel to the list of files to read.
687 # Package list for Japanese
688 jplist="${script_path}/channels/${channel_name}/packages.${arch}/jp.${arch}"
690 # Package list for non-Japanese
691 nojplist="${script_path}/channels/${channel_name}/packages.${arch}/non-jp.${arch}"
693 if [[ "${japanese}" = true ]]; then
694 # If Japanese is enabled, add it to the list of files to read other than non-jp.
695 _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
697 # If Japanese is disabled, add it to the list of files to read other than jp.
698 _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv ${jplist}))
702 #-- Read package list --#
703 # Read the file and remove comments starting with # and add it to the list of packages to install.
704 for _file in ${_loadfilelist[@]}; do
705 _msg_debug "Loaded package file ${_file}"
706 pkglist=( ${pkglist[@]} "$(grep -h -v ^'#' ${_file} | sed ':a;N;$!ba;s/\n/ /g')" )
708 if [[ ${debug} = true ]]; then
712 # Exclude packages from the share exclusion list
713 excludefile="${script_path}/channels/share/packages.${arch}/exclude"
714 if [[ -f "${excludefile}" ]]; then
715 excludelist=( $(grep -h -v ^'#' "${excludefile}" | sed ':a;N;$!ba;s/\n/ /g') )
718 _pkglist=(${pkglist[@]})
720 for _pkg in ${_pkglist[@]}; do
721 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
722 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
723 pkglist=(${pkglist[@]} "${_pkg}")
728 if [[ -n "${excludelist}" ]]; then
729 _msg_debug "The following packages have been removed from the installation list."
730 _msg_debug "Excluded packages:" "${excludelist[@]}"
733 # Exclude packages from the exclusion list for each channel
734 excludefile="${script_path}/channels/${channel_name}/packages.${arch}/exclude"
735 if [[ -f "${excludefile}" ]]; then
736 excludelist=( $(grep -h -v ^'#' "${excludefile}" | sed ':a;N;$!ba;s/\n/ /g') )
739 _pkglist=(${pkglist[@]})
741 for _pkg in ${_pkglist[@]}; do
742 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
743 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
744 pkglist=(${pkglist[@]} "${_pkg}")
749 # Sort the list of packages in abc order.
752 for _pkg in ${pkglist[@]}; do
764 # _msg_debug "${pkglist[@]}"
766 # Create a list of packages to be finally installed as packages.list directly under the working directory.
767 echo "# The list of packages that is installed in live cd." > ${work_dir}/packages.list
768 echo "#" >> ${work_dir}/packages.list
769 echo >> ${work_dir}/packages.list
770 for _pkg in ${pkglist[@]}; do
771 echo ${_pkg} >> ${work_dir}/packages.list
774 # Install packages on airootfs
775 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "${pkglist[*]}" install
778 # Customize installation (airootfs)
779 make_customize_airootfs() {
780 # Overwrite airootfs with customize_airootfs.
787 if [[ -d "${_dir}" ]]; then
788 cp -af --no-preserve=ownership "${_dir}"/* "${work_dir}/${arch}/airootfs"
793 copy_airootfs "${script_path}/channels/share/airootfs.any"
794 copy_airootfs "${script_path}/channels/share/airootfs.${arch}"
795 copy_airootfs "${script_path}/channels/${channel_name}/airootfs.any"
796 copy_airootfs "${script_path}/channels/${channel_name}/airootfs.${arch}"
798 # Replace /etc/mkinitcpio.conf if Plymouth is enabled.
799 if [[ "${boot_splash}" = true ]]; then
800 cp "${script_path}/mkinitcpio/mkinitcpio-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio.conf"
804 # customize_airootfs.sh options
805 # -b : Enable boot splash.
806 # -d : Enable debug mode.
807 # -i <inst_dir> : Set install dir
808 # -j : Enable Japanese.
809 # -k <kernel> : Set kernel name.
810 # -o <os name> : Set os name.
811 # -p <password> : Set password.
812 # -s <shell> : Set user shell.
813 # -t : Set plymouth theme.
814 # -u <username> : Set live user name.
815 # -x : Enable bash debug mode.
816 # -r : Enable rebuild.
819 # Generate options of customize_airootfs.sh.
820 local addition_options
823 if [[ ${boot_splash} = true ]]; then
824 if [[ -z ${theme_name} ]]; then
825 addition_options="${addition_options} -b"
827 addition_options="${addition_options} -b -t ${theme_name}"
830 if [[ ${debug} = true ]]; then
831 addition_options="${addition_options} -d"
833 if [[ ${bash_debug} = true ]]; then
834 addition_options="${addition_options} -x"
836 if [[ ${japanese} = true ]]; then
837 addition_options="${addition_options} -j"
839 if [[ ${rebuild} = true ]]; then
840 addition_options="${addition_options} -r"
843 share_options="-p '${password}' -k '${kernel}' -u '${username}' -o '${os_name}' -i '${install_dir}' -s '${usershell}' -a '${arch}'"
847 if [[ -f ${work_dir}/${arch}/airootfs/root/customize_airootfs.sh ]]; then
848 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
850 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then
851 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
853 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
854 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
855 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
856 chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh"
859 # Execute customize_airootfs.sh.
860 if [[ -z ${addition_options} ]]; then
861 ${mkalteriso} ${mkalteriso_option} \
862 -w "${work_dir}/${arch}" \
863 -C "${work_dir}/pacman-${arch}.conf" \
864 -D "${install_dir}" \
865 -r "/root/customize_airootfs.sh ${share_options}" \
867 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
868 ${mkalteriso} ${mkalteriso_option} \
869 -w "${work_dir}/${arch}" \
870 -C "${work_dir}/pacman-${arch}.conf" \
871 -D "${install_dir}" \
872 -r "/root/customize_airootfs_${channel_name}.sh ${share_options}" \
874 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
875 ${mkalteriso} ${mkalteriso_option} \
876 -w "${work_dir}/${arch}" \
877 -C "${work_dir}/pacman-${arch}.conf" \
878 -D "${install_dir}" \
879 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options}" \
883 ${mkalteriso} ${mkalteriso_option} \
884 -w "${work_dir}/${arch}" \
885 -C "${work_dir}/pacman-${arch}.conf" \
886 -D "${install_dir}" \
887 -r "/root/customize_airootfs.sh ${share_options} ${addition_options}" \
890 if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
891 ${mkalteriso} ${mkalteriso_option} \
892 -w "${work_dir}/${arch}" \
893 -C "${work_dir}/pacman-${arch}.conf" \
894 -D "${install_dir}" \
895 -r "/root/customize_airootfs_${channel_name}.sh ${share_options} ${addition_options}" \
897 elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
898 ${mkalteriso} ${mkalteriso_option} \
899 -w "${work_dir}/${arch}" \
900 -C "${work_dir}/pacman-${arch}.conf" \
901 -D "${install_dir}" \
902 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options} ${addition_options}" \
908 # Delete customize_airootfs.sh.
909 remove "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
910 remove "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
913 # https://github.com/archlinux/archiso/commit/d39e2ba41bf556674501062742190c29ee11cd59
914 chmod -f 750 "${work_dir}/x86_64/airootfs/root"
917 # Copy mkinitcpio archiso hooks and build initramfs (airootfs)
918 make_setup_mkinitcpio() {
920 mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
921 mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/install"
922 for _hook in "archiso" "archiso_shutdown" "archiso_pxe_common" "archiso_pxe_nbd" "archiso_pxe_http" "archiso_pxe_nfs" "archiso_loop_mnt"; do
923 cp "${script_path}/system/initcpio/hooks/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
924 cp "${script_path}/system/initcpio/install/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
926 sed -i "s|/usr/lib/initcpio/|/etc/initcpio/|g" "${work_dir}/${arch}/airootfs/etc/initcpio/install/archiso_shutdown"
927 cp "${script_path}/system/initcpio/install/archiso_kms" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
928 cp "${script_path}/system/initcpio/archiso_shutdown" "${work_dir}/${arch}/airootfs/etc/initcpio"
929 if [[ "${boot_splash}" = true ]]; then
930 cp "${script_path}/mkinitcpio/mkinitcpio-archiso-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
932 cp "${script_path}/mkinitcpio/mkinitcpio-archiso.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
935 if [[ "${gpg_key}" ]]; then
936 gpg --export "${gpg_key}" >"${work_dir}/gpgkey"
937 exec 17<>"${work_dir}/gpgkey"
940 if [[ ! ${kernel} = "core" ]]; then
941 ARCHISO_GNUPG_FD=${gpg_key:+17} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -r "mkinitcpio -c /etc/mkinitcpio-archiso.conf -k /boot/vmlinuz-linux-${kernel} -g /boot/archiso.img" run
943 ARCHISO_GNUPG_FD=${gpg_key:+17} ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -r 'mkinitcpio -c /etc/mkinitcpio-archiso.conf -k /boot/vmlinuz-linux -g /boot/archiso.img' run
946 if [[ "${gpg_key}" ]]; then
951 # Prepare kernel/initramfs ${install_dir}/boot/
953 mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}"
954 cp "${work_dir}/${arch}/airootfs/boot/archiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img"
956 if [[ ! "${kernel}" = "core" ]]; then
957 cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel}" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}"
959 cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux"
963 # Add other aditional/extra files to ${install_dir}/boot/
965 if [[ -e "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" ]]; then
966 cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest"
967 cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" "${work_dir}/iso/${install_dir}/boot/memtest.COPYING"
969 if [[ -e "${work_dir}/${arch}/airootfs/boot/intel-ucode.img" ]]; then
970 cp "${work_dir}/${arch}/airootfs/boot/intel-ucode.img" "${work_dir}/iso/${install_dir}/boot/intel_ucode.img"
971 cp "${work_dir}/${arch}/airootfs/usr/share/licenses/intel-ucode/LICENSE" "${work_dir}/iso/${install_dir}/boot/intel_ucode.LICENSE"
973 if [[ -e "${work_dir}/${arch}/airootfs/boot/amd-ucode.img" ]]; then
974 cp "${work_dir}/${arch}/airootfs/boot/amd-ucode.img" "${work_dir}/iso/${install_dir}/boot/amd_ucode.img"
975 cp "${work_dir}/${arch}/airootfs/usr/share/licenses/amd-ucode/LICENSE.amd-ucode" "${work_dir}/iso/${install_dir}/boot/amd_ucode.LICENSE"
979 # Prepare /${install_dir}/boot/syslinux
981 if [[ ! ${kernel} = "core" ]]; then
982 _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel} | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
984 _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
986 mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux"
988 for _cfg in ${script_path}/syslinux/${arch}/*.cfg; do
989 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
990 s|%OS_NAME%|${os_name}|g;
991 s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}"
994 if [[ ${boot_splash} = true ]]; then
995 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
996 s|%OS_NAME%|${os_name}|g;
997 s|%INSTALL_DIR%|${install_dir}|g" \
998 "${script_path}/syslinux/${arch}/pxe-plymouth/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
1000 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1001 s|%OS_NAME%|${os_name}|g;
1002 s|%INSTALL_DIR%|${install_dir}|g" \
1003 "${script_path}/syslinux/${arch}/sys-plymouth/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
1005 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1006 s|%OS_NAME%|${os_name}|g;
1007 s|%INSTALL_DIR%|${install_dir}|g" \
1008 "${script_path}/syslinux/${arch}/pxe/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
1010 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1011 s|%OS_NAME%|${os_name}|g;
1012 s|%INSTALL_DIR%|${install_dir}|g" \
1013 "${script_path}/syslinux/${arch}/sys/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
1016 if [[ -f "${script_path}/channels/${channel_name}/splash.png" ]]; then
1017 cp "${script_path}/channels/${channel_name}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
1019 cp "${script_path}/syslinux/${arch}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
1021 cp "${work_dir}"/${arch}/airootfs/usr/lib/syslinux/bios/*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux"
1022 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux"
1023 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux"
1024 mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt"
1025 gzip -c -9 "${work_dir}/${arch}/airootfs/usr/share/hwdata/pci.ids" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/pciids.gz"
1026 gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz"
1031 mkdir -p "${work_dir}/iso/isolinux"
1033 sed "s|%INSTALL_DIR%|${install_dir}|g" \
1034 "${script_path}/system/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg"
1035 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/"
1036 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/"
1037 cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/"
1042 mkdir -p "${work_dir}/iso/EFI/boot"
1043 cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/iso/EFI/boot/bootx64.efi"
1045 mkdir -p "${work_dir}/iso/loader/entries"
1046 cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/iso/loader/"
1048 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1049 s|%OS_NAME%|${os_name}|g;
1050 s|%INSTALL_DIR%|${install_dir}|g" \
1051 "${script_path}/efiboot/loader/entries/usb/archiso-x86_64-usb-${kernel}.conf" > "${work_dir}/iso/loader/entries/archiso-x86_64.conf"
1053 # edk2-shell based UEFI shell
1054 # shellx64.efi is picked up automatically when on /
1055 cp "${work_dir}/x86_64/airootfs/usr/share/edk2-shell/x64/Shell_Full.efi" "${work_dir}/iso/shellx64.efi"
1058 # Prepare efiboot.img::/EFI for "El Torito" EFI boot mode
1060 mkdir -p "${work_dir}/iso/EFI/archiso"
1061 truncate -s 64M "${work_dir}/iso/EFI/archiso/efiboot.img"
1062 mkfs.fat -n ARCHISO_EFI "${work_dir}/iso/EFI/archiso/efiboot.img"
1064 mkdir -p "${work_dir}/efiboot"
1065 mount "${work_dir}/iso/EFI/archiso/efiboot.img" "${work_dir}/efiboot"
1067 mkdir -p "${work_dir}/efiboot/EFI/archiso"
1069 if [[ ! ${kernel} = "core" ]]; then
1070 cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}" "${work_dir}/efiboot/EFI/archiso/vmlinuz-linux-${kernel}.efi"
1072 cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz" "${work_dir}/efiboot/EFI/archiso/vmlinuz.efi"
1075 cp "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img" "${work_dir}/efiboot/EFI/archiso/archiso.img"
1077 cp "${work_dir}/iso/${install_dir}/boot/intel_ucode.img" "${work_dir}/efiboot/EFI/archiso/intel_ucode.img"
1078 cp "${work_dir}/iso/${install_dir}/boot/amd_ucode.img" "${work_dir}/efiboot/EFI/archiso/amd_ucode.img"
1080 mkdir -p "${work_dir}/efiboot/EFI/boot"
1081 cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/efiboot/EFI/boot/bootx64.efi"
1083 mkdir -p "${work_dir}/efiboot/loader/entries"
1084 cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/"
1087 sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1088 s|%OS_NAME%|${os_name}|g;
1089 s|%INSTALL_DIR%|${install_dir}|g" \
1090 "${script_path}/efiboot/loader/entries/cd/archiso-x86_64-cd-${kernel}.conf" > "${work_dir}/efiboot/loader/entries/archiso-x86_64.conf"
1092 # shellx64.efi is picked up automatically when on /
1093 cp "${work_dir}/iso/shellx64.efi" "${work_dir}/efiboot/"
1095 umount -d "${work_dir}/efiboot"
1098 # Build airootfs filesystem image
1100 cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}"
1101 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" pkglist
1102 pacman -Q --sysroot "${work_dir}/airootfs" > "${work_dir}/packages-full.list"
1103 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} -c "${sfs_comp}" -t "${sfs_comp_opt}" prepare
1104 remove "${work_dir}/airootfs"
1106 if [[ "${cleaning}" = true ]]; then
1107 remove "${work_dir}/${arch}/airootfs"
1113 ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" -A "${iso_application}" -o "${out_dir}" iso "${iso_filename}"
1114 _msg_info "The password for the live user and root is ${password}."
1120 _opt_short="a:bc:dg:hjk:lo:p:t:u:w:x"
1121 _opt_long="arch:,boot-splash,comp-type:,debug,gpgkey:,help,japanese,kernel:,cleaning,out:,password:,comp-opts:,user:,work:,bash-debug,nocolor,noconfirm,nodepend,gitversion,shmkalteriso,msgdebug,noloopmod,channellist"
1122 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- "${@}")
1123 if [[ ${?} != 0 ]]; then
1127 eval set -- "${OPT}"
1128 unset OPT _opt_short _opt_long
1142 "gzip" | "lzma" | "lzo" | "lz4" | "xz" | "zstd") sfs_comp="${2}" ;;
1143 *) _msg_error "Invaild compressors '${2}'" '1' ;;
1164 if [[ -n $(cat ${script_path}/system/kernel_list-${arch} | grep -h -v ^'#' | sed "/^$/d" | grep -x "${2}") ]]; then
1167 _msg_error "Invalid kernel ${2}" "1"
1188 customized_username=true
1189 username="$(echo -n "${2}" | sed 's/ //g' |tr '[A-Z]' '[a-z]')"
1214 if [[ -d "${script_path}/.git" ]]; then
1217 _msg_error "There is no git directory. You need to use git clone to use this feature." "1"
1242 _msg_error "Invalid argument '${1}'"
1250 if [[ ${EUID} -ne 0 ]]; then
1251 _msg_warn "This script must be run as root." >&2
1252 # echo "Use -h to display script details." >&2
1254 _msg_warn "Re-run 'sudo ${0} ${options}'"
1255 sudo ${0} ${options}
1259 # Show alteriso version
1260 if [[ -d "${script_path}/.git" ]]; then
1262 _msg_debug "The version of alteriso is $(git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g')."
1263 cd - > /dev/null 2>&1
1266 # Show config message
1267 [[ -f "${defaultconfig}" ]] && _msg_debug "Use the default configuration file (${defaultconfig})."
1270 mkalteriso_option="-a ${arch} -v"
1271 if [[ "${bash_debug}" = true ]]; then
1273 mkalteriso_option="${mkalteriso_option} -x"
1276 # Pacman configuration file used only when building
1277 build_pacman_conf="${script_path}/system/pacman-${arch}.conf"
1279 # Set rebuild config file
1280 rebuildfile="${work_dir}/build_options"
1285 if [[ -n "${1}" ]]; then
1289 # check_channel <channel name>
1294 for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
1295 if [[ -n $(ls "${script_path}"/channels/${i}) ]] && [[ ! ${i} = "share" ]]; then
1296 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1297 if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
1298 channel_list="${channel_list[@]} ${i}"
1301 channel_list="${channel_list[@]} ${i}"
1305 for i in ${channel_list[@]}; do
1306 if [[ $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1307 if [[ $(echo ${i} | sed 's/\.[^\.]*$//') = ${1} ]]; then
1312 if [[ ${i} = ${1} ]]; then
1318 if [[ "${channel_name}" = "rebuild" ]] || [[ "${channel_name}" = "clean" ]]; then
1327 if [[ $(check_channel "${channel_name}") = false ]]; then
1328 _msg_error "Invalid channel ${channel_name}" "1"
1331 if [[ -d "${script_path}"/channels/${channel_name}.add ]]; then
1332 channel_name="${channel_name}.add"
1333 elif [[ "${channel_name}" = "rebuild" ]]; then
1334 if [[ -f "${rebuildfile}" ]]; then
1337 _msg_error "The previous build information is not in the working directory." "1"
1341 if [[ ! "${channel_name}" == "rebuild" ]] && [[ ! "${channel_name}" == "clean" ]]; then
1342 _msg_debug "channel path is ${script_path}/channels/${channel_name}"
1346 # Check architecture and kernel for each channel
1347 if [[ ! "${channel_name}" = "rebuild" ]] && [[ ! "${channel_name}" = "clean" ]]; then
1349 if [[ -z $(cat "${script_path}/channels/${channel_name}/architecture" | grep -h -v ^'#' | sed "/^$/d" | grep -x "${arch}") ]]; then
1350 _msg_error "${channel_name} channel does not support current architecture (${arch})." "1"
1354 if [[ -f "${script_path}/channels/${channel_name}/kernel_list-${arch}" ]]; then
1355 if [[ -z $(cat "${script_path}/channels/${channel_name}/kernel_list-${arch}" | grep -h -v ^'#' | sed "/^$/d" | grep -x "${kernel}") ]]; then
1356 _msg_error "This kernel is currently not supported on this channel." "1"
1362 if [[ "${channel_name}" = "clean" ]]; then
1364 remove "${script_path}/menuconfig/build"
1365 remove "${script_path}/system/cpp-src/mkalteriso/build"
1366 remove "${script_path}/menuconfig-script/kernel_choice"
1367 remove "${work_dir%/}"/*
1368 remove "${work_dir}"
1369 remove "${rebuildfile}"
1370 remove "${script_path}/temp"
1374 # Check the value of a variable that can only be set to true or false.
1376 local _value="$(eval echo '$'${1})"
1377 _msg_debug -n "Checking ${1}..."
1378 if [[ "${debug}" = true ]]; then
1379 echo -e " ${_value}"
1381 if [[ ! -v "${1}" ]]; then
1382 echo; _msg_error "The variable name ${1} is empty." "1"
1383 elif [[ ! "${_value}" = "true" ]] && [[ ! "${_value}" = "false" ]]; then
1384 echo; _msg_error "The variable name ${1} is not of bool type." "1"
1388 if [[ "${debug}" = true ]]; then
1391 check_bool boot_splash
1393 check_bool bash_debug
1397 check_bool noconfirm
1400 check_bool shmkalteriso
1402 check_bool customized_username
1403 check_bool noloopmod
1406 if [[ "${debug}" = true ]]; then
1414 run_once make_pacman_conf
1415 run_once make_basefs
1416 run_once make_packages
1417 run_once make_customize_airootfs
1418 run_once make_setup_mkinitcpio
1420 run_once make_boot_extra
1421 run_once make_syslinux
1422 run_once make_isolinux
1424 run_once make_efiboot
1425 run_once make_prepare
1428 if [[ "${cleaning}" = true ]]; then
1429 remove "${work_dir}"