OSDN Git Service

[change] : Changed script name.
[alterlinux/alterlinux.git] / build.sh
1 #!/usr/bin/env bash
2 #
3 # Yamada Hayao
4 # Twitter: @Hayao0819
5 # Email  : hayao@fascode.net
6 #
7 # (c) 2019-2020 Fascode Network.
8 #
9 # build.sh
10 #
11 # The main script that runs the build
12 #
13
14 set -e
15 set -u
16
17 # Internal config
18 # Do not change these values.
19 script_path="$(readlink -f ${0%/*})"
20 defaultconfig="${script_path}/default.conf"
21 rebuild=false
22 customized_username=false
23
24
25 # Load config file
26 if [[ -f "${defaultconfig}" ]]; then
27     source "${defaultconfig}"
28 else
29     echo "${defaultconfig} was not found."
30     exit 1
31 fi
32
33
34 umask 0022
35
36
37 # Color echo
38 # usage: echo_color -b <backcolor> -t <textcolor> -d <decoration> [Text]
39 #
40 # Text Color
41 # 30 => Black
42 # 31 => Red
43 # 32 => Green
44 # 33 => Yellow
45 # 34 => Blue
46 # 35 => Magenta
47 # 36 => Cyan
48 # 37 => White
49 #
50 # Background color
51 # 40 => Black
52 # 41 => Red
53 # 42 => Green
54 # 43 => Yellow
55 # 44 => Blue
56 # 45 => Magenta
57 # 46 => Cyan
58 # 47 => White
59 #
60 # Text decoration
61 # You can specify multiple decorations with ;.
62 # 0 => All attributs off (ノーマル)
63 # 1 => Bold on (太字)
64 # 4 => Underscore (下線)
65 # 5 => Blink on (点滅)
66 # 7 => Reverse video on (色反転)
67 # 8 => Concealed on
68
69 echo_color() {
70     local backcolor
71     local textcolor
72     local decotypes
73     local echo_opts
74     local arg
75     local OPTIND
76     local OPT
77
78     echo_opts="-e"
79
80     while getopts 'b:t:d:n' arg; do
81         case "${arg}" in
82             b) backcolor="${OPTARG}" ;;
83             t) textcolor="${OPTARG}" ;;
84             d) decotypes="${OPTARG}" ;;
85             n) echo_opts="-n -e"     ;;
86         esac
87     done
88
89     shift $((OPTIND - 1))
90
91     if [[ "${nocolor}" = false ]]; then
92         echo ${echo_opts} "\e[$([[ -v backcolor ]] && echo -n "${backcolor}"; [[ -v textcolor ]] && echo -n ";${textcolor}"; [[ -v decotypes ]] && echo -n ";${decotypes}")m${@}\e[m"
93     else
94         echo ${echo_opts} "${@}"
95     fi
96 }
97
98
99 # Show an INFO message
100 # $1: message string
101 _msg_info() {
102     if [[ "${msgdebug}" = false ]]; then
103         set +xv
104     else
105         set -xv
106     fi
107     local echo_opts="-e"
108     local arg
109     local OPTIND
110     local OPT
111     while getopts 'n' arg; do
112         case "${arg}" in
113             n) echo_opts="${echo_opts} -n" ;;
114         esac
115     done
116     shift $((OPTIND - 1))
117     echo ${echo_opts} "$( echo_color -t '36' '[build.sh]')    $( echo_color -t '32' 'Info') ${@}"
118     if [[ "${bash_debug}" = true ]]; then
119         set -xv
120     else
121         set +xv
122     fi
123 }
124
125
126 # Show an Warning message
127 # $1: message string
128 _msg_warn() {
129     if [[ "${msgdebug}" = false ]]; then
130         set +xv
131     else
132         set -xv
133     fi
134     local echo_opts="-e"
135     local arg
136     local OPTIND
137     local OPT
138     while getopts 'n' arg; do
139         case "${arg}" in
140             n) echo_opts="${echo_opts} -n" ;;
141         esac
142     done
143     shift $((OPTIND - 1))
144     echo ${echo_opts} "$( echo_color -t '36' '[build.sh]') $( echo_color -t '33' 'Warning') ${@}" >&2
145     if [[ "${bash_debug}" = true ]]; then
146         set -xv
147     else
148         set +xv
149     fi
150 }
151
152
153 # Show an debug message
154 # $1: message string
155 _msg_debug() {
156     if [[ "${msgdebug}" = false ]]; then
157         set +xv
158     else
159         set -xv
160     fi
161     local echo_opts="-e"
162     local arg
163     local OPTIND
164     local OPT
165     while getopts 'n' arg; do
166         case "${arg}" in
167             n) echo_opts="${echo_opts} -n" ;;
168         esac
169     done
170     shift $((OPTIND - 1))
171     if [[ ${debug} = true ]]; then
172         echo ${echo_opts} "$( echo_color -t '36' '[build.sh]')   $( echo_color -t '35' 'Debug') ${@}"
173     fi
174     if [[ "${bash_debug}" = true ]]; then
175         set -xv
176     else
177         set +xv
178     fi
179 }
180
181
182 # Show an ERROR message then exit with status
183 # $1: message string
184 # $2: exit code number (with 0 does not exit)
185 _msg_error() {
186     if [[ "${msgdebug}" = false ]]; then
187         set +xv
188     else
189         set -xv
190     fi
191     local echo_opts="-e"
192     local arg
193     local OPTIND
194     local OPT
195     local OPTARG
196     while getopts 'n' arg; do
197         case "${arg}" in
198             n) echo_opts="${echo_opts} -n" ;;
199         esac
200     done
201     shift $((OPTIND - 1))
202     echo ${echo_opts} "$( echo_color -t '36' '[build.sh]')   $( echo_color -t '31' 'Error') ${1}" >&2
203     if [[ -n "${2:-}" ]]; then
204         exit ${2}
205     fi
206     if [[ "${bash_debug}" = true ]]; then
207         set -xv
208     else
209         set +xv
210     fi
211 }
212
213
214 _usage () {
215     echo "usage ${0} [options] [channel]"
216     echo
217     echo " General options:"
218     echo
219     echo "    -b | --boot-splash           Enable boot splash"
220     echo "                                  Default: disable"
221     echo "    -j | --japanese              Enable Japanese mode."
222     echo "                                  Default: disable"
223     echo "    -l | --cleanup               Enable post-build cleaning."
224     echo "                                  Default: disable"
225     echo "    -d | --debug                 Enable debug messages."
226     echo "                                  Default: disable"
227     echo "    -x | --bash-debug            Enable bash debug mode.(set -xv)"
228     echo "                                  Default: disable"
229     echo "    -h | --help                  This help message and exit."
230     echo
231     echo "    -a | --arch <arch>           Set iso architecture."
232     echo "                                  Default: ${arch}"
233     echo "    -c | <comp_type>             Set SquashFS compression type (gzip, lzma, lzo, xz, zstd)"
234     echo "                                  Default: ${sfs_comp}"
235     echo "    -g | --gpgkey <key>          Set gpg key"
236     echo "                                  Default: ${gpg_key}"
237     echo "    -k | --kernel <kernel>       Set special kernel type.See below for available kernels."
238     echo "                                  Default: ${kernel}"
239     echo "    -o | --out <out_dir>         Set the output directory"
240     echo "                                  Default: ${out_dir}"
241     echo "    -p | --password <password>   Set a live user password"
242     echo "                                  Default: ${password}"
243     echo "    -t | --comp-opts <options>   Set compressor-specific options."
244     echo "                                  Default: empty"
245     echo "    -u | --user <username>        Set user name."
246     echo "                                  Default: ${username}"
247     echo "    -w | --work <work_dir>       Set the working directory"
248     echo "                                  Default: ${work_dir}"
249     echo
250     echo "    --gitversion                 Add Git commit hash to image file version"
251     echo "    --msgdebug                   Enables output debugging."
252     echo "    --nocolor                    No output colored output."
253     echo "    --noconfirm                  No check the settings before building."
254     echo "    --noloopmod                  No check and load kernel module automatically."
255     echo "    --nodepend                   No check package dependencies before building."
256     echo "    --shmkalteriso               Use the shell script version of mkalteriso."
257     echo
258     echo "A list of kernels available for each architecture."
259     echo
260     local kernel
261     local list
262     for list in $(ls ${script_path}/system/kernel_list-*); do
263         echo " ${list#${script_path}/system/kernel_list-}:"
264         echo -n "    "
265         for kernel in $(grep -h -v ^'#' ${list}); do
266             echo -n "${kernel} "
267         done
268         echo
269     done
270     echo
271     echo "You can switch between installed packages, files included in images, etc. by channel."
272     echo
273     echo " Channel:"
274     for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
275         if [[ -n $(ls "${script_path}"/channels/${i}) ]]; then
276             if [[ ! ${i} = "share" ]]; then
277                 if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
278                     if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
279                         channel_list="${channel_list[@]} ${i}"
280                     fi
281                 else
282                     channel_list="${channel_list[@]} ${i}"
283                 fi
284             fi
285         fi
286     done
287     channel_list="${channel_list[@]} rebuild"
288     local blank="33"
289
290     for _channel in ${channel_list[@]}; do
291         if [[ -f "${script_path}/channels/${_channel}/description.txt" ]]; then
292             description=$(cat "${script_path}/channels/${_channel}/description.txt")
293         elif [[ "${_channel}" = "rebuild" ]]; then
294             description="Rebuild using the settings of the previous build."
295         else
296             description="This channel does not have a description.txt."
297         fi
298         if [[ $(echo "${_channel}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
299             echo -ne "    $(echo ${_channel} | sed 's/\.[^\.]*$//')"
300             for i in $( seq 1 $(( ${blank} - ${#_channel} )) ); do
301                 echo -ne " "
302             done
303         else
304             echo -ne "    ${_channel}"
305             for i in $( seq 1 $(( ${blank} - 4 - ${#_channel} )) ); do
306                 echo -ne " "
307             done
308         fi
309         echo -ne "${description}\n"
310     done
311
312     if [[ -n "${1:-}" ]]; then
313         exit "${1}"
314     fi
315 }
316
317
318 # Unmount chroot dir
319 umount_chroot () {
320     local mount
321     for mount in $(mount | awk '{print $3}' | grep $(realpath ${work_dir}) | tac); do
322         _msg_info "Unmounting ${mount}"
323         umount -lf "${mount}"
324     done
325 }
326
327 # Helper function to run make_*() only one time.
328 run_once() {
329     if [[ ! -e "${work_dir}/build.${1}_${arch}" ]]; then
330         _msg_debug "Running $1 ..."
331         "$1"
332         touch "${work_dir}/build.${1}_${arch}"
333         umount_chroot
334     else
335         _msg_debug "Skipped because ${1} has already been executed."
336     fi
337 }
338
339
340 # rm helper
341 # Delete the file if it exists.
342 # For directories, rm -rf is used.
343 # If the file does not exist, skip it.
344 # remove <file> <file> ...
345 remove() {
346     local _list
347     local _file
348     _list=($(echo "$@"))
349     for _file in "${_list[@]}"; do
350         if [[ -f ${_file} ]]; then
351             _msg_debug "Removeing ${_file}"
352             rm -f "${_file}"
353         elif [[ -d ${_file} ]]; then
354             _msg_debug "Removeing ${_file}"
355             rm -rf "${_file}"
356         fi
357     done
358 }
359
360
361 # 強制終了時にアンマウント
362 umount_trap() {
363     local status=${?}
364     umount_chroot
365     _msg_error "It was killed by the user."
366     _msg_error "The process may not have completed successfully."
367     exit ${status}
368 }
369
370 # 設定ファイルを読み込む
371 # load_config [file1] [file2] ...
372 load_config() {
373     local file
374     for file in ${@}; do
375         if [[ -f "${file}" ]]; then
376             source "${file}"
377             _msg_debug "The settings have been overwritten by the ${file}"
378         fi
379     done
380 }
381
382
383 # 作業ディレクトリを削除
384 remove_work() {
385     remove "$(ls ${work_dir}/* | grep "build.make")"
386     remove "${work_dir}"/pacman-*.conf
387     remove "${work_dir}/efiboot"
388     remove "${work_dir}/iso"
389     remove "${work_dir}/${arch}"
390     remove "${work_dir}/packages.list"
391     remove "${work_dir}/packages-full.list"
392     #remove "${rebuildfile}"
393     if [[ -z $(ls $(realpath "${work_dir}")/* 2>/dev/null) ]]; then
394         remove ${work_dir}
395     fi
396 }
397
398
399 # Preparation for build
400 prepare_build() {
401     # Build mkalteriso
402     if [[ "${shmkalteriso}" = false ]]; then
403         mkalteriso="${script_path}/system/mkalteriso"
404         cd "${script_path}"
405         _msg_info "Building mkalteriso..."
406         if [[ "${debug}" = true ]]; then
407             make mkalteriso
408             echo
409         else
410             make mkalteriso > /dev/null 2>&1
411         fi
412         cd - > /dev/null 2>&1
413     else
414         mkalteriso="${script_path}/system/mkalteriso.sh"
415     fi
416
417     # Create a working directory.
418     [[ ! -d "${work_dir}" ]] && mkdir -p "${work_dir}"
419
420
421     # Check work dir
422     if [[ -n $(ls -a "${work_dir}" 2> /dev/null | grep -xv ".." | grep -xv ".") ]] && [[ ! "${rebuild}" = true ]]; then
423         umount_chroot
424         _msg_info "Deleting the contents of ${work_dir}..."
425         remove "${work_dir%/}"/*
426     fi
427
428
429     # 強制終了時に作業ディレクトリを削除する
430     local trap_remove_work
431     trap_remove_work() {
432         local status=${?}
433         echo
434         remove_work
435         exit ${status}
436     }
437     trap 'trap_remove_work' 1 2 3 15
438
439     # Save build options
440     local save_var
441     save_var() {
442         local out_file="${rebuildfile}"
443         local i
444         echo "#!/usr/bin/env bash" > "${out_file}"
445         echo "# Build options are stored here." >> "${out_file}"
446         for i in ${@}; do
447             echo -n "${i}=" >> "${out_file}"
448             echo -n '"' >> "${out_file}"
449             eval echo -n '$'{${i}} >> "${out_file}"
450             echo '"' >> "${out_file}"
451         done
452     }
453     if [[ ${rebuild} = false ]]; then
454         # If there is pacman.conf for each channel, use that for building
455         if [[ -f "${script_path}/channels/${channel_name}/pacman-${arch}.conf" ]]; then
456             build_pacman_conf="${script_path}/channels/${channel_name}/pacman-${arch}.conf"
457         fi
458
459         # If there is config for share channel. load that.
460         load_config "${script_path}/channels/share/config.any"
461         load_config ${script_path}/channels/share/config.${arch}
462
463
464         # If there is config for each channel. load that.
465         load_config "${script_path}/channels/${channel_name}/config.any"
466         load_config "${script_path}/channels/${channel_name}/config.${arch}"
467
468
469         # Set username
470         if [[ "${customized_username}" = false ]]; then
471             username="${defaultusername}"
472         fi
473
474         # gitversion
475         if [[ "${gitversion}" = true ]]; then
476             cd ${script_path}
477             iso_version=${iso_version}-$(git rev-parse --short HEAD)
478             cd - > /dev/null 2>&1
479         fi
480     
481         # Generate iso file name.
482         local _channel_name
483         if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
484             _channel_name="$(echo ${channel_name} | sed 's/\.[^\.]*$//')"
485         else
486             _channel_name="${channel_name}"
487         fi
488         if [[ "${japanese}" = true ]]; then
489             _channel_name="${_channel_name}-jp"
490         fi
491         if [[ "${nochname}" = true ]]; then
492             iso_filename="${iso_name}-${iso_version}-${arch}.iso"
493         else
494             iso_filename="${iso_name}-${_channel_name}-${iso_version}-${arch}.iso"
495         fi
496         _msg_debug "Iso filename is ${iso_filename}"
497
498         # Save the value of the variable for use in rebuild.
499         save_var \
500             arch \
501             os_name \
502             iso_name \
503             iso_label \
504             iso_publisher \
505             iso_application \
506             iso_version \
507             iso_filename \
508             install_dir \
509             work_dir \
510             out_dir \
511             gpg_key \
512             mkalteriso_option \
513             password \
514             boot_splash \
515             kernel \
516             theme_name \
517             theme_pkg \
518             sfs_comp \
519             sfs_comp_opt \
520             debug \
521             japanese \
522             channel_name \
523             cleaning \
524             username \
525             mkalteriso \
526             usershell \
527             shmkalteriso \
528             nocolor \
529             build_pacman_conf \
530             defaultconfig \
531             msgdebug \
532             defaultusername \
533             customized_username \
534             gitversion \
535             noloopmod
536     else
537         # Load rebuild file
538         load_config "${rebuildfile}"
539         _msg_debug "Iso filename is ${iso_filename}"
540
541         # Delete the lock file.
542         # remove "$(ls ${work_dir}/* | grep "build.make")"
543     fi
544
545
546     # Unmount
547     local mount
548     for mount in $(mount | awk '{print $3}' | grep $(realpath ${work_dir})); do
549         _msg_info "Unmounting ${mount}"
550         umount "${mount}"
551     done
552
553
554      # Check packages
555     if [[ "${nodepend}" = false ]] && [[ "${arch}" = $(uname -m) ]] ; then
556         local installed_pkg
557         local installed_ver
558         local check_pkg
559         local check_failed=false
560         local pkg
561
562         installed_pkg=($(pacman -Q | awk '{print $1}'))
563         installed_ver=($(pacman -Q | awk '{print $2}'))
564
565         check_pkg() {
566             local i
567             local ver
568             for i in $(seq 0 $(( ${#installed_pkg[@]} - 1 ))); do
569                 if [[ "${installed_pkg[${i}]}" = ${1} ]]; then
570                     ver=$(pacman -Sp --print-format '%v' --config ${build_pacman_conf} ${1} 2> /dev/null)
571                     if [[ "${installed_ver[${i}]}" = "${ver}" ]]; then
572                         echo -n "installed"
573                         return 0
574                     elif [[ -z ${ver} ]]; then
575                         echo "norepo"
576                         return 0
577                     else
578                         echo -n "old"
579                         return 0
580                     fi
581                 fi
582             done
583             echo -n "not"
584             return 0
585         }
586         if [[ ${debug} = false ]]; then
587             _msg_info "Checking dependencies ..."
588         else
589             echo
590         fi
591         for pkg in ${dependence[@]}; do
592             _msg_debug -n "Checking ${pkg} ..."
593             case $(check_pkg ${pkg}) in
594                 "old") 
595                     [[ "${debug}" = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n"
596                     _msg_warn "${pkg} is not the latest package."
597                     _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)"
598                     ;;
599                 "not")
600                     [[ "${debug}" = true ]] && echo
601                     _msg_error "${pkg} is not installed." ; check_failed=true
602                     ;;
603                 "norepo") 
604                     [[ "${debug}" = true ]] && echo
605                     _msg_warn "${pkg} is not a repository package."
606                     ;;
607                 "installed") [[ ${debug} = true ]] && echo -ne " $(pacman -Q ${pkg} | awk '{print $2}')\n" ;;
608             esac
609         done
610
611         if [[ "${check_failed}" = true ]]; then
612             exit 1
613         fi
614     fi
615
616     # Load loop kernel module
617     if [[ "${noloopmod}" = false ]]; then
618         if [[ ! -d "/usr/lib/modules/$(uname -r)" ]]; then
619             _msg_error "The currently running kernel module could not be found."
620             _msg_error "Probably the system kernel has been updated."
621             _msg_error "Reboot your system to run the latest kernel." "1"
622         fi
623         if [[ -z $(lsmod | awk '{print $1}' | grep -x "loop") ]]; then
624             sudo modprobe loop
625         fi
626     fi
627 }
628
629
630 # Show settings.
631 show_settings() {
632     _msg_info "mkalteriso path is ${mkalteriso}"
633     echo
634     if [[ "${boot_splash}" = true ]]; then
635         _msg_info "Boot splash is enabled."
636         _msg_info "Theme is used ${theme_name}."
637     fi
638     _msg_info "Use the ${kernel} kernel."
639     _msg_info "Live username is ${username}."
640     _msg_info "Live user password is ${password}."
641     _msg_info "The compression method of squashfs is ${sfs_comp}."
642     if [[ $(echo "${channel_name}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
643         _msg_info "Use the $(echo ${channel_name} | sed 's/\.[^\.]*$//') channel."
644     else
645         _msg_info "Use the ${channel_name} channel."
646     fi
647     [[ "${japanese}" = true ]] && _msg_info "Japanese mode has been activated."
648     _msg_info "Build with architecture ${arch}."
649     echo
650     if [[ ${noconfirm} = false ]]; then
651         echo "Press Enter to continue or Ctrl + C to cancel."
652         read
653     else
654         :
655         #sleep 3
656     fi
657     trap 1 2 3 15
658     trap 'umount_trap' 1 2 3 15
659 }
660
661
662 # Setup custom pacman.conf with current cache directories.
663 make_pacman_conf() {
664     _msg_debug "Use ${build_pacman_conf}"
665     local _cache_dirs
666     _cache_dirs=($(pacman -v 2>&1 | grep '^Cache Dirs:' | sed 's/Cache Dirs:\s*//g'))
667     sed -r "s|^#?\\s*CacheDir.+|CacheDir = $(echo -n ${_cache_dirs[@]})|g" ${build_pacman_conf} > "${work_dir}/pacman-${arch}.conf"
668 }
669
670 # Base installation, plus needed packages (airootfs)
671 make_basefs() {
672     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" init
673     # ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "haveged intel-ucode amd-ucode memtest86+ mkinitcpio-nfs-utils nbd zsh efitools" install
674     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "bash haveged intel-ucode amd-ucode mkinitcpio-nfs-utils nbd efitools" install
675
676     # Install plymouth.
677     if [[ "${boot_splash}" = true ]]; then
678         if [[ -n "${theme_pkg}" ]]; then
679             ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "plymouth ${theme_pkg}" install
680         else
681             ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "plymouth" install
682         fi
683     fi
684
685     # Install kernel.
686     if [[ ! "${kernel}" = "core" ]]; then
687         ${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
688     else
689         ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "linux linux-headers broadcom-wl" install
690     fi
691 }
692
693 # Additional packages (airootfs)
694 make_packages() {
695     # インストールするパッケージのリストを読み込み、配列pkglistに代入します。
696     installpkglist() {
697         set +e
698         local _loadfilelist
699         local _pkg
700         local _file
701         local jplist
702         local excludefile
703         local excludelist
704         local _pkglist
705
706         #-- Detect package list to load --#
707         # Append the file in the share directory to the file to be read.
708
709         # Package list for Japanese
710         jplist="${script_path}/channels/share/packages.${arch}/jp.${arch}"
711
712         # Package list for non-Japanese
713         nojplist="${script_path}/channels/share/packages.${arch}/non-jp.${arch}"
714
715         if [[ "${japanese}" = true ]]; then
716             _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
717         else
718             _loadfilelist=($(ls "${script_path}"/channels/share/packages.${arch}/*.${arch} | grep -xv "${jplist}"))
719         fi
720
721
722         # Add the files for each channel to the list of files to read.
723
724         # Package list for Japanese
725         jplist="${script_path}/channels/${channel_name}/packages.${arch}/jp.${arch}"
726
727         # Package list for non-Japanese
728         nojplist="${script_path}/channels/${channel_name}/packages.${arch}/non-jp.${arch}"
729
730         if [[ "${japanese}" = true ]]; then
731             # If Japanese is enabled, add it to the list of files to read other than non-jp.
732             _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv "${nojplist}"))
733         else
734             # If Japanese is disabled, add it to the list of files to read other than jp.
735             _loadfilelist=(${_loadfilelist[@]} $(ls "${script_path}"/channels/${channel_name}/packages.${arch}/*.${arch} | grep -xv ${jplist}))
736         fi
737
738
739         #-- Read package list --#
740         # Read the file and remove comments starting with # and add it to the list of packages to install.
741         for _file in ${_loadfilelist[@]}; do
742             _msg_debug "Loaded package file ${_file}."
743             pkglist=( ${pkglist[@]} "$(grep -h -v ^'#' ${_file})" )
744         done
745         if [[ ${debug} = true ]]; then
746             sleep 3
747         fi
748
749         # Exclude packages from the share exclusion list
750         excludefile="${script_path}/channels/share/packages.${arch}/exclude"
751         if [[ -f "${excludefile}" ]]; then
752             excludelist=( $(grep -h -v ^'#' "${excludefile}") )
753
754             # 現在のpkglistをコピーする
755             _pkglist=(${pkglist[@]})
756             unset pkglist
757             for _pkg in ${_pkglist[@]}; do
758                 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
759                 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
760                     pkglist=(${pkglist[@]} "${_pkg}")
761                 fi
762             done
763         fi
764
765         if [[ -n "${excludelist[@]}" ]]; then
766             _msg_debug "The following packages have been removed from the installation list."
767             _msg_debug "Excluded packages: ${excludelist[@]}"
768         fi
769
770         # Exclude packages from the exclusion list for each channel
771         excludefile="${script_path}/channels/${channel_name}/packages.${arch}/exclude"
772         if [[ -f "${excludefile}" ]]; then
773             excludelist=( $(grep -h -v ^'#' "${excludefile}") )
774         
775             # 現在のpkglistをコピーする
776             _pkglist=(${pkglist[@]})
777             unset pkglist
778             for _pkg in ${_pkglist[@]}; do
779                 # もし変数_pkgの値が配列excludelistに含まれていなかったらpkglistに追加する
780                 if [[ ! $(printf '%s\n' "${excludelist[@]}" | grep -qx "${_pkg}"; echo -n ${?} ) = 0 ]]; then
781                     pkglist=(${pkglist[@]} "${_pkg}")
782                 fi
783             done
784         fi
785             
786         
787         # Sort the list of packages in abc order.
788         pkglist=(
789             "$(
790                 for _pkg in ${pkglist[@]}; do
791                     echo "${_pkg}"
792                 done \
793                 | sort
794             )"
795         )
796
797
798         #-- Debug code --#
799         #for _pkg in ${pkglist[@]}; do
800         #    echo -n "${_pkg} "
801         #done
802         # echo "${pkglist[@]}"
803
804
805         set -e
806     }
807
808     installpkglist
809
810     # _msg_debug "${pkglist[@]}"
811
812     # Create a list of packages to be finally installed as packages.list directly under the working directory.
813     echo "# The list of packages that is installed in live cd." > ${work_dir}/packages.list
814     echo "#" >> ${work_dir}/packages.list
815     echo >> ${work_dir}/packages.list
816     for _pkg in ${pkglist[@]}; do
817         echo ${_pkg} >> ${work_dir}/packages.list
818     done
819
820     # Install packages on airootfs
821     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}/${arch}" -C "${work_dir}/pacman-${arch}.conf" -D "${install_dir}" -p "${pkglist[@]}" install
822 }
823
824 # Customize installation (airootfs)
825 make_customize_airootfs() {
826     # Overwrite airootfs with customize_airootfs.
827     local copy_airootfs
828
829     copy_airootfs() {
830         local i 
831         for i in "${@}"; do
832             local _dir="${1%/}"
833             if [[ -d "${_dir}" ]]; then
834                 cp -af "${_dir}"/* "${work_dir}/${arch}/airootfs"
835             fi
836         done
837     }
838
839     copy_airootfs "${script_path}/channels/share/airootfs.any"
840     copy_airootfs "${script_path}/channels/share/airootfs.${arch}"
841     copy_airootfs "${script_path}/channels/${channel_name}/airootfs.any"
842     copy_airootfs "${script_path}/channels/${channel_name}/airootfs.${arch}"
843
844     # Replace /etc/mkinitcpio.conf if Plymouth is enabled.
845     if [[ "${boot_splash}" = true ]]; then
846         cp "${script_path}/mkinitcpio/mkinitcpio-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio.conf"
847     fi
848
849     # Code to use common pacman.conf in archiso.
850     # cp "${script_path}/pacman.conf" "${work_dir}/${arch}/airootfs/etc"
851     # cp "${build_pacman_conf}" "${work_dir}/${arch}/airootfs/etc"
852
853     # Get the optimal mirror list.
854     local mirrorlisturl
855     local mirrorlisturl_all
856     local mirrorlisturl_jp
857
858
859     case "${arch}" in
860         "x86_64")
861             mirrorlisturl_jp='https://www.archlinux.org/mirrorlist/?country=JP'
862             mirrorlisturl_all='https://www.archlinux.org/mirrorlist/?country=all'
863             ;;
864         "i686")
865             mirrorlisturl_jp='https://archlinux32.org/mirrorlist/?country=jp'
866             mirrorlisturl_all='https://archlinux32.org/mirrorlist/?country=all'
867             ;;
868     esac
869
870     if [[ "${japanese}" = true ]]; then
871         mirrorlisturl="${mirrorlisturl_jp}"
872     else
873         mirrorlisturl="${mirrorlisturl_all}"
874     fi
875     curl -o "${work_dir}/${arch}/airootfs/etc/pacman.d/mirrorlist" "${mirrorlisturl}"
876
877     # Add install guide to /root (disabled)
878     # lynx -dump -nolist 'https://wiki.archlinux.org/index.php/Installation_Guide?action=render' >> ${work_dir}/${arch}/airootfs/root/install.txt
879
880
881     # customize_airootfs.sh options
882     # -b            : Enable boot splash.
883     # -d            : Enable debug mode.
884     # -i <inst_dir> : Set install dir
885     # -j            : Enable Japanese.
886     # -k <kernel>   : Set kernel name.
887     # -o <os name>  : Set os name.
888     # -p <password> : Set password.
889     # -s <shell>    : Set user shell.
890     # -t            : Set plymouth theme.
891     # -u <username> : Set live user name.
892     # -x            : Enable bash debug mode.
893     # -r            : Enable rebuild.
894
895
896     # Generate options of customize_airootfs.sh.
897     local addition_options
898     local share_options
899     addition_options=
900     if [[ ${boot_splash} = true ]]; then
901         if [[ -z ${theme_name} ]]; then
902             addition_options="${addition_options} -b"
903         else
904             addition_options="${addition_options} -b -t ${theme_name}"
905         fi
906     fi
907     if [[ ${debug} = true ]]; then
908         addition_options="${addition_options} -d"
909     fi
910     if [[ ${bash_debug} = true ]]; then
911         addition_options="${addition_options} -x"
912     fi
913     if [[ ${japanese} = true ]]; then
914         addition_options="${addition_options} -j"
915     fi
916     if [[ ${rebuild} = true ]]; then
917         addition_options="${addition_options} -r"
918     fi
919
920     share_options="-p '${password}' -k '${kernel}' -u '${username}' -o '${os_name}' -i '${install_dir}' -s '${usershell}' -a '${arch}'"
921
922
923     # X permission
924     if [[ -f ${work_dir}/${arch}/airootfs/root/customize_airootfs.sh ]]; then
925         chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
926     fi
927     if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh" ]]; then
928         chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
929     fi
930     if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
931         chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
932     elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
933         chmod 755 "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh"
934     fi
935
936     # Execute customize_airootfs.sh.
937     if [[ -z ${addition_options} ]]; then
938         ${mkalteriso} ${mkalteriso_option} \
939             -w "${work_dir}/${arch}" \
940             -C "${work_dir}/pacman-${arch}.conf" \
941             -D "${install_dir}" \
942             -r "/root/customize_airootfs.sh ${share_options}" \
943             run
944         if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
945             ${mkalteriso} ${mkalteriso_option} \
946                 -w "${work_dir}/${arch}" \
947                 -C "${work_dir}/pacman-${arch}.conf" \
948                 -D "${install_dir}" \
949                 -r "/root/customize_airootfs_${channel_name}.sh ${share_options}" \
950                 run
951         elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
952             ${mkalteriso} ${mkalteriso_option} \
953                 -w "${work_dir}/${arch}" \
954                 -C "${work_dir}/pacman-${arch}.conf" \
955                 -D "${install_dir}" \
956                 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options}" \
957                 run
958         fi
959     else
960         ${mkalteriso} ${mkalteriso_option} \
961             -w "${work_dir}/${arch}" \
962             -C "${work_dir}/pacman-${arch}.conf" \
963             -D "${install_dir}" \
964             -r "/root/customize_airootfs.sh ${share_options} ${addition_options}" \
965             run
966
967         if [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh" ]]; then
968             ${mkalteriso} ${mkalteriso_option} \
969                 -w "${work_dir}/${arch}" \
970                 -C "${work_dir}/pacman-${arch}.conf" \
971                 -D "${install_dir}" \
972                 -r "/root/customize_airootfs_${channel_name}.sh ${share_options} ${addition_options}" \
973                 run
974         elif [[ -f "${work_dir}/${arch}/airootfs/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh" ]]; then
975             ${mkalteriso} ${mkalteriso_option} \
976                 -w "${work_dir}/${arch}" \
977                 -C "${work_dir}/pacman-${arch}.conf" \
978                 -D "${install_dir}" \
979                 -r "/root/customize_airootfs_$(echo ${channel_name} | sed 's/\.[^\.]*$//').sh ${share_options} ${addition_options}" \
980                 run
981         fi
982     fi
983
984
985     # Delete customize_airootfs.sh.
986     remove "${work_dir}/${arch}/airootfs/root/customize_airootfs.sh"
987     remove "${work_dir}/${arch}/airootfs/root/customize_airootfs_${channel_name}.sh"
988 }
989
990 # Copy mkinitcpio archiso hooks and build initramfs (airootfs)
991 make_setup_mkinitcpio() {
992     local _hook
993     mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
994     mkdir -p "${work_dir}/${arch}/airootfs/etc/initcpio/install"
995     for _hook in "archiso" "archiso_shutdown" "archiso_pxe_common" "archiso_pxe_nbd" "archiso_pxe_http" "archiso_pxe_nfs" "archiso_loop_mnt"; do
996         cp "${script_path}/system/initcpio/hooks/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/hooks"
997         cp "${script_path}/system/initcpio/install/${_hook}" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
998     done
999     sed -i "s|/usr/lib/initcpio/|/etc/initcpio/|g" "${work_dir}/${arch}/airootfs/etc/initcpio/install/archiso_shutdown"
1000     cp "${script_path}/system/initcpio/install/archiso_kms" "${work_dir}/${arch}/airootfs/etc/initcpio/install"
1001     cp "${script_path}/system/initcpio/archiso_shutdown" "${work_dir}/${arch}/airootfs/etc/initcpio"
1002     if [[ "${boot_splash}" = true ]]; then
1003         cp "${script_path}/mkinitcpio/mkinitcpio-archiso-plymouth.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
1004     else
1005         cp "${script_path}/mkinitcpio/mkinitcpio-archiso.conf" "${work_dir}/${arch}/airootfs/etc/mkinitcpio-archiso.conf"
1006     fi
1007     gnupg_fd=
1008     if [[ "${gpg_key}" ]]; then
1009       gpg --export "${gpg_key}" >"${work_dir}/gpgkey"
1010       exec 17<>$"{work_dir}/gpgkey"
1011     fi
1012
1013     if [[ ! ${kernel} = "core" ]]; then
1014         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
1015     else
1016         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
1017     fi
1018
1019     if [[ "${gpg_key}" ]]; then
1020       exec 17<&-
1021     fi
1022 }
1023
1024 # Prepare kernel/initramfs ${install_dir}/boot/
1025 make_boot() {
1026     mkdir -p "${work_dir}/iso/${install_dir}/boot/${arch}"
1027     cp "${work_dir}/${arch}/airootfs/boot/archiso.img" "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img"
1028
1029     if [[ ! "${kernel}" = "core" ]]; then
1030         cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel}" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}"
1031     else
1032         cp "${work_dir}/${arch}/airootfs/boot/vmlinuz-linux" "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz"
1033     fi
1034 }
1035
1036 # Add other aditional/extra files to ${install_dir}/boot/
1037 make_boot_extra() {
1038     # In AlterLinux, memtest has been removed.
1039     # cp "${work_dir}/${arch}/airootfs/boot/memtest86+/memtest.bin" "${work_dir}/iso/${install_dir}/boot/memtest"
1040     # cp "${work_dir}/${arch}/airootfs/usr/share/licenses/common/GPL2/license.txt" "${work_dir}/iso/${install_dir}/boot/memtest.COPYING"
1041     cp "${work_dir}/${arch}/airootfs/boot/intel-ucode.img" "${work_dir}/iso/${install_dir}/boot/intel_ucode.img"
1042     cp "${work_dir}/${arch}/airootfs/usr/share/licenses/intel-ucode/LICENSE" "${work_dir}/iso/${install_dir}/boot/intel_ucode.LICENSE"
1043     cp "${work_dir}/${arch}/airootfs/boot/amd-ucode.img" "${work_dir}/iso/${install_dir}/boot/amd_ucode.img"
1044     cp "${work_dir}/${arch}/airootfs/usr/share/licenses/amd-ucode/LICENSE" "${work_dir}/iso/${install_dir}/boot/amd_ucode.LICENSE"
1045 }
1046
1047 # Prepare /${install_dir}/boot/syslinux
1048 make_syslinux() {
1049     if [[ ! ${kernel} = "core" ]]; then
1050         _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux-${kernel} | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
1051     else
1052         _uname_r="$(file -b ${work_dir}/${arch}/airootfs/boot/vmlinuz-linux | awk 'f{print;f=0} /version/{f=1}' RS=' ')"
1053     fi
1054     mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux"
1055
1056     for _cfg in ${script_path}/syslinux/${arch}/*.cfg; do
1057         sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1058              s|%OS_NAME%|${os_name}|g;
1059              s|%INSTALL_DIR%|${install_dir}|g" "${_cfg}" > "${work_dir}/iso/${install_dir}/boot/syslinux/${_cfg##*/}"
1060     done
1061
1062     if [[ ${boot_splash} = true ]]; then
1063         sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1064              s|%OS_NAME%|${os_name}|g;
1065              s|%INSTALL_DIR%|${install_dir}|g" \
1066              "${script_path}/syslinux/${arch}/pxe-plymouth/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
1067
1068         sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1069              s|%OS_NAME%|${os_name}|g;
1070              s|%INSTALL_DIR%|${install_dir}|g" \
1071              "${script_path}/syslinux/${arch}/sys-plymouth/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
1072     else
1073         sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1074              s|%OS_NAME%|${os_name}|g;
1075              s|%INSTALL_DIR%|${install_dir}|g" \
1076              "${script_path}/syslinux/${arch}/pxe/archiso_pxe-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_pxe.cfg"
1077
1078         sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1079              s|%OS_NAME%|${os_name}|g;
1080              s|%INSTALL_DIR%|${install_dir}|g" \
1081              "${script_path}/syslinux/${arch}/sys/archiso_sys-${kernel}.cfg" > "${work_dir}/iso/${install_dir}/boot/syslinux/archiso_sys.cfg"
1082     fi
1083
1084     if [[ -f "${script_path}/channels/${channel_name}/splash.png" ]]; then
1085         cp "${script_path}/channels/${channel_name}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
1086     else
1087         cp "${script_path}/syslinux/${arch}/splash.png" "${work_dir}/iso/${install_dir}/boot/syslinux"
1088     fi
1089     cp "${work_dir}"/${arch}/airootfs/usr/lib/syslinux/bios/*.c32 "${work_dir}/iso/${install_dir}/boot/syslinux"
1090     cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/lpxelinux.0" "${work_dir}/iso/${install_dir}/boot/syslinux"
1091     cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/memdisk" "${work_dir}/iso/${install_dir}/boot/syslinux"
1092     mkdir -p "${work_dir}/iso/${install_dir}/boot/syslinux/hdt"
1093     gzip -c -9 "${work_dir}/${arch}/airootfs/usr/share/hwdata/pci.ids" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/pciids.gz"
1094     gzip -c -9 "${work_dir}/${arch}/airootfs/usr/lib/modules/${_uname_r}/modules.alias" > "${work_dir}/iso/${install_dir}/boot/syslinux/hdt/modalias.gz"
1095 }
1096
1097 # Prepare /isolinux
1098 make_isolinux() {
1099     mkdir -p "${work_dir}/iso/isolinux"
1100
1101     sed "s|%INSTALL_DIR%|${install_dir}|g" \
1102         "${script_path}/system/isolinux.cfg" > "${work_dir}/iso/isolinux/isolinux.cfg"
1103     cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isolinux.bin" "${work_dir}/iso/isolinux/"
1104     cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/isohdpfx.bin" "${work_dir}/iso/isolinux/"
1105     cp "${work_dir}/${arch}/airootfs/usr/lib/syslinux/bios/ldlinux.c32" "${work_dir}/iso/isolinux/"
1106 }
1107
1108 # Prepare /EFI
1109 make_efi() {
1110     mkdir -p "${work_dir}/iso/EFI/boot"
1111     cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/HashTool.efi" "${work_dir}/iso/EFI/boot/"
1112     if [[ "${arch}" = "x86_64" ]]; then
1113         cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/PreLoader.efi" "${work_dir}/iso/EFI/boot/bootx64.efi"
1114         cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/iso/EFI/boot/loader.efi"
1115     fi
1116
1117     mkdir -p "${work_dir}/iso/loader/entries"
1118     cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/iso/loader/"
1119     cp "${script_path}/efiboot/loader/entries/uefi-shell-x86_64.conf" "${work_dir}/iso/loader/entries/"
1120     cp "${script_path}/efiboot/loader/entries/uefi-shell-full-x86_64.conf" "${work_dir}/iso/loader/entries/"
1121
1122     sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1123          s|%OS_NAME%|${os_name}|g;
1124          s|%INSTALL_DIR%|${install_dir}|g" \
1125         "${script_path}/efiboot/loader/entries/usb/archiso-x86_64-usb-${kernel}.conf" > "${work_dir}/iso/loader/entries/archiso-x86_64.conf"
1126
1127     # edk2-shell based UEFI shell
1128     cp /usr/share/edk2-shell/x64/Shell.efi ${work_dir}/iso/EFI/Shell_x64.efi
1129     cp /usr/share/edk2-shell/x64/Shell_Full.efi ${work_dir}/iso/EFI/Shell_Full_x64.efi
1130 }
1131
1132 # Prepare efiboot.img::/EFI for "El Torito" EFI boot mode
1133 make_efiboot() {
1134     mkdir -p "${work_dir}/iso/EFI/archiso"
1135     truncate -s 64M "${work_dir}/iso/EFI/archiso/efiboot.img"
1136     mkfs.fat -n ARCHISO_EFI "${work_dir}/iso/EFI/archiso/efiboot.img"
1137
1138     mkdir -p "${work_dir}/efiboot"
1139     mount "${work_dir}/iso/EFI/archiso/efiboot.img" "${work_dir}/efiboot"
1140
1141     mkdir -p "${work_dir}/efiboot/EFI/archiso"
1142
1143     if [[ ! ${kernel} = "core" ]]; then
1144         cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz-linux-${kernel}" "${work_dir}/efiboot/EFI/archiso/vmlinuz-linux-${kernel}.efi"
1145     else
1146         cp "${work_dir}/iso/${install_dir}/boot/${arch}/vmlinuz" "${work_dir}/efiboot/EFI/archiso/vmlinuz.efi"
1147     fi
1148
1149     cp "${work_dir}/iso/${install_dir}/boot/${arch}/archiso.img" "${work_dir}/efiboot/EFI/archiso/archiso.img"
1150
1151     cp "${work_dir}/iso/${install_dir}/boot/intel_ucode.img" "${work_dir}/efiboot/EFI/archiso/intel_ucode.img"
1152     cp "${work_dir}/iso/${install_dir}/boot/amd_ucode.img" "${work_dir}/efiboot/EFI/archiso/amd_ucode.img"
1153
1154     mkdir -p "${work_dir}/efiboot/EFI/boot"
1155     cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/HashTool.efi" "${work_dir}/efiboot/EFI/boot/"
1156
1157     if [[ "${arch}" = "x86_64" ]]; then
1158         cp "${work_dir}/${arch}/airootfs/usr/share/efitools/efi/PreLoader.efi" "${work_dir}/efiboot/EFI/boot/bootx64.efi"
1159         cp "${work_dir}/${arch}/airootfs/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "${work_dir}/efiboot/EFI/boot/loader.efi"
1160     fi
1161
1162     mkdir -p "${work_dir}/efiboot/loader/entries"
1163     cp "${script_path}/efiboot/loader/loader.conf" "${work_dir}/efiboot/loader/"
1164     cp "${script_path}/efiboot/loader/entries/uefi-shell-x86_64.conf" "${work_dir}/efiboot/loader/entries/"
1165     cp "${script_path}/efiboot/loader/entries/uefi-shell-full-x86_64.conf" "${work_dir}/efiboot/loader/entries/"
1166
1167
1168     sed "s|%ARCHISO_LABEL%|${iso_label}|g;
1169          s|%OS_NAME%|${os_name}|g;
1170          s|%INSTALL_DIR%|${install_dir}|g" \
1171         "${script_path}/efiboot/loader/entries/cd/archiso-x86_64-cd-${kernel}.conf" > "${work_dir}/efiboot/loader/entries/archiso-x86_64.conf"
1172
1173     cp "${work_dir}/iso/EFI/Shell_x64.efi" "${work_dir}/efiboot/EFI/"
1174     cp "${work_dir}/iso/EFI/Shell_Full_x64.efi" "${work_dir}/efiboot/EFI/"
1175
1176     umount -d "${work_dir}/efiboot"
1177 }
1178
1179 # Build airootfs filesystem image
1180 make_prepare() {
1181     cp -a -l -f "${work_dir}/${arch}/airootfs" "${work_dir}"
1182     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" pkglist
1183     pacman -Q --sysroot "${work_dir}/airootfs" > "${work_dir}/packages-full.list"
1184     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" ${gpg_key:+-g ${gpg_key}} -c "${sfs_comp}" -t "${sfs_comp_opt}" prepare
1185     remove "${work_dir}/airootfs"
1186
1187     if [[ "${cleaning}" = true ]]; then
1188         remove "${work_dir}/${arch}/airootfs"
1189     fi
1190 }
1191
1192 # Build ISO
1193 make_iso() {
1194     ${mkalteriso} ${mkalteriso_option} -w "${work_dir}" -D "${install_dir}" -L "${iso_label}" -P "${iso_publisher}" -A "${iso_application}" -o "${out_dir}" iso "${iso_filename}"
1195     _msg_info "The password for the live user and root is ${password}."
1196 }
1197
1198
1199 # Parse options
1200 options="${@}"
1201 _opt_short="a:bc:dg:hjk:lo:p:t:u:w:x"
1202 _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"
1203 OPT=$(getopt -o ${_opt_short} -l ${_opt_long} -- "${@}")
1204 if [[ ${?} != 0 ]]; then
1205     exit 1
1206 fi
1207
1208 eval set -- "${OPT}"
1209 unset OPT
1210 unset _opt_short
1211 unset _opt_long
1212
1213
1214 while :; do
1215     case ${1} in
1216         -a | --arch)
1217             arch="${2}"
1218             shift 2
1219             ;;
1220         -b | --boot-splash)
1221             boot_splash=true
1222             shift 1
1223             ;;
1224         -c | --comp-type)
1225             case "${2}" in
1226                 "gzip" | "lzma" | "lzo" | "lz4" | "xz" | "zstd") sfs_comp="${2}" ;;
1227                 *) _msg_error "Invaild compressors '${2}'" '1' ;;
1228             esac
1229             shift 2
1230             ;;
1231         -d | --debug) 
1232             debug=true
1233             shift 1
1234             ;;
1235         -g | --gpgkey)
1236             gpg_key="$2"
1237             shift 2
1238             ;;
1239         -h | --help)
1240             _usage
1241             exit 0
1242             ;;
1243         -j | --japanese)
1244             japanese=true
1245             shift 1
1246             ;;
1247         -k | --kernel)
1248             if [[ -n $(cat ${script_path}/system/kernel_list-${arch} | grep -h -v ^'#' | grep -x "${2}") ]]; then
1249                 kernel="${2}"
1250             else
1251                 _msg_error "Invalid kernel ${2}" "1"
1252             fi
1253             shift 2
1254             ;;
1255         -l | --cleaning)
1256             cleaning=true
1257             shift 1
1258             ;;
1259         -o | --out)
1260             out_dir="${2}"
1261             shift 2
1262             ;;
1263         -p | --password)
1264             password="${2}"
1265             shift 2
1266             ;;
1267         -t | --comp-opts)
1268             sfs_comp_opt="${2}"
1269             shift 2
1270             ;;
1271         -u | --user)
1272             customized_username=true
1273             username="$(echo -n "${2}" | sed 's/ //g' |tr '[A-Z]' '[a-z]')"
1274             shift 2
1275             ;;
1276         -w | --work)
1277             work_dir="${2}"
1278             shift 2
1279             ;;
1280         -x | --bash-debug)
1281             debug=true
1282             bash_debug=true
1283             shift 1
1284             ;;
1285         --noconfirm)
1286             noconfirm=true
1287             shift 1
1288             ;;
1289         --nodepend)
1290             nodepend=true
1291             shift 1
1292             ;;
1293         --nocolor)
1294             nocolor=true
1295             shift 1
1296             ;;
1297         --gitversion)
1298             if [[ -d "${script_path}/.git" ]]; then
1299                 gitversion=true
1300             else
1301                 _msg_error "There is no git directory. You need to use git clone to use this feature." "1"
1302             fi
1303             shift 1
1304             ;;
1305         --shmkalteriso)
1306             shmkalteriso=true
1307             shift 1
1308             ;;
1309         --msgdebug)
1310             msgdebug=true;
1311             shift 1
1312             ;;
1313         --noloopmod)
1314             noloopmod=true
1315             shift 1
1316             ;;
1317         --)
1318             shift
1319             break
1320             ;;
1321         *)
1322             _msg_error "Invalid argument '${1}'"
1323             _usage 1
1324             ;;
1325     esac
1326 done
1327
1328
1329 # Check root.
1330 if [[ ${EUID} -ne 0 ]]; then
1331     _msg_warn "This script must be run as root." >&2
1332     # echo "Use -h to display script details." >&2
1333     # _usage 1
1334     _msg_warn "Re-run 'sudo ${0} ${options}'"
1335     sudo ${0} ${options}
1336     exit 1
1337 fi
1338
1339
1340 # Show alteriso version
1341 if [[ -d "${script_path}/.git" ]]; then
1342     cd  "${script_path}"
1343     _msg_debug "The version of alteriso is $(git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g')."
1344     cd - > /dev/null 2>&1
1345 fi
1346
1347
1348 # Show config message
1349 [[ -f "${defaultconfig}" ]] && _msg_debug "The settings have been overwritten by the ${defaultconfig}"
1350
1351
1352 # Debug mode
1353 mkalteriso_option="-a ${arch} -v"
1354 if [[ "${bash_debug}" = true ]]; then
1355     set -x
1356     set -v
1357     mkalteriso_option="${mkalteriso_option} -x"
1358 fi
1359
1360
1361 # Pacman configuration file used only when building
1362 build_pacman_conf=${script_path}/system/pacman-${arch}.conf
1363
1364 # Set rebuild config file
1365 rebuildfile="${work_dir}/build_options"
1366
1367
1368 # Parse channels
1369 set +eu
1370 if [[ -n "${1}" ]]; then
1371     channel_name="${1}"
1372
1373     # Channel list
1374     # check_channel <channel name>
1375     check_channel() {
1376         local channel_list
1377         local i
1378         channel_list=()
1379         for i in $(ls -l "${script_path}"/channels/ | awk '$1 ~ /d/ {print $9 }'); do
1380             if [[ -n $(ls "${script_path}"/channels/${i}) ]]; then
1381                 if [[ ! ${i} = "share" ]]; then
1382                     if [[ ! $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1383                         if [[ ! -d "${script_path}/channels/${i}.add" ]]; then
1384                             channel_list="${channel_list[@]} ${i}"
1385                         fi
1386                     else
1387                         channel_list="${channel_list[@]} ${i}"
1388                     fi
1389                 fi
1390             fi
1391         done
1392         for i in ${channel_list[@]}; do
1393             if [[ $(echo "${i}" | sed 's/^.*\.\([^\.]*\)$/\1/') = "add" ]]; then
1394                 if [[ $(echo ${i} | sed 's/\.[^\.]*$//') = ${1} ]]; then
1395                     echo -n "true"
1396                     return 0
1397                 fi
1398             else
1399                 if [[ ${i} = ${1} ]]; then
1400                     echo -n "true"
1401                     return 0
1402                 fi
1403             fi
1404         done
1405         if [[ "${channel_name}" = "rebuild" ]] || [[ "${channel_name}" = "clean" ]]; then
1406             echo -n "true"
1407             return 0
1408         else
1409             echo -n "false"
1410             return 1
1411         fi
1412     }
1413
1414     if [[ $(check_channel "${channel_name}") = false ]]; then
1415         _msg_error "Invalid channel ${channel_name}" "1"
1416     fi
1417
1418     if [[ -d "${script_path}"/channels/${channel_name}.add ]]; then
1419         channel_name="${channel_name}.add"
1420     elif [[ "${channel_name}" = "rebuild" ]]; then
1421         if [[ -f "${rebuildfile}" ]]; then
1422                 rebuild=true
1423         else
1424             _msg_error "The previous build information is not in the working directory." "1"
1425         fi
1426     elif [[ "${channel_name}" = "clean" ]]; then
1427             umount_chroot
1428             rm -rf "${work_dir}"
1429             exit 
1430     fi
1431
1432     _msg_debug "channel path is ${script_path}/channels/${channel_name}"
1433 fi
1434
1435 # Check architecture and kernel for each channel
1436 if [[ ! "${channel_name}" = "rebuild" ]]; then
1437     # architecture
1438     if [[ -z $(cat "${script_path}/channels/${channel_name}/architecture" | grep -h -v ^'#' | grep -x "${arch}") ]]; then
1439         _msg_error "${channel_name} channel does not support current architecture (${arch})." "1"
1440     fi
1441
1442     # kernel
1443     if [[ -f "${script_path}/channels/${channel_name}/kernel_list-${arch}" ]]; then
1444         if [[ -z $(cat "${script_path}/channels/${channel_name}/kernel_list-${arch}" | grep -h -v ^'#' | grep -x "${kernel}") ]]; then
1445             _msg_error "This kernel is currently not supported on this channel." "1"
1446         fi
1447     fi
1448 fi
1449
1450
1451 # Check the value of a variable that can only be set to true or false.
1452 check_bool() {
1453     local _value
1454     _value="$(eval echo '$'${1})"
1455     _msg_debug -n "Checking ${1}..."
1456     if [[ "${debug}" = true ]]; then
1457         echo -e " ${_value}"
1458     fi
1459     if [[ ! -v "${1}" ]]; then
1460         echo; _msg_error "The variable name ${1} is empty." "1"
1461     elif [[ ! "${_value}" = "true" ]] && [[ ! "${_value}" = "false" ]]; then
1462         echo; _msg_error "The variable name ${1} is not of bool type." "1"
1463     fi
1464 }
1465
1466 if [[ "${debug}" =  true ]]; then
1467     echo
1468 fi
1469 check_bool boot_splash
1470 check_bool debug
1471 check_bool bash_debug
1472 check_bool rebuild
1473 check_bool japanese
1474 check_bool cleaning
1475 check_bool noconfirm
1476 check_bool nodepend
1477 check_bool nocolor
1478 check_bool shmkalteriso
1479 check_bool msgdebug
1480 check_bool customized_username
1481 check_bool noloopmod
1482 check_bool nochname
1483
1484 if [[ "${debug}" =  true ]]; then
1485     echo
1486 fi
1487
1488 set -eu
1489
1490 prepare_build
1491 show_settings
1492 run_once make_pacman_conf
1493 run_once make_basefs
1494 run_once make_packages
1495 run_once make_customize_airootfs
1496 run_once make_setup_mkinitcpio
1497 run_once make_boot
1498 run_once make_boot_extra
1499 run_once make_syslinux
1500 run_once make_isolinux
1501 run_once make_efi
1502 run_once make_efiboot
1503 run_once make_prepare
1504 run_once make_iso
1505
1506 if [[ ${cleaning} = true ]]; then
1507     remove_work
1508 fi