# # set +o errexit -o noglob is assumed. # # # exp_pkg_dispatch_complete() - XXX # @_dispatch_fn: top-level dispatch function name # @_group_names: build group name(s) # @_pkg_disabled: list of disabled packages # @_pkg_finished: list of finished packages # # Return: zero (0) on success, non-zero (>0) on failure. # exp_pkg_dispatch_complete() { local _dispatch_fn="${1}" _group_name="${2}" _pkg_disabled="${3}" _pkg_finished="${4}" _pkg_name=""; for _pkg_name in ${_pkg_disabled}; do "${_dispatch_fn}" disabled_pkg "${_group_name}" "${_pkg_name}"; done; for _pkg_name in ${_pkg_finished}; do "${_dispatch_fn}" skipped_pkg "${_group_name}" "${_pkg_name}"; done; }; # # exp_pkg_dispatch_group() - dispatch a single build group # @_build_steps_default: list of default build steps # @_build_vars_default: list of default build variables # @_dispatch_fn: top-level dispatch function name # @_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_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 # # Return: zero (0) on success, non-zero (>0) on failure. # exp_pkg_dispatch_group() { local _build_steps_default="${1}" _build_vars_default="${2}" _dispatch_fn="${3}" \ _group_name="${4}" _njobs_max="${5}" _pipe_path="${6}" _restart_at="${7}" \ _restart_recursive="${8}" _workdir="${9}" _pipe_msg="" _pkg_name="" _rc=0; rtl_fileop mkfifo "${_pipe_path}"; while true; do while [ "${EXP_PKG_DISPATCH_NJOBS:-0}" -gt 0 ] && read _pipe_msg; do case "${_pipe_msg%% *}" in done) : $((EXP_PKG_DISPATCH_NJOBS-=1)); _pkg_name="${_pipe_msg#done * }"; "${_dispatch_fn}" finish_pkg ${_pipe_msg#done }; EXP_PKG_COMPLETE="$(rtl_lconcat "${EXP_PKG_COMPLETE}" "${_pkg_name}")"; EXP_PKG_NAMES="$(rtl_lfilter "${EXP_PKG_NAMES}" "${_pkg_name}")"; EX_PKG_DISPATCH_WAIT="$(rtl_lfilter "${EX_PKG_DISPATCH_WAIT}" "${_pkg_name}")"; if [ -n "${EXP_PKG_NAMES}" ] && [ "${_rc}" -eq 0 ]; then if [ "${EXP_PKG_DISPATCH_NJOBS}" -ne "${_njobs_max}" ]; then exp_pkg_dispatch_packages "${_build_steps_default}" \ "${_build_vars_default}" "${_dispatch_fn}" \ "${_group_name}" "${_njobs_max}" \ "${_pipe_path}" "${EXP_PKG_COMPLETE}" \ "${_restart_at}" "${_restart_recursive}" "${_workdir}"; fi; elif [ "${EXP_PKG_DISPATCH_NJOBS:-0}" -eq 0 ]; then break; fi; ;; fail) : $((EXP_PKG_DISPATCH_NJOBS-=1)); _rc=1; "${_dispatch_fn}" fail_pkg ${_pipe_msg#fail }; ;; msg_pkg) "${_dispatch_fn}" msg_pkg ${_pipe_msg#msg_pkg }; ;; step) "${_dispatch_fn}" step_pkg ${_pipe_msg#step }; ;; esac; done <>"${_pipe_path}"; if [ -n "${EXP_PKG_NAMES}" ] && [ "${_rc}" -eq 0 ]; then if [ "${EXP_PKG_DISPATCH_NJOBS}" -ne "${_njobs_max}" ]; then exp_pkg_dispatch_packages "${_build_steps_default}" \ "${_build_vars_default}" "${_dispatch_fn}" \ "${_group_name}" "${_njobs_max}" "${_pipe_path}" \ "${EXP_PKG_COMPLETE}" "${_restart_at}" \ "${_restart_recursive}" "${_workdir}"; fi; elif [ "${EXP_PKG_DISPATCH_NJOBS:-0}" -eq 0 ]; then break; fi; done; rtl_fileop rm "${_pipe_path}"; return "${_rc}"; }; # # exp_pkg_dispatch_package() - dispatch single named packages # @_build_steps_default: list of default build steps # @_build_vars_default: list of default build variables # @_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 # @_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}, ${EXP_PKG_NAMES}, and ${EX_PKG_DISPATCH_WAIT} may be mutated post-return. # exp_pkg_dispatch_package() { local _build_steps_default="${1}" _build_vars_default="${2}" _dispatch_fn="${3}" \ _group_name="${4}" _pkg_name="${5}" _restart_at="${6}" _workdir="${7}"; if "${_dispatch_fn}" start_pkg "${_group_name}" "${_pkg_name}" "$((${EXP_PKG_DISPATCH_COUNT}+1))" "${EXP_PKG_DISPATCH_COUNT_MAX}"; then : $((EXP_PKG_DISPATCH_NJOBS+=1)); : $((EXP_PKG_DISPATCH_COUNT+=1)); EX_PKG_DISPATCH_WAIT="$(rtl_lconcat "${EX_PKG_DISPATCH_WAIT}" "${_pkg_name}")"; (set +o errexit -o noglob; BUILD_IS_PARENT=0; if ex_pkg_env "${_build_steps_default}" "${_build_vars_default}" \ "${_group_name}" "${_pkg_name}" "${_restart_at}" "${_workdir}"; then ex_pkg_exec "${_dispatch_fn}" "${_group_name}" "${_pkg_name}" "${_restart_at}"; else return 1; fi;) 1>"${_workdir}/${_pkg_name}_stderrout.log" 2>&1 3>"${_pipe_path}" & else return 1; fi; }; # # exp_pkg_dispatch_packages() - dispatch set of packages # @_build_steps_default: list of default build steps # @_build_vars_default: list of default build variables # @_dispatch_fn: top-level dispatch function name # @_group_name: build group name # @_njobs_max: maximum count of simultaneous jobs # @_pipe_path: pathname to parent-child process FIFO # @_pkg_complete: list of completed packages # @_restart_at: optional comma-separated list of build steps at which to rebuild or ALL # @_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 # # Return: zero (0) on success, non-zero (>0) on failure, ${EXP_PKG_DISPATCH_NJOBS}, ${EXP_PKG_DISPATCH_COUNT}, ${EXP_PKG_NAMES}, and ${EX_PKG_DISPATCH_WAIT} may be mutated post-return. # exp_pkg_dispatch_packages() { local _build_steps_default="${1}" _build_vars_default="${2}" _dispatch_fn="${3}" \ _group_name="${4}" _njobs_max="${5}" _pipe_path="${6}" _pkg_complete="${7}" \ _restart_at="${8}" _restart_recursive="${9}" _workdir="${10}" \ _foundfl=0 _njob=0 _pkg_depends="" _pkg_name=""; while [ "${EXP_PKG_DISPATCH_NJOBS:-0}" -lt "${_njobs_max}" ]; do _foundfl=0; for _pkg_name in ${EXP_PKG_NAMES}; do if ! rtl_lmatch "${_pkg_complete}" "${_pkg_name}"\ && ! rtl_lmatch "${EX_PKG_DISPATCH_WAIT}" "${_pkg_name}"\ && ex_pkg_check_depends "${_pkg_complete}" "${_pkg_name}" "${EX_PKG_DISPATCH_WAIT}" "${_restart_recursive}"; then exp_pkg_dispatch_package "${_build_steps_default}" \ "${_build_vars_default}" "${_dispatch_fn}" \ "${_group_name}" "${_pkg_name}" "${_restart_at}" \ "${_workdir}"; _foundfl=1; break; fi; done; if [ "${_foundfl:-0}" -eq 0 ]; then break; fi; done; }; # # ex_pkg_dispatch() - dispatch a set of build group # @_build_steps_default: list of default build steps # @_build_vars_default: list of default build variables # @_dispatch_fn: top-level dispatch function name # @_group_names: build group name(s) # @_groups_inhibit_deps: inhibit group-group dependency expansion # @_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_recursive: optional flag specifiying either no dependency expansion (0,) dependency expansion (1,) dependency expansion and forcibly rebuild (2.) # @_workdir: pathname to build-specific temporary directory # # Return: zero (0) on success, non-zero (>0) on failure, ${EX_PKG_DISPATCH_UNKNOWN} and ${EX_PKG_DISPATCH_WAIT} mutated post-return. # ex_pkg_dispatch() { local _build_steps_default="${1}" _build_vars_default="${2}" _dispatch_fn="${3}" \ _group_names="${4}" _groups_inhibit_deps="${5}" _njobs_max="${6}" _pipe_path="${7}" \ _restart="${8}" _restart_at="${9}" _restart_recursive="${10}" _workdir="${11}" \ _pkg_name="" _pkg_names="" _rc=0 \ EXP_PKG_COMPLETE EXP_PKG_DISABLED EXP_PKG_FINISHED EXP_PKG_DISPATCH_COUNT \ EXP_PKG_DISPATCH_COUNT_MAX EXP_PKG_DISPATCH_NJOBS EXP_PKG_NAMES; EX_PKG_DISPATCH_WAIT=""; if [ "${_groups_inhibit_deps:-0}" -eq 0 ]; then _group_names="$(rtl_uniq $(rtl_lunfold_depends '${_name}_GROUP_DEPENDS' ${_group_names}))"; fi; for _group_name in ${_group_names}; do EXP_PKG_COMPLETE="" EXP_PKG_DISABLED="" EXP_PKG_FINISHED=""; EXP_PKG_DISPATCH_COUNT=0 EXP_PKG_DISPATCH_COUNT_MAX=0 EXP_PKG_DISPATCH_NJOBS=0; EXP_PKG_NAMES="" EX_PKG_DISPATCH_WAIT=""; if "${_dispatch_fn}" start_group "${_group_name}" ""; then if rtl_fileop mkdir "${_workdir}"\ && rtl_log_msg vnfo "Resolving \`${_group_name}' dependencies..."\ && ex_pkg_expand_packages "${_group_name}" "${_restart}" "${_restart_recursive}"\ && exp_pkg_dispatch_complete "${_dispatch_fn}" "${_group_name}" "${EXP_PKG_DISABLED}" "${EXP_PKG_FINISHED}"\ && rtl_log_msg vnfo "Resolved \`${_group_name}' dependencies."\ && EXP_PKG_DISPATCH_COUNT_MAX="$(rtl_llength "${EXP_PKG_NAMES}")"\ && [ "${EXP_PKG_DISPATCH_COUNT_MAX}" -gt 0 ]; then _pkg_names="$(rtl_lconcat "${_pkg_names}" "${EXP_PKG_NAMES}")"; exp_pkg_dispatch_group "${_build_steps_default}" \ "${_build_vars_default}" "${_dispatch_fn}" "${_group_name}" \ "${_njobs_max}" "${_pipe_path}" "${_restart_at}" \ "${_restart_recursive}" "${_workdir}"; _rc="${?}"; fi; "${_dispatch_fn}" finish_group "${_group_name}" ""; if [ "${_rc}" -ne 0 ]; then break; fi; fi; done; if ! rtl_lmatch "${_restart}" "ALL LAST"; then for _pkg_name in ${_restart}; do if ! rtl_lmatch "${_pkg_names}" "${_pkg_name}"; then EX_PKG_DISPATCH_UNKNOWN="$(rtl_lconcat "${EX_PKG_DISPATCH_UNKNOWN}" "${_pkg_name}")"; fi; done; fi; if [ -n "${EX_PKG_DISPATCH_UNKNOWN}" ]; then _rc=1; fi; return "${_rc}"; }; # vim:filetype=sh textwidth=0