summaryrefslogtreecommitdiffhomepage
path: root/subr
diff options
context:
space:
mode:
authorLucio Andrés Illanes Albornoz <lucio@lucioillanes.de>2021-05-07 17:12:29 +0100
committerLucio Andrés Illanes Albornoz <lucio@lucioillanes.de>2021-05-07 17:12:29 +0100
commit370e98db644d9cd75172205e4e472978e68e0990 (patch)
tree28c009461e87ea94ebad5ad55c48e1cbdd74a63b /subr
parent9d255dd37a449f7661fd8a73f58ea6102269851d (diff)
downloadmidipix_build-370e98db644d9cd75172205e4e472978e68e0990.tar.bz2
midipix_build-370e98db644d9cd75172205e4e472978e68e0990.tar.xz
Implements extended -r syntax.
build.sh:buildp_ast(): only reset package build step state if ${ARG_RESET_PKG} is 1. etc/{build.usage,README.md}: updated. etc/build.usage.short, subr/build_init.subr: implement short help screen. midipix.env: correctly escape multi-line variable assignment expressions. subr.rtl/rtl_list.subr: updated. subr.rtl/rtl_state.subr:rtl_state_set(): correctly implement invalidation. subr.rtl/rtl_state.subr:rtl_state_test(): honour `LAST'. subr/build_init.subr:buildp_init_getopts(): implements --reset-pkg. subr/build_init.subr:buildp_{expand_restart_{at,recursive},process_restart_spec}(): initial implementation. subr/ex_pkg_{dispatch,env}.subr: updated. subr/ex_pkg_exec.subr:ex_pkg_exec(): honour `ALL' and `LAST'. vars/gcc.vars: updated.
Diffstat (limited to 'subr')
-rw-r--r--subr/build_init.subr266
-rw-r--r--subr/ex_pkg_dispatch.subr8
-rw-r--r--subr/ex_pkg_env.subr9
-rw-r--r--subr/ex_pkg_exec.subr76
4 files changed, 234 insertions, 125 deletions
diff --git a/subr/build_init.subr b/subr/build_init.subr
index d3e4ce19..f5894e69 100644
--- a/subr/build_init.subr
+++ b/subr/build_init.subr
@@ -2,10 +2,153 @@
# set +o errexit -o noglob -o nounset is assumed.
#
+buildp_expand_restart_at() {
+ local _restart_at_spec="${1}" _restart_at="" _restart_at_spec_new="";
+
+ for _restart_at in $(rtl_llift "${_restart_at_spec}" "," " "); do
+ case "${_restart_at}" in
+ @fetch) _restart_at="fetch_download,fetch_extract"; ;;
+ @configure)
+ _restart_at="configure_patch_pre,configure_autotools,configure_patch,configure"; ;;
+ @build) _restart_at="build"; ;;
+ @install)
+ _restart_at="install_subdirs,install_make,install_files,install_libs,install,install_rpm"; ;;
+ @clean)
+ _restart_at="clean"; ;;
+ *) ;;
+ esac;
+ _restart_at_spec_new="$(rtl_lconcat "${_restart_at_spec_new}" "${_restart_at}" ",")"
+ done;
+ printf "%s" "${_restart_at_spec_new}";
+};
+
+buildp_expand_restart_recursive() {
+ local _restart_spec="${1}" _last_pkg="" _restart_spec_at="" _restart_spec_recursive=0;
+
+ case "${_restart_spec}" in
+ \*\*\*[a-zA-Z]*)
+ _restart_spec="${_restart_spec#\*\*\*}"; _restart_spec_recursive=3; ;;
+ \*\*[a-zA-Z]*) _restart_spec="${_restart_spec#\*\*}"; _restart_spec_recursive=2; ;;
+ \*[a-zA-Z]*) _restart_spec="${_restart_spec#\*}"; _restart_spec_recursive=1; ;;
+ ALL) _restart_spec_at=ALL; _restart_spec_recursive=2; ;;
+ LAST) _restart_spec_at=ALL; _restart_spec_recursive=0;
+ if [ -n "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}" ]\
+ && [ -e "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}" ]; then
+ _last_pkg="$(cat "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}")";
+ rtl_fileop rm "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}";
+ rtl_state_clear "${BUILD_WORKDIR}" "${_last_pkg}";
+ _restart_spec="${_last_pkg}";
+ else
+ _status="cannot rebuild last failed package"; return 1;
+ fi; ;;
+ esac;
+ ARG_RESTART="${_restart_spec}";
+ ARG_RESTART_AT="${_restart_spec_at}";
+ ARG_RESTART_RECURSIVE="${_restart_spec_recursive}";
+ return 0;
+};
+
+buildp_process_restart_spec() {
+ local _restart_spec="${1}" _eqfl=0 _ltfl=0 _restart_spec_at0="" _restart_spec_at="" _step="" _step1=""; _status="";
+
+ buildp_expand_restart_recursive "${_restart_spec}" || return "${?}";
+ _restart_spec="${ARG_RESTART}"; _restart_spec_at="${ARG_RESTART_AT}";
+
+ case "${_restart_spec}" in
+ "") return 0; ;;
+ *:*)
+ _restart_spec_at="${_restart_spec#*:}"; _restart_spec="${_restart_spec%%:*}";
+ _restart_spec_at0="${_restart_spec_at}"; _restart_spec_at="";
+ case "${_restart_spec_at0}" in
+ ALL|LAST)
+ _restart_spec_at="${_restart_spec_at0}"; ;;
+
+ ^*) _restart_spec_at0="${_restart_spec_at0#^}";
+ _restart_spec_at0="$(buildp_expand_restart_at "${_restart_spec_at0}")";
+ _restart_spec_at="$(rtl_llift "${DEFAULT_BUILD_STEPS}" " " ",")";
+ for _restart_at in $(rtl_llift "${_restart_spec_at0}" "," " "); do
+ _restart_spec_at="$(rtl_lfilter "${_restart_spec_at}" "${_restart_at}" ",")";
+ done; _restart_spec_at="$(rtl_lfilter "${_restart_spec_at}" "finish" ",")"; ;;
+
+ \<=*|\<*|\>=*|\>*)
+ [ "${_restart_spec_at0#<}" != "${_restart_spec_at0}" ] && _ltfl=1;
+ if [ "${_restart_spec_at0#[<>]=}" != "${_restart_spec_at0}" ]; then
+ _restart_spec_at0="${_restart_spec_at0#[<>]=}"; _eqfl=1;
+ else
+ _restart_spec_at0="${_restart_spec_at0#[<>]}"; _eqfl=0;
+ fi; _restart_spec_at="";
+ _restart_spec_at0="$(buildp_expand_restart_at "${_restart_spec_at0%%,*}")";
+ if [ \( "${_eqfl}" -eq 1 \) -a \( "${_ltfl}" -eq 1 \) ]\
+ || [ \( "${_eqfl}" -eq 0 \) -a \( "${_ltfl}" -eq 0 \) ]; then
+ _restart_spec_at0="${_restart_spec_at0##*,}";
+ elif [ \( "${_eqfl}" -eq 1 \) -a \( "${_ltfl}" -eq 0 \) ]\
+ || [ \( "${_eqfl}" -eq 0 \) -a \( "${_ltfl}" -eq 1 \) ]; then
+ _restart_spec_at0="${_restart_spec_at0%%,*}";
+ fi;
+ for _restart_at in ${DEFAULT_BUILD_STEPS}; do
+ if [ "${_ltfl}" -eq 1 ]; then
+ if [ "${_restart_at}" = "${_restart_spec_at0%%,*}" ]; then
+ if [ "${_eqfl}" -eq 1 ]; then
+ _restart_spec_at="$(rtl_lconcat "${_restart_spec_at}" "${_restart_at}" ",")";
+ fi; break;
+ fi;
+ else
+ if [ "${_restart_at}" = "${_restart_spec_at0%%,*}" ]; then
+ _foundfl=1; [ "${_eqfl}" -eq 0 ] && continue;
+ fi; [ "${_foundfl}" -eq 0 ] && continue;
+ fi;
+ _restart_spec_at="$(rtl_lconcat "${_restart_spec_at}" "${_restart_at}" ",")";
+ done; ;;
+
+ *) _restart_spec_at="$(buildp_expand_restart_at "${_restart_spec_at0}")"; ;;
+ esac; ;;
+
+ *) _restart_spec_at=ALL; ;;
+ esac;
+
+ ARG_RESTART="$(rtl_llift "${_restart_spec}" "," " ")";
+ ARG_RESTART_AT="${_restart_spec_at}";
+ if [ "${#ARG_RESTART_AT}" -eq 0 ]; then
+ _status="zero-length build step list"; return 1;
+ elif [ "${ARG_RESTART_AT}" != "ALL" ]\
+ && [ "${ARG_RESTART_AT}" != "LAST" ]; then
+ for _restart_at in $(rtl_lfilter "$(rtl_llift "${ARG_RESTART_AT}" "," " ")" "${DEFAULT_BUILD_STEPS}"); do
+ case "${_restart_at}" in
+ start) ;;
+ *) _status="unknown build step \`${_restart_at}'"; return 1; ;;
+ esac;
+ done;
+ fi;
+ if [ "${#ARG_RESTART_AT}" -gt 0 ]\
+ && [ "${ARG_RESTART_AT}" != "ALL" ]\
+ && [ "${ARG_RESTART_AT}" != "LAST" ]; then
+ _restart_spec_at="${ARG_RESTART_AT}"; ARG_RESTART_AT="";
+ for _restart_at in ${DEFAULT_BUILD_STEPS}; do
+ if rtl_lmatch "${_restart_spec_at}" "${_restart_at}" ","; then
+ ARG_RESTART_AT="$(rtl_lconcat "${ARG_RESTART_AT}" "${_restart_at}" ",")";
+ fi;
+ done;
+ if [ "${ARG_RESTART_AT##*,}" != "finish" ]; then
+ _step="$(rtl_lfilter "${ARG_RESTART_AT}" "clean,finish" ",")"; _step="${_step##*,}";
+ _step1="$(rtl_lfilter "${DEFAULT_BUILD_STEPS}" "clean finish")"; _step1="${_step1##* }";
+ if [ "${_step}" = "${_step1}" ]; then
+ ARG_RESTART_AT="$(rtl_lconcat "${ARG_RESTART_AT}" "finish" ",")";
+ fi;
+ fi;
+ fi;
+ return 0;
+};
+
buildp_init_args() {
- local _foundfl=0 _group="" _last_pkg="" _pkg_names_unknown="" _rc=0\
+ local _eqfl=0 _foundfl=0 _group="" _pkg_names_unknown="" _rc=0 \
EX_PKG_BUILD_GROUPS EX_PKG_BUILD_GROUPS_NOAUTO; _status="";
+ case "${ARG_FETCH_FORCE}" in
+ ipv4) DEFAULT_GIT_ARGS="$(rtl_lconcat "-4" "${DEFAULT_GIT_ARGS}")";
+ DEFAULT_WGET_ARGS="$(rtl_lconcat "-4" "${DEFAULT_WGET_ARGS}")"; ;;
+ ipv6) DEFAULT_GIT_ARGS="$(rtl_lconcat "-6" "${DEFAULT_GIT_ARGS}")";
+ DEFAULT_WGET_ARGS="$(rtl_lconcat "-6" "${DEFAULT_WGET_ARGS}")"; ;;
+ esac;
if [ -z "${BUILD_HNAME:-}" ]\
&& ! BUILD_HNAME="$(hostname)"; then
_rc=1; _status="Error: failed to obtain hostname.";
@@ -16,73 +159,45 @@ buildp_init_args() {
&& [ -e "${PREFIX}/build.gitref" ]\
&& [ "$(git rev-parse HEAD)" = "$(cat "${PREFIX}/build.gitref")" ]; then
_rc=0; _status="Git repository has not changed since last build and --as-needed was specified.";
- else case "${ARG_FETCH_FORCE}" in
- ipv4) DEFAULT_GIT_ARGS="$(rtl_lconcat "-4" "${DEFAULT_GIT_ARGS}")";
- DEFAULT_WGET_ARGS="$(rtl_lconcat "-4" "${DEFAULT_WGET_ARGS}")"; ;;
- ipv6) DEFAULT_GIT_ARGS="$(rtl_lconcat "-6" "${DEFAULT_GIT_ARGS}")";
- DEFAULT_WGET_ARGS="$(rtl_lconcat "-6" "${DEFAULT_WGET_ARGS}")"; ;;
- esac;
- case "${ARG_RESTART}" in
- \*\*\*[a-zA-Z]*)
- ARG_RESTART="${ARG_RESTART#\*\*\*}"; ARG_RESTART_RECURSIVE=3; ;;
- \*\*[a-zA-Z]*) ARG_RESTART="${ARG_RESTART#\*\*}"; ARG_RESTART_RECURSIVE=2; ;;
- \*[a-zA-Z]*) ARG_RESTART="${ARG_RESTART#\*}"; ARG_RESTART_RECURSIVE=1; ;;
- ALL) ARG_RESTART_AT=ALL; ARG_RESTART_RECURSIVE=2; ;;
- LAST) ARG_RESTART_AT=ALL; ARG_RESTART_RECURSIVE=0;
- if [ -n "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}" ]\
- && [ -e "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}" ]; then
- _last_pkg="$(cat "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}")";
- rtl_fileop rm "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}";
- rtl_state_clear "${BUILD_WORKDIR}" "${_last_pkg}";
- ARG_RESTART="${_last_pkg}";
- else
- _rc=1; _status="Error: cannot rebuild last failed package.";
- fi; ;;
- esac;
- if [ "${_rc:-0}" -eq 0 ]; then
- case "${ARG_RESTART}" in
- *:*) ARG_RESTART_AT="${ARG_RESTART#*:}"; ARG_RESTART="$(rtl_llift "${ARG_RESTART%%:*}" "," " ")"; ;;
- *) ARG_RESTART="$(rtl_llift "${ARG_RESTART}" "," " ")"; ARG_RESTART_AT=ALL; ;;
- esac;
- if ! ex_pkg_load_groups; then
- _rc=1; _status="Error: failed to load build groups.";
- else if ! rtl_lmatch "${ARG_DIST:-}" "rpm" ","\
- && [ -z "${ARG_DUMP_IN:-}" ]\
- && [ "${ARG_DUMP_ON_ABORT:-0}" -eq 0 ]; then
- EX_PKG_BUILD_GROUPS="$(rtl_lfilter "${EX_PKG_BUILD_GROUPS}" "host_deps_rpm")";
- fi;
- if [ -z "${BUILD_GROUPS}" ]; then
- BUILD_GROUPS="${EX_PKG_BUILD_GROUPS}";
- else _foundfl=0; for _group in ${BUILD_GROUPS}; do
- if rtl_lmatch "${EX_PKG_BUILD_GROUPS}" "${_group}"; then
- _foundfl=1; break;
- fi;
- done;
- if [ "${_foundfl}" -eq 0 ]; then
- _foundfl=0; for _group in ${BUILD_GROUPS}; do
- if rtl_lmatch "${EX_PKG_BUILD_GROUPS}" "${_group}"; then
- _rc=1; _status="Error: unknown build group \`${_group}'."; break;
- fi;
- done;
- fi;
+ elif ! buildp_process_restart_spec "${ARG_RESTART:-}"; then
+ _rc=1; _status="Error: failed to process -r specification: ${_status}.";
+ elif ! ex_pkg_load_groups; then
+ _rc=1; _status="Error: failed to load build groups.";
+ else if ! rtl_lmatch "${ARG_DIST:-}" "rpm" ","\
+ && [ -z "${ARG_DUMP_IN:-}" ]\
+ && [ "${ARG_DUMP_ON_ABORT:-0}" -eq 0 ]; then
+ EX_PKG_BUILD_GROUPS="$(rtl_lfilter "${EX_PKG_BUILD_GROUPS}" "host_deps_rpm")";
+ fi;
+ if [ -z "${BUILD_GROUPS}" ]; then
+ BUILD_GROUPS="${EX_PKG_BUILD_GROUPS}";
+ else _foundfl=0; for _group in ${BUILD_GROUPS}; do
+ if rtl_lmatch "${EX_PKG_BUILD_GROUPS}" "${_group}"; then
+ _foundfl=1; break;
fi;
- if [ "${_rc:-0}" -eq 0 ]; then
- if [ -n "${ARG_DIST}" ]; then
- BUILD_GROUPS="$(rtl_lconcat "$(rtl_lfilter "${BUILD_GROUPS}" "dist")" "dist")";
+ done;
+ if [ "${_foundfl}" -eq 0 ]; then
+ _foundfl=0; for _group in ${BUILD_GROUPS}; do
+ if rtl_lmatch "${EX_PKG_BUILD_GROUPS}" "${_group}"; then
+ _rc=1; _status="Error: unknown build group \`${_group}'."; break;
fi;
- if [ -n "${ARG_RESTART}" ] && ! rtl_lmatch "${ARG_RESTART}" "ALL LAST"; then
- for _pkg_name in ${ARG_RESTART}; do
- if ! ex_pkg_find_package "${BUILD_GROUPS}" "${_pkg_name}" >/dev/null; then
- _pkg_names_unknown="$(rtl_lconcat "${_pkg_names_unknown}" "${_pkg_name}")";
- fi;
- done;
- case "$(rtl_llength "${_pkg_names_unknown}")" in
- 0) ;;
- 1) _rc=1; _status="Error: unknown package \`${_pkg_names_unknown}'."; ;;
- *) _rc=1; _status="Error: unknown packages: $(rtl_subst "${_pkg_names_unknown}" " " ", ")"; ;;
- esac;
+ done;
+ fi;
+ fi;
+ if [ "${_rc:-0}" -eq 0 ]; then
+ if [ -n "${ARG_DIST}" ]; then
+ BUILD_GROUPS="$(rtl_lconcat "$(rtl_lfilter "${BUILD_GROUPS}" "dist")" "dist")";
+ fi;
+ if [ -n "${ARG_RESTART}" ] && ! rtl_lmatch "${ARG_RESTART}" "ALL LAST"; then
+ for _pkg_name in ${ARG_RESTART}; do
+ if ! ex_pkg_find_package "${BUILD_GROUPS}" "${_pkg_name}" >/dev/null; then
+ _pkg_names_unknown="$(rtl_lconcat "${_pkg_names_unknown}" "${_pkg_name}")";
fi;
- fi;
+ done;
+ case "$(rtl_llength "${_pkg_names_unknown}")" in
+ 0) ;;
+ 1) _rc=1; _status="Error: unknown package \`${_pkg_names_unknown}'."; ;;
+ *) _rc=1; _status="Error: unknown packages: $(rtl_subst "${_pkg_names_unknown}" " " ", ")"; ;;
+ esac;
fi;
fi;
fi; return "${_rc}";
@@ -146,8 +261,8 @@ buildp_init_getopts() {
local _arg="" _opt="" _rc=0 _shiftfl=0 OPTIND=0; _status="";
: ${ARCH:="nt64"}; : ${BUILD_KIND:="debug"};
ARG_AS_NEEDED=0; ARG_CLEAN_BUILDS=""; ARG_DEBUG_MINIPIX=0; ARG_DIST=""; ARG_DUMP_IN="";
- ARG_DUMP_ON_ABORT=0; ARG_FETCH_FORCE=""; ARG_PARALLEL=1; ARG_RELAXED=0; ARG_RESTART="";
- ARG_RESTART_AT=""; ARG_RESTART_RECURSIVE=""; ARG_VERBOSE=0;
+ ARG_DUMP_ON_ABORT=0; ARG_FETCH_FORCE=""; ARG_PARALLEL=1; ARG_RELAXED=0; ARG_RESET_PKG=0;
+ ARG_RESTART=""; ARG_RESTART_AT=""; ARG_RESTART_RECURSIVE=""; ARG_VERBOSE=0;
while [ "${#}" -gt 0 ]; do
case "${1}" in
--as-needed) ARG_AS_NEEDED=1; _shiftfl=1; ;;
@@ -159,6 +274,8 @@ buildp_init_getopts() {
--dump-on-abort)
ARG_DUMP_ON_ABORT=1; _shiftfl=1; ;;
--debug-minipx) ARG_DEBUG_MINIPIX=1; _shiftfl=1; ;;
+ --help) cat etc/build.usage; exit 0; ;;
+ --reset-state) ARG_RESET_PKG=1; _shiftfl=1; ;;
-v*) _opt="${1#-}"; while [ -n "${_opt}" ]; do
: $((ARG_VERBOSE+=1)); _opt="${_opt#?}";
done; _shiftfl=1; ;;
@@ -190,7 +307,7 @@ buildp_init_getopts() {
C) ARG_CLEAN_BUILDS="${OPTARG}"; ;;
D) ARG_DIST="${OPTARG}"; ;;
F) ARG_FETCH_FORCE="${OPTARG}"; ;;
- h) cat etc/build.usage; exit 0; ;;
+ h) cat etc/build.usage.short; exit 0; ;;
p) ARG_PARALLEL="${OPTARG}"; ;;
P) ARG_PARALLEL="auto";
if [ -n "${2:-}" ]\
@@ -199,7 +316,7 @@ buildp_init_getopts() {
fi; ;;
r) ARG_RESTART="${OPTARG}"; ;;
R) ARG_RELAXED=1; ;;
- *) cat etc/build.usage; exit 1; ;;
+ *) cat etc/build.usage.short; exit 1; ;;
esac; shift $((${OPTIND}-1)); OPTIND=1;
else if rtl_match "${1}" "=*"; then
BUILD_GROUPS_INHIBIT_DEPS=1; _arg="${1#=}";
@@ -241,14 +358,6 @@ buildp_init_getopts() {
return "${_rc}";
};
-buildp_init_getopts_help() {
- local _opt="";
- while getopts a:b:C:D:Fhp:Pr:R _opt 2>/dev/null; do
- case "${_opt}" in
- h) cat etc/build.usage; exit 0; ;;
- esac; done; shift $((${OPTIND}-1));
-};
-
buildp_init_prereqs() {
if ! rtl_check_prereqs \
awk bunzip2 bzip2 cat chmod cmake cp date find flock \
@@ -268,9 +377,8 @@ buildp_init_prereqs() {
build_init() {
local _rc=0; _status="";
if ! buildp_init_env \
- || ! buildp_init_getopts_help "${@}" \
- || ! buildp_init_prereqs \
|| ! buildp_init_getopts "${@}" \
+ || ! buildp_init_prereqs \
|| ! ex_pkg_load_vars \
|| ! buildp_init_args \
|| ! buildp_init_files; then
diff --git a/subr/ex_pkg_dispatch.subr b/subr/ex_pkg_dispatch.subr
index f2b78e3c..4f6c3744 100644
--- a/subr/ex_pkg_dispatch.subr
+++ b/subr/ex_pkg_dispatch.subr
@@ -53,7 +53,7 @@ exp_pkg_dispatch_expand_packages() {
# @_group_name: build group name
# @_njobs_max: maximum count of simultaneous jobs
# @_pipe_path: pathname to build FIFO
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_workdir: pathname to build-specific temporary directory
#
# Return: zero (0) on success, non-zero (>0) on failure, ${EXP_PKG_DISPATCH_COUNT_CUR} may be mutated post-return.
@@ -116,7 +116,7 @@ exp_pkg_dispatch_group() {
# @_dispatch_fn: top-level dispatch function name
# @_group_name: build group name
# @_pkg_name: single package name
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_workdir: pathname to build-specific temporary directory
#
# Return: zero (0) on success, non-zero (>0) on failure, ${EXP_PKG_DISPATCH_NJOBS}, ${EXP_PKG_DISPATCH_COUNT}, ${EX_PKG_NAMES}, and ${EX_PKG_DISPATCH_WAIT} may be mutated post-return.
@@ -158,7 +158,7 @@ exp_pkg_dispatch_package() {
# @_pipe_path: pathname to parent-child process FIFO
# @_pkg_disabled: list of disabled packages
# @_pkg_finished: list of finished packages
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_workdir: pathname to build-specific temporary directory
#
# Return: zero (0) on success, non-zero (>0) on failure, ${EXP_PKG_DISPATCH_NJOBS}, ${EXP_PKG_DISPATCH_COUNT}, ${EX_PKG_NAMES}, and ${EX_PKG_DISPATCH_WAIT} may be mutated post-return.
@@ -198,7 +198,7 @@ exp_pkg_dispatch_packages() {
# @_njobs_max: maximum count of simultaneous jobs
# @_pipe_path: pathname to build FIFO
# @_restart: optional whitespace-separated list of package names to rebuild
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_restart_recursive: optional flag specifiying either no dependency expansion (0,) dependency expansion (1,) dependency expansion and forcibly rebuild (2,) forcibly rebuild reverse dependencies (3.)
# @_workdir: pathname to build-specific temporary directory
#
diff --git a/subr/ex_pkg_env.subr b/subr/ex_pkg_env.subr
index d31f01de..5048c939 100644
--- a/subr/ex_pkg_env.subr
+++ b/subr/ex_pkg_env.subr
@@ -136,7 +136,7 @@ ex_pkg_env_sofort() {
# @_group_name: build group name
# @_nounset: don't clear package variable namespace
# @_pkg_name: single package name
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_workdir: pathname to build-specific temporary directory
#
# Return: zero (0) on success, non-zero (>0) on failure
@@ -154,9 +154,9 @@ ex_pkg_env() {
#
# ex_pkg_state_set() - update build step status for single named package
-# @_workdir: pathname to temporary build directory
# @_pkg_name: single package name
-# @${@}: list of build steps
+# @_build_step: build step set status of
+# [@${@}]: optional list of build steps to invalidate status of
#
# Return: zero (0) on success, non-zero (>0) on failure
#
@@ -166,10 +166,9 @@ ex_pkg_state_set() {
#
# ex_pkg_state_test() - test build step status of single named package
-# @_workdir: pathname to temporary build directory
# @_pkg_name: single package name
# @_build_step: build step to test status of
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
#
# Return: zero (0) on success, non-zero (>0) on failure
#
diff --git a/subr/ex_pkg_exec.subr b/subr/ex_pkg_exec.subr
index 992b7c8c..ee49b87d 100644
--- a/subr/ex_pkg_exec.subr
+++ b/subr/ex_pkg_exec.subr
@@ -21,7 +21,7 @@ exp_pkg_exec_filter_vars_fn() {
# exp_pkg_exec_pre() - XXX
# @_group_name: build group name
# @_pkg_name: single package name
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
#
# Return: zero (0) on success, non-zero (>0) on failure
#
@@ -51,7 +51,7 @@ exp_pkg_exec_pre() {
# exp_pkg_exec_step() - XXX
# @_group_name: build group name
# @_pkg_name: single package name
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
# @_step: build step to execute
#
# Return: zero (0) on success, non-zero (>0) on failure
@@ -81,47 +81,49 @@ exp_pkg_exec_step() {
# @_dispatch_fn: top-level dispatch function name
# @_group_name: build group name
# @_pkg_name: single package name
-# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL
+# @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL or LAST
#
# Return: zero (0) on success, non-zero (>0) on failure
#
ex_pkg_exec() {
local _dispatch_fn="${1}" _group_name="${2}" _pkg_name="${3}" _restart_at="${4}" \
- _rc=0 _step="" _step_next="";
- if exp_pkg_exec_pre "${_group_name}" "${_pkg_name}" "${_restart_at}"\
- && "${_dispatch_fn}" start_pkg_child "${_group_name}" "${_pkg_name}"; then
- if rtl_test_cmd "pkg_${_pkg_name}_all"; then
- "pkg_${_pkg_name}_all" "${_restart_at}"; _rc="${?}";
- else set -- ${PKG_BUILD_STEPS};
- while [ ${#} -gt 0 ]; do
- _step="${1}"; _step_next="${2:-}"; shift;
- if [ "${ARG_DUMP_IN}" = "${_step}" ]; then
- printf "" > "${BUILD_WORKDIR}/${_pkg_name}.dump";
- rtl_filter_vars exp_pkg_exec_filter_vars_fn >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
- export >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
- exit 1;
- elif [ "${PKG_FORCE:-0}" -eq 0 ]\
- && ex_pkg_state_test "${_pkg_name}" "${_step}" "${_restart_at}" ; then
- continue;
- elif ! exp_pkg_exec_step "${_group_name}" "${_pkg_name}" "${_restart_at}" "${_step}"; then
- _rc=1; break;
- else
- printf "step %s %s %s\n" "${_group_name}" "${_pkg_name}" "${_step}" >&3;
- ex_pkg_state_set "${_pkg_name}" "${_step}" "${_step_next:+-${_step_next}}";
- fi;
- done;
- fi;
- if [ "${_rc:-0}" -eq 0 ]; then
- if [ -z "${_restart_at}" ]\
- || [ "${_restart_at}" = "ALL" ]; then
- ex_pkg_state_set "${_pkg_name}" finish;
+ _build_step_last="" _rc=0 _step="";
+
+ if ! exp_pkg_exec_pre "${_group_name}" "${_pkg_name}" "${_restart_at}"\
+ || ! "${_dispatch_fn}" start_pkg_child "${_group_name}" "${_pkg_name}"; then
+ _rc=1;
+ elif rtl_test_cmd "pkg_${_pkg_name}_all"; then
+ "pkg_${_pkg_name}_all" "${_restart_at}"; _rc="${?}";
+ else set -- $(rtl_lfilter "${PKG_BUILD_STEPS}" "start");
+ while [ ${#} -gt 0 ]; do
+ _step="${1}"; shift;
+ if [ "${#_restart_at}" -gt 0 ]\
+ && [ "${_restart_at}" != "ALL" ]\
+ && [ "${_restart_at}" != "LAST" ]\
+ && ! rtl_lmatch "${_restart_at}" "${_step}" ","; then
+ continue;
fi;
- elif [ "${_rc:-0}" -ne 0 ]\
- && [ "${ARG_DUMP_ON_ABORT:-0}" -eq 1 ]; then
- printf "" > "${BUILD_WORKDIR}/${_pkg_name}.dump";
- rtl_filter_vars exp_pkg_exec_filter_vars_fn >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
- export >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
- fi;
+ if [ "${_step}" = "${ARG_DUMP_IN}" ]; then
+ printf "" > "${BUILD_WORKDIR}/${_pkg_name}.dump";
+ rtl_filter_vars exp_pkg_exec_filter_vars_fn >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
+ export >> "${BUILD_WORKDIR}/${_pkg_name}.dump"; exit 1;
+ elif [ "${_step}" = "finish" ]; then
+ ex_pkg_state_set "${_pkg_name}" finish; break;
+ elif [ "${PKG_FORCE:-0}" -eq 0 ]\
+ && ex_pkg_state_test "${_pkg_name}" "${_step}" "${_restart_at}"; then
+ continue;
+ elif ! exp_pkg_exec_step "${_group_name}" "${_pkg_name}" "${_restart_at}" "${_step}"; then
+ _rc=1; break;
+ else printf "step %s %s %s\n" "${_group_name}" "${_pkg_name}" "${_step}" >&3;
+ ex_pkg_state_set "${_pkg_name}" "${_step}" "${@}";
+ fi;
+ done;
+ fi;
+ if [ "${_rc:-0}" -ne 0 ]\
+ && [ "${ARG_DUMP_ON_ABORT:-0}" -eq 1 ]; then
+ printf "" > "${BUILD_WORKDIR}/${_pkg_name}.dump";
+ rtl_filter_vars exp_pkg_exec_filter_vars_fn >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
+ export >> "${BUILD_WORKDIR}/${_pkg_name}.dump";
fi;
return "${_rc}";
};