mirror of
https://github.com/armbian/build
synced 2025-09-24 19:47:06 +07:00
armbian-next: rootfs: new CLI command for rootfs cache building; further refactorings
- _told ya it would all make sense eventually..._ - introduce new, real, non-alias `rootfs` command in `cli-rootfs` -- this _only_ builds rootfs, nothing else - no more `main_default_build_single()`; instead `full_build_packages_rootfs_and_image()` - introduce `do_with_default_build()` wrapper, for things that need host prepared + aggregation to run - CLI-specific parts of `main_default_build_single()` moved to cli-build - put prepare/cleanup pair of `prepare_rootfs_build_params_and_trap()` and `trap_handler_cleanup_rootfs_and_image()` into new `trap-rootfs.sh` (this needs further splitting for the image part) - refactor `get_or_create_rootfs_cache_chroot_sdcard()` into `build_rootfs_only()`, `calculate_rootfs_cache_id()` - update library with new files
This commit is contained in:
@@ -9,6 +9,25 @@ function cli_standard_build_run() {
|
||||
# configuration etc - it initializes the extension manager; handles its own logging sections
|
||||
prep_conf_main_build_single
|
||||
|
||||
# main_default_build_single() handles its own logging sections...
|
||||
main_default_build_single
|
||||
# the full build. It has its own logging sections.
|
||||
do_with_default_build full_build_packages_rootfs_and_image
|
||||
|
||||
# CLI-specific: how to redo the build.
|
||||
if armbian_is_running_in_container; then
|
||||
BUILD_CONFIG='docker' # @TODO: this is not true, CLI handles this differently, gotta ask the CLI; this whole thing is inconsistent
|
||||
fi
|
||||
|
||||
# Make it easy to repeat build by displaying build options used. Prepare array. @TODO this is inconsistent. Maybe something like the relaunch vars?
|
||||
local -a repeat_args=("./compile.sh" "${BUILD_CONFIG}" " BRANCH=${BRANCH}")
|
||||
[[ -n ${RELEASE} ]] && repeat_args+=("RELEASE=${RELEASE}")
|
||||
[[ -n ${BUILD_MINIMAL} ]] && repeat_args+=("BUILD_MINIMAL=${BUILD_MINIMAL}")
|
||||
[[ -n ${BUILD_DESKTOP} ]] && repeat_args+=("BUILD_DESKTOP=${BUILD_DESKTOP}")
|
||||
[[ -n ${KERNEL_ONLY} ]] && repeat_args+=("KERNEL_ONLY=${KERNEL_ONLY}")
|
||||
[[ -n ${KERNEL_CONFIGURE} ]] && repeat_args+=("KERNEL_CONFIGURE=${KERNEL_CONFIGURE}")
|
||||
[[ -n ${DESKTOP_ENVIRONMENT} ]] && repeat_args+=("DESKTOP_ENVIRONMENT=${DESKTOP_ENVIRONMENT}")
|
||||
[[ -n ${DESKTOP_ENVIRONMENT_CONFIG_NAME} ]] && repeat_args+=("DESKTOP_ENVIRONMENT_CONFIG_NAME=${DESKTOP_ENVIRONMENT_CONFIG_NAME}")
|
||||
[[ -n ${DESKTOP_APPGROUPS_SELECTED} ]] && repeat_args+=("DESKTOP_APPGROUPS_SELECTED=\"${DESKTOP_APPGROUPS_SELECTED}\"")
|
||||
[[ -n ${DESKTOP_APT_FLAGS_SELECTED} ]] && repeat_args+=("DESKTOP_APT_FLAGS_SELECTED=\"${DESKTOP_APT_FLAGS_SELECTED}\"")
|
||||
[[ -n ${COMPRESS_OUTPUTIMAGE} ]] && repeat_args+=("COMPRESS_OUTPUTIMAGE=${COMPRESS_OUTPUTIMAGE}")
|
||||
display_alert "Repeat Build Options" "${repeat_args[*]}" "ext" # * = expand array, space delimited, single-word.
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ function cli_patch_kernel_run() {
|
||||
"${target_repo_url}"
|
||||
"kernel-${LINUXFAMILY}-${KERNEL_MAJOR_MINOR}:${target_branch}")
|
||||
|
||||
# Prepare the host and build kernel instead of main_default_build_single
|
||||
# Prepare the host and build kernel; without using standard build
|
||||
prepare_host # This handles its own logging sections, and is possibly interactive.
|
||||
compile_kernel # This handles its own logging sections.
|
||||
|
||||
|
||||
25
lib/functions/cli/cli-rootfs.sh
Normal file
25
lib/functions/cli/cli-rootfs.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
function cli_rootfs_pre_run() {
|
||||
declare -g ARMBIAN_COMMAND_REQUIRE_BASIC_DEPS="yes" # Require prepare_host_basic to run before the command.
|
||||
|
||||
# "gimme root on a Linux machine"
|
||||
cli_standard_relaunch_docker_or_sudo
|
||||
}
|
||||
|
||||
function cli_rootfs_run() {
|
||||
# configuration etc - it initializes the extension manager; handles its own logging sections
|
||||
prep_conf_main_build_single
|
||||
|
||||
# default build, but only invoke specific rootfs functions needed. It has its own logging sections.
|
||||
do_with_default_build cli_rootfs_only_in_default_build
|
||||
}
|
||||
|
||||
# This is run inside do_with_default_build(), above.
|
||||
function cli_rootfs_only_in_default_build() {
|
||||
declare -i tmpfs_estimated_size # in MiB; set by prepare_rootfs_build_params_and_trap()
|
||||
LOG_SECTION="prepare_rootfs_build_params_and_trap" do_with_logging prepare_rootfs_build_params_and_trap
|
||||
|
||||
LOG_SECTION="calculate_rootfs_cache_id" do_with_logging calculate_rootfs_cache_id
|
||||
|
||||
# "rootfs" CLI skips over a lot goes straight to create the rootfs. It doesn't check cache etc.
|
||||
LOG_SECTION="create_new_rootfs_cache" do_with_logging create_new_rootfs_cache
|
||||
}
|
||||
@@ -22,7 +22,9 @@ function armbian_register_commands() {
|
||||
["build"]="standard_build" # implemented in cli_standard_build_pre_run and cli_standard_build_run
|
||||
["distccd"]="distccd" # implemented in cli_distccd_pre_run and cli_distccd_run
|
||||
|
||||
# shortcuts, see vars set below
|
||||
["rootfs"]="rootfs" # implemented in cli_rootfs_pre_run and cli_rootfs_run
|
||||
|
||||
# shortcuts, see vars set below. the use legacy single build, and try to control it via variables
|
||||
["kernel"]="standard_build"
|
||||
["u-boot"]="standard_build"
|
||||
["uboot"]="standard_build"
|
||||
|
||||
@@ -388,7 +388,6 @@ function do_extra_configuration() {
|
||||
display_alert "Done with do_extra_configuration" "do_extra_configuration" "debug"
|
||||
}
|
||||
|
||||
# This is called by main_default_build_single() but declared here for 'convenience'
|
||||
function write_config_summary_output_file() {
|
||||
local debug_dpkg_arch debug_uname debug_virt debug_src_mount
|
||||
debug_dpkg_arch="$(dpkg --print-architecture)"
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
# This does NOT run under the logging manager. We should invoke the do_with_logging wrapper for
|
||||
# strategic parts of this. Attention: almost everything does it's own logging.
|
||||
function main_default_build_single() {
|
||||
main_default_start_build # Has its own logging, prepares workdir, does prepare_host, aggregation, and
|
||||
|
||||
# This does NOT run under the logging manager.
|
||||
function full_build_packages_rootfs_and_image() {
|
||||
main_default_build_packages # has its own logging sections # requires aggregation
|
||||
|
||||
# build rootfs, if not only kernel. Again, read "KERNEL_ONLY" as if it was "PACKAGES_ONLY"
|
||||
@@ -11,24 +8,10 @@ function main_default_build_single() {
|
||||
build_rootfs_and_image # old "debootstrap-ng"; has its own logging sections.
|
||||
display_alert "Done building image" "${BOARD}" "target-reached"
|
||||
fi
|
||||
|
||||
main_default_end_build
|
||||
|
||||
if armbian_is_running_in_container; then
|
||||
BUILD_CONFIG='docker' # @TODO: this is not true, CLI handles this differently, gotta ask the CLI; this whole thing is inconsistent
|
||||
fi
|
||||
|
||||
# Make it easy to repeat build by displaying build options used. Prepare array. @TODO this is inconsistent. Maybe something like the relaunch vars?
|
||||
local -a repeat_args=("./compile.sh" "${BUILD_CONFIG}" " BRANCH=${BRANCH}")
|
||||
[[ -n ${RELEASE} ]] && repeat_args+=("RELEASE=${RELEASE}")
|
||||
[[ -n ${BUILD_MINIMAL} ]] && repeat_args+=("BUILD_MINIMAL=${BUILD_MINIMAL}")
|
||||
[[ -n ${BUILD_DESKTOP} ]] && repeat_args+=("BUILD_DESKTOP=${BUILD_DESKTOP}")
|
||||
[[ -n ${KERNEL_ONLY} ]] && repeat_args+=("KERNEL_ONLY=${KERNEL_ONLY}")
|
||||
[[ -n ${KERNEL_CONFIGURE} ]] && repeat_args+=("KERNEL_CONFIGURE=${KERNEL_CONFIGURE}")
|
||||
[[ -n ${DESKTOP_ENVIRONMENT} ]] && repeat_args+=("DESKTOP_ENVIRONMENT=${DESKTOP_ENVIRONMENT}")
|
||||
[[ -n ${DESKTOP_ENVIRONMENT_CONFIG_NAME} ]] && repeat_args+=("DESKTOP_ENVIRONMENT_CONFIG_NAME=${DESKTOP_ENVIRONMENT_CONFIG_NAME}")
|
||||
[[ -n ${DESKTOP_APPGROUPS_SELECTED} ]] && repeat_args+=("DESKTOP_APPGROUPS_SELECTED=\"${DESKTOP_APPGROUPS_SELECTED}\"")
|
||||
[[ -n ${DESKTOP_APT_FLAGS_SELECTED} ]] && repeat_args+=("DESKTOP_APT_FLAGS_SELECTED=\"${DESKTOP_APT_FLAGS_SELECTED}\"")
|
||||
[[ -n ${COMPRESS_OUTPUTIMAGE} ]] && repeat_args+=("COMPRESS_OUTPUTIMAGE=${COMPRESS_OUTPUTIMAGE}")
|
||||
display_alert "Repeat Build Options" "${repeat_args[*]}" "ext" # * = expand array, space delimited, single-word.
|
||||
}
|
||||
|
||||
function do_with_default_build() {
|
||||
main_default_start_build # Has its own logging, prepares workdir, does prepare_host, aggregation, and
|
||||
"${@}"
|
||||
main_default_end_build
|
||||
}
|
||||
|
||||
@@ -2,52 +2,16 @@
|
||||
|
||||
function build_rootfs_and_image() {
|
||||
display_alert "Checking for rootfs cache" "$(echo "${BRANCH} ${BOARD} ${RELEASE} ${DESKTOP_APPGROUPS_SELECTED} ${DESKTOP_ENVIRONMENT} ${BUILD_MINIMAL}" | tr -s " ")" "info"
|
||||
|
||||
[[ $ROOTFS_TYPE != ext4 ]] && display_alert "Assuming ${BOARD} ${BRANCH} kernel supports ${ROOTFS_TYPE}" "" "wrn"
|
||||
|
||||
# add handler to cleanup when done or if something fails or is interrupted.
|
||||
add_cleanup_handler trap_handler_cleanup_rootfs_and_image
|
||||
declare -i tmpfs_estimated_size # in MiB; set by prepare_rootfs_build_params_and_trap()
|
||||
prepare_rootfs_build_params_and_trap
|
||||
|
||||
# stage: clean and create directories
|
||||
rm -rf "${SDCARD}" "${MOUNT}"
|
||||
mkdir -p "${SDCARD}" "${MOUNT}" "${DEST}/images" "${SRC}/cache/rootfs"
|
||||
# get a basic rootfs, either from cache or from scratch
|
||||
build_rootfs_only
|
||||
|
||||
# bind mount rootfs if defined
|
||||
if [[ -d "${ARMBIAN_CACHE_ROOTFS_PATH}" ]]; then
|
||||
mountpoint -q "${SRC}"/cache/rootfs && umount "${SRC}"/cache/toolchain
|
||||
mount --bind "${ARMBIAN_CACHE_ROOTFS_PATH}" "${SRC}/cache/rootfs"
|
||||
fi
|
||||
|
||||
# stage: verify tmpfs configuration and mount
|
||||
# CLI needs ~2GiB, desktop ~5GiB
|
||||
# vs 60% of "available" RAM (free + buffers + magic)
|
||||
declare -i available_physical_memory_mib
|
||||
available_physical_memory_mib=$(($(awk '/MemAvailable/ {print $2}' /proc/meminfo) * 6 / 1024 / 10)) # MiB
|
||||
|
||||
# @TODO: well those are very... arbitrary numbers. At least when using cached rootfs, we can be more precise.
|
||||
# predicting the size of tmpfs is hard/impossible, so would be nice to show the used size at the end so we can tune.
|
||||
declare -i tmpfs_estimated_size=2000 # MiB
|
||||
[[ $BUILD_DESKTOP == yes ]] && tmpfs_estimated_size=5000 # MiB
|
||||
|
||||
declare use_tmpfs=no # by default
|
||||
if [[ ${FORCE_USE_RAMDISK} == no ]]; then # do not use, even if it fits
|
||||
display_alert "Not using tmpfs for rootfs" "due to FORCE_USE_RAMDISK=no" "info"
|
||||
elif [[ ${FORCE_USE_RAMDISK} == yes || ${available_physical_memory_mib} -gt ${tmpfs_estimated_size} ]]; then # use, either force or fits
|
||||
use_tmpfs=yes
|
||||
display_alert "Using tmpfs for rootfs build" "RAM available: ${available_physical_memory_mib}MiB > ${tmpfs_estimated_size}MiB estimated" "info"
|
||||
else
|
||||
display_alert "Not using tmpfs for rootfs" "RAM available: ${available_physical_memory_mib}MiB < ${tmpfs_estimated_size}MiB estimated" "info"
|
||||
fi
|
||||
|
||||
if [[ $use_tmpfs == yes ]]; then
|
||||
declare -g -r ROOTFS_IS_UNDER_TMPFS=yes
|
||||
mount -t tmpfs tmpfs "${SDCARD}" # do not specify size; we've calculated above that it should fit, and Linux will try its best if it doesn't.
|
||||
fi
|
||||
|
||||
# stage: prepare basic rootfs: unpack cache or create from scratch
|
||||
LOG_SECTION="get_or_create_rootfs_cache_chroot_sdcard" do_with_logging get_or_create_rootfs_cache_chroot_sdcard
|
||||
|
||||
mount_chroot "${SDCARD}" # this used to be inside get_or_create_rootfs_cache_chroot_sdcard().
|
||||
# stage: with a basic rootfs available, we mount the chroot and work on it
|
||||
mount_chroot "${SDCARD}"
|
||||
|
||||
call_extension_method "pre_install_distribution_specific" "config_pre_install_distribution_specific" <<- 'PRE_INSTALL_DISTRIBUTION_SPECIFIC'
|
||||
*give config a chance to act before install_distribution_specific*
|
||||
@@ -90,7 +54,7 @@ function build_rootfs_and_image() {
|
||||
|
||||
# warn if rootfs_size_mib is higher than the tmpfs_estimated_size
|
||||
if [[ ${rootfs_size_mib} -gt ${tmpfs_estimated_size} ]]; then
|
||||
display_alert "Rootfs actual size is larger than estimated tmpfs size" "${rootfs_size_mib}MiB > ${tmpfs_estimated_size}MiB" "wrn"
|
||||
display_alert "Rootfs post-tweaks size is larger than estimated tmpfs size" "${rootfs_size_mib}MiB > ${tmpfs_estimated_size}MiB" "wrn"
|
||||
fi
|
||||
|
||||
# ------------------------------------ UP HERE IT's 'rootfs' stuff -------------------------------
|
||||
@@ -106,13 +70,13 @@ function build_rootfs_and_image() {
|
||||
LOG_SECTION="create_image_from_sdcard_rootfs" do_with_logging create_image_from_sdcard_rootfs
|
||||
fi
|
||||
|
||||
# Completely and recursively unmount the directory. This will remove the tmpfs mount too
|
||||
# Completely and recursively unmount the directory. --> This will remove the tmpfs mount too <--
|
||||
umount_chroot_recursive "${SDCARD}" "SDCARD rootfs finished"
|
||||
|
||||
# Remove the dir
|
||||
[[ -d "${SDCARD}" ]] && rm -rf --one-file-system "${SDCARD}"
|
||||
|
||||
# Run the cleanup handler. @TODO: this already does the above, so can be simpler.
|
||||
# Run the cleanup handler. @TODO: this already does the above, so can be simpler. @TODO: don't forget to split MOUNT/SDCARD trap
|
||||
execute_and_remove_cleanup_handler trap_handler_cleanup_rootfs_and_image
|
||||
|
||||
return 0
|
||||
@@ -123,38 +87,3 @@ function list_installed_packages() {
|
||||
LOG_ASSET="installed_packages.txt" do_with_log_asset chroot_sdcard dpkg --get-selections "| grep -v deinstall | awk '{print \$1}' | cut -f1 -d':'"
|
||||
}
|
||||
|
||||
function trap_handler_cleanup_rootfs_and_image() {
|
||||
display_alert "Cleanup for rootfs and image" "trap_handler_cleanup_rootfs_and_image" "cleanup"
|
||||
|
||||
debug_tmpfs_show_usage "before cleanup of rootfs"
|
||||
|
||||
cd "${SRC}" || echo "Failed to cwd to ${SRC}" # Move pwd away, so unmounts work
|
||||
# those will loop until they're unmounted.
|
||||
umount_chroot_recursive "${SDCARD}" "SDCARD" || true
|
||||
umount_chroot_recursive "${MOUNT}" "MOUNT" || true
|
||||
|
||||
# unmount tmpfs mounted on SDCARD if it exists. #@TODO: move to new tmpfs-utils scheme
|
||||
mountpoint -q "${SDCARD}" && umount "${SDCARD}"
|
||||
|
||||
# @TODO: rpardini: igor: why lazy umounts?
|
||||
mountpoint -q "${SRC}"/cache/toolchain && umount -l "${SRC}"/cache/toolchain >&2
|
||||
mountpoint -q "${SRC}"/cache/rootfs && umount -l "${SRC}"/cache/rootfs >&2
|
||||
[[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose "${ROOT_MAPPER}" >&2
|
||||
|
||||
if [[ "${PRESERVE_SDCARD_MOUNT}" == "yes" ]]; then
|
||||
display_alert "Preserving SD card mount" "trap_handler_cleanup_rootfs_and_image" "warn"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2153 # global var.
|
||||
if [[ -b "${LOOP}" ]]; then
|
||||
display_alert "Freeing loop" "trap_handler_cleanup_rootfs_and_image ${LOOP}" "wrn"
|
||||
free_loop_device_insistent "${LOOP}" || true
|
||||
fi
|
||||
|
||||
[[ -d "${SDCARD}" ]] && rm -rf --one-file-system "${SDCARD}"
|
||||
[[ -d "${MOUNT}" ]] && rm -rf --one-file-system "${MOUNT}"
|
||||
[[ -f "${SDCARD}".raw ]] && rm -f "${SDCARD}".raw
|
||||
|
||||
return 0 # short-circuit above, so exit clean here
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Common start/end build functions. Used by main_default_build_single()
|
||||
# Common start/end build functions. Used by the default build and others
|
||||
|
||||
function main_default_start_build() {
|
||||
wait_for_disk_sync "before starting build" # fsync, wait for disk to sync, and then continue. alert user if takes too long.
|
||||
|
||||
@@ -1,6 +1,39 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# this gets from cache or produces a new rootfs, and leaves a mounted chroot "$SDCARD" at the end.
|
||||
function build_rootfs_only() {
|
||||
# validate that tmpfs_estimated_size is set and higher than zero, or exit_with_error
|
||||
[[ -z ${tmpfs_estimated_size} ]] && exit_with_error "tmpfs_estimated_size is not set"
|
||||
[[ ${tmpfs_estimated_size} -le 0 ]] && exit_with_error "tmpfs_estimated_size is not higher than zero"
|
||||
|
||||
# stage: prepare basic rootfs: unpack cache or create from scratch
|
||||
LOG_SECTION="get_or_create_rootfs_cache_chroot_sdcard" do_with_logging get_or_create_rootfs_cache_chroot_sdcard
|
||||
|
||||
# obtain the size, in MiB, of "${SDCARD}" at this point.
|
||||
declare -i rootfs_size_mib
|
||||
rootfs_size_mib=$(du -sm "${SDCARD}" | awk '{print $1}')
|
||||
display_alert "Actual rootfs size" "${rootfs_size_mib}MiB after basic/cache" ""
|
||||
|
||||
# warn if rootfs_size_mib is higher than the tmpfs_estimated_size
|
||||
if [[ ${rootfs_size_mib} -gt ${tmpfs_estimated_size} ]]; then
|
||||
display_alert "Rootfs actual size is larger than estimated tmpfs size after basic/cache" "${rootfs_size_mib}MiB > ${tmpfs_estimated_size}MiB" "wrn"
|
||||
fi
|
||||
}
|
||||
|
||||
function calculate_rootfs_cache_id() {
|
||||
# Validate that AGGREGATED_ROOTFS_HASH is set
|
||||
[[ -z "${AGGREGATED_ROOTFS_HASH}" ]] && exit_with_error "AGGREGATED_ROOTFS_HASH is not set at calculate_rootfs_cache_id()"
|
||||
|
||||
declare -g packages_hash="${AGGREGATED_ROOTFS_HASH}" # Produced by aggregation.py - currently only AGGREGATED_PACKAGES_DEBOOTSTRAP and AGGREGATED_PACKAGES_ROOTFS
|
||||
declare -g -r packages_hash=${packages_hash:0:16} # it's an md5, which is 32 hex digits; used to be 8; make readonly
|
||||
|
||||
declare -g cache_type="cli"
|
||||
[[ ${BUILD_DESKTOP} == yes ]] && cache_type="xfce-desktop"
|
||||
[[ -n ${DESKTOP_ENVIRONMENT} ]] && cache_type="${DESKTOP_ENVIRONMENT}"
|
||||
[[ ${BUILD_MINIMAL} == yes ]] && cache_type="minimal"
|
||||
declare -g -r cache_type="${cache_type}"
|
||||
}
|
||||
|
||||
# this gets from cache or produces a basic new rootfs, ready, but not mounted, at "$SDCARD"
|
||||
function get_or_create_rootfs_cache_chroot_sdcard() {
|
||||
# validate "${SDCARD}" is set. it does not exist, yet...
|
||||
if [[ -z "${SDCARD}" ]]; then
|
||||
@@ -28,20 +61,13 @@ function get_or_create_rootfs_cache_chroot_sdcard() {
|
||||
else
|
||||
display_alert "ROOTFSCACHE_VERSION is set externally" "${ROOTFSCACHE_VERSION}" "warn"
|
||||
fi
|
||||
|
||||
|
||||
# Make ROOTFSCACHE_VERSION global at this point, in case it was not.
|
||||
declare -g ROOTFSCACHE_VERSION="${ROOTFSCACHE_VERSION}"
|
||||
|
||||
display_alert "ROOTFSCACHE_VERSION found online or preset" "${ROOTFSCACHE_VERSION}" "warn"
|
||||
|
||||
local packages_hash="${AGGREGATED_ROOTFS_HASH}" # Produced by aggregation.py - currently only AGGREGATED_PACKAGES_DEBOOTSTRAP and AGGREGATED_PACKAGES_ROOTFS
|
||||
local packages_hash=${packages_hash:0:16} # it's an md5, which is 32 hex digits; used to be 8
|
||||
|
||||
local cache_type="cli"
|
||||
[[ ${BUILD_DESKTOP} == yes ]] && cache_type="xfce-desktop"
|
||||
[[ -n ${DESKTOP_ENVIRONMENT} ]] && cache_type="${DESKTOP_ENVIRONMENT}"
|
||||
[[ ${BUILD_MINIMAL} == yes ]] && cache_type="minimal"
|
||||
|
||||
calculate_rootfs_cache_id # this sets packages_hash and cache_type
|
||||
# seek last cache, proceed to previous otherwise build it
|
||||
local cache_list
|
||||
readarray -t cache_list <<< "$(get_rootfs_cache_list "$cache_type" "$packages_hash" | sort -r)"
|
||||
@@ -108,11 +134,15 @@ function get_or_create_rootfs_cache_chroot_sdcard() {
|
||||
|
||||
function create_new_rootfs_cache() {
|
||||
[[ ! -d "${SDCARD:?}" ]] && exit_with_error "create_new_rootfs_cache: ${SDCARD} is not a directory"
|
||||
# validate cache_type is set
|
||||
[[ -n "${cache_type}" ]] || exit_with_error "create_new_rootfs_cache: cache_type is not set"
|
||||
# validate packages_hash is set
|
||||
[[ -n "${packages_hash}" ]] || exit_with_error "create_new_rootfs_cache: packages_hash is not set"
|
||||
|
||||
# This var ROOT_FS_CREATE_VERSION is only used here, afterwards it's all cache_name and cache_fname
|
||||
local ROOT_FS_CREATE_VERSION=${ROOT_FS_CREATE_VERSION:-$(date --utc +"%Y%m%d")}
|
||||
local cache_name=${ARCH}-${RELEASE}-${cache_type}-${packages_hash}-${ROOT_FS_CREATE_VERSION}.tar.zst
|
||||
local cache_fname=${SRC}/cache/rootfs/${cache_name}
|
||||
declare ROOT_FS_CREATE_VERSION="${ROOT_FS_CREATE_VERSION:-"$(date --utc +"%Y%m%d")"}"
|
||||
declare cache_name=${ARCH}-${RELEASE}-${cache_type}-${packages_hash}-${ROOT_FS_CREATE_VERSION}.tar.zst
|
||||
declare cache_fname=${SRC}/cache/rootfs/${cache_name}
|
||||
|
||||
display_alert "Creating new rootfs cache for" "${RELEASE} ${ROOT_FS_CREATE_VERSION}" "info"
|
||||
|
||||
|
||||
78
lib/functions/rootfs/trap-rootfs.sh
Normal file
78
lib/functions/rootfs/trap-rootfs.sh
Normal file
@@ -0,0 +1,78 @@
|
||||
## Prepare/cleanup pair @TODO needs to be split between SDCARD and MOUNT, no sense doing both in rootfs trap anymore
|
||||
function prepare_rootfs_build_params_and_trap() {
|
||||
# add handler to cleanup when done or if something fails or is interrupted.
|
||||
add_cleanup_handler trap_handler_cleanup_rootfs_and_image
|
||||
|
||||
# stage: clean and create directories
|
||||
run_host_command_logged rm -rfv "${SDCARD}" "${MOUNT}"
|
||||
run_host_command_logged mkdir -pv "${SDCARD}" "${MOUNT}" "${SRC}/cache/rootfs" "${DEST}/images" # @TODO images shouldn't be here up
|
||||
|
||||
# bind mount rootfs if defined # @TODO: is this used? it is never unmounted
|
||||
if [[ -d "${ARMBIAN_CACHE_ROOTFS_PATH}" ]]; then
|
||||
display_alert "Warning, using untested code path" "ARMBIAN_CACHE_ROOTFS_PATH" "warn"
|
||||
mountpoint -q "${SRC}"/cache/rootfs && umount "${SRC}"/cache/rootfs
|
||||
mount --bind "${ARMBIAN_CACHE_ROOTFS_PATH}" "${SRC}/cache/rootfs"
|
||||
fi
|
||||
|
||||
# stage: verify tmpfs configuration and mount
|
||||
# CLI needs ~2GiB, desktop ~5GiB
|
||||
# vs 60% of "available" RAM (free + buffers + magic)
|
||||
declare -i available_physical_memory_mib
|
||||
available_physical_memory_mib=$(($(awk '/MemAvailable/ {print $2}' /proc/meminfo) * 6 / 1024 / 10)) # MiB
|
||||
|
||||
# @TODO: well those are very... arbitrary numbers. At least when using cached rootfs, we can be more precise.
|
||||
# predicting the size of tmpfs is hard/impossible, so would be nice to show the used size at the end so we can tune.
|
||||
declare -i tmpfs_estimated_size=2000 # MiB
|
||||
[[ $BUILD_DESKTOP == yes ]] && tmpfs_estimated_size=5000 # MiB
|
||||
|
||||
declare use_tmpfs=no # by default
|
||||
if [[ ${FORCE_USE_RAMDISK} == no ]]; then # do not use, even if it fits
|
||||
display_alert "Not using tmpfs for rootfs" "due to FORCE_USE_RAMDISK=no" "info"
|
||||
elif [[ ${FORCE_USE_RAMDISK} == yes || ${available_physical_memory_mib} -gt ${tmpfs_estimated_size} ]]; then # use, either force or fits
|
||||
use_tmpfs=yes
|
||||
display_alert "Using tmpfs for rootfs build" "RAM available: ${available_physical_memory_mib}MiB > ${tmpfs_estimated_size}MiB estimated" "info"
|
||||
else
|
||||
display_alert "Not using tmpfs for rootfs" "RAM available: ${available_physical_memory_mib}MiB < ${tmpfs_estimated_size}MiB estimated" "info"
|
||||
fi
|
||||
|
||||
if [[ $use_tmpfs == yes ]]; then
|
||||
declare -g -r ROOTFS_IS_UNDER_TMPFS=yes
|
||||
mount -t tmpfs tmpfs "${SDCARD}" # do not specify size; we've calculated above that it should fit, and Linux will try its best if it doesn't.
|
||||
fi
|
||||
}
|
||||
|
||||
function trap_handler_cleanup_rootfs_and_image() {
|
||||
display_alert "Cleanup for rootfs and image" "trap_handler_cleanup_rootfs_and_image" "cleanup"
|
||||
|
||||
debug_tmpfs_show_usage "before cleanup of rootfs"
|
||||
|
||||
cd "${SRC}" || echo "Failed to cwd to ${SRC}" # Move pwd away, so unmounts work
|
||||
# those will loop until they're unmounted.
|
||||
umount_chroot_recursive "${SDCARD}" "SDCARD" || true
|
||||
umount_chroot_recursive "${MOUNT}" "MOUNT" || true
|
||||
|
||||
# unmount tmpfs mounted on SDCARD if it exists. #@TODO: move to new tmpfs-utils scheme
|
||||
mountpoint -q "${SDCARD}" && umount "${SDCARD}"
|
||||
|
||||
# @TODO: rpardini: igor: why lazy umounts?
|
||||
mountpoint -q "${SRC}"/cache/toolchain && umount -l "${SRC}"/cache/toolchain >&2
|
||||
mountpoint -q "${SRC}"/cache/rootfs && umount -l "${SRC}"/cache/rootfs >&2
|
||||
[[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose "${ROOT_MAPPER}" >&2
|
||||
|
||||
if [[ "${PRESERVE_SDCARD_MOUNT}" == "yes" ]]; then
|
||||
display_alert "Preserving SD card mount" "trap_handler_cleanup_rootfs_and_image" "warn"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2153 # global var.
|
||||
if [[ -b "${LOOP}" ]]; then
|
||||
display_alert "Freeing loop" "trap_handler_cleanup_rootfs_and_image ${LOOP}" "wrn"
|
||||
free_loop_device_insistent "${LOOP}" || true
|
||||
fi
|
||||
|
||||
[[ -d "${SDCARD}" ]] && rm -rf --one-file-system "${SDCARD}"
|
||||
[[ -d "${MOUNT}" ]] && rm -rf --one-file-system "${MOUNT}"
|
||||
[[ -f "${SDCARD}".raw ]] && rm -f "${SDCARD}".raw
|
||||
|
||||
return 0 # short-circuit above, so exit clean here
|
||||
}
|
||||
@@ -91,6 +91,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/cli/cli-requirements.sh
|
||||
source "${SRC}"/lib/functions/cli/cli-requirements.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/cli/cli-rootfs.sh
|
||||
# shellcheck source=lib/functions/cli/cli-rootfs.sh
|
||||
source "${SRC}"/lib/functions/cli/cli-rootfs.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
@@ -766,6 +775,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/logging/traps.sh
|
||||
source "${SRC}"/lib/functions/logging/traps.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/main/build-packages.sh
|
||||
# shellcheck source=lib/functions/main/build-packages.sh
|
||||
source "${SRC}"/lib/functions/main/build-packages.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
@@ -802,6 +820,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/main/rootfs-image.sh
|
||||
source "${SRC}"/lib/functions/main/rootfs-image.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/main/start-end.sh
|
||||
# shellcheck source=lib/functions/main/start-end.sh
|
||||
source "${SRC}"/lib/functions/main/start-end.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
@@ -883,6 +910,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/rootfs/qemu-static.sh
|
||||
source "${SRC}"/lib/functions/rootfs/qemu-static.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/rootfs/rootfs-create.sh
|
||||
# shellcheck source=lib/functions/rootfs/rootfs-create.sh
|
||||
source "${SRC}"/lib/functions/rootfs/rootfs-create.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
@@ -901,6 +937,15 @@ set -o errexit ## set -e : exit the script if any statement returns a non-true
|
||||
# shellcheck source=lib/functions/rootfs/systemd-utils.sh
|
||||
source "${SRC}"/lib/functions/rootfs/systemd-utils.sh
|
||||
|
||||
# no errors tolerated. invoked before each sourced file to make sure.
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
#set -o nounset ## set -u : exit the script if you try to use an uninitialised variable - one day will be enabled
|
||||
set -o errtrace # trace ERR through - enabled
|
||||
set -o errexit ## set -e : exit the script if any statement returns a non-true return value - enabled
|
||||
### lib/functions/rootfs/trap-rootfs.sh
|
||||
# shellcheck source=lib/functions/rootfs/trap-rootfs.sh
|
||||
source "${SRC}"/lib/functions/rootfs/trap-rootfs.sh
|
||||
|
||||
|
||||
# no errors tolerated. one last time for the win!
|
||||
#set -o pipefail # trace ERR through pipes - will be enabled "soon"
|
||||
|
||||
Reference in New Issue
Block a user