# # Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 LucĂ­a Andrea Illanes Albornoz # set +o errexit -o noglob -o nounset is assumed. # # # ex_pkg_check_depends() - check single named package for unsatisfied dependencies # @_checkfl: enable (1) or inhibit (0) dependency expansion # @_rpkg_disabled: in reference to variable of list of disabled packages # @_rpkg_finished: in reference to variable of list of finished packages # @_pkg_name: single package name # @_rpkg_names: in reference to variable of list of package names # @_workdir: pathname to build-specific temporary directory # # Returns: zero (0) given no outstanding dependencies, non-zero (>0) otherwise # ex_pkg_check_depends() { local _epcd_checkfl="${1}" _epcd_rpkg_disabled="${2}" _epcd_rpkg_finished="${3#\$}" \ _epcd_pkg_name="${4}" _epcd_rpkg_names="${5#\$}" _epcd_workdir="${6}" \ _epcd_dependfl=0 _epcd_depends="" _epcd_pkg_name_depend=""; if [ "${_epcd_checkfl}" -eq 1 ]\ && rtl_get_var_unsafe \$_epcd_depends -u "PKG_"${_epcd_pkg_name}"_DEPENDS"\ && [ "${_epcd_depends:+1}" = 1 ]; then for _epcd_pkg_name_depend in ${_epcd_depends}; do if ! rtl_lmatch "${_epcd_rpkg_disabled}" "${_epcd_pkg_name_depend}"\ && ! ex_pkg_state_test2 "${_epcd_workdir}" "${_epcd_pkg_name_depend}" finish; then if ! rtl_lmatch "${_epcd_rpkg_names}" "${_epcd_pkg_name_depend}"; then rtl_log_msgV "fatalexit" "${MSG_build_unknown_dep}" "${_epcd_pkg_name_depend}" "${_epcd_pkg_name}"; else _epcd_dependfl=1; break; fi; fi; done; fi; return "${_epcd_dependfl}"; }; # # ex_pkg_check_depends_unknown() - check single named package for unknown dependencies # @_pkg_name: single package name # @_rpkg_names_set: in reference to variable of set of package names # @_rpkg_unknown: out reference to variable of list of finished packages # # Returns: zero (0) given no unknown dependencies, non-zero (>0) otherwise # ex_pkg_check_depends_unknown() { local _epcdu_pkg_name="${1}" _epcdu_rpkg_names_set="${2#\$}" \ _epcdu_rpkg_unknown="${3#\$}" \ _epcdu_defined=0 _epcdu_depends="" _epcdu_pkg_name_depend="" \ _epcdu_rc=0; if rtl_get_var_unsafe \$_epcdu_depends -u "PKG_"${_epcdu_pkg_name}"_DEPENDS"\ && [ "${_epcdu_depends:+1}" = 1 ]; then for _epcdu_pkg_name_depend in ${_epcdu_depends}; do if ! rtl_get_var_unsafe \$_epcdu_defined "${_epcdu_rpkg_names_set}_${_epcdu_pkg_name_depend}"\ || [ "${_epcdu_defined:-0}" -eq 0 ]; then rtl_lconcat "${_epcdu_rpkg_unknown}" "${_epcdu_pkg_name_depend}"; _epcdu_rc=1; fi; done; fi; return "${_epcdu_rc}"; }; # # ex_pkg_copy_group_vars() - copy build group variables into build group # @_group_name_src: single source build group name # @_group_name_dst: single destination build group name # @[_build_vars_default]: optional list of default build variables, defaults to ${DEFAULT_BUILD_VARS} # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_copy_group_vars() { local _epcgv_group_name_src="${1#\$}" _epcgv_group_name_dst="${2#\$}" \ _epcgv_build_vars_default="${3:-${DEFAULT_BUILD_VARS}}" \ _epcgv_group_name_dst_uc="" _epcgv_group_name_src_uc="" \ _epcgv_vname="" _epcgv_vval=""; rtl_toupper2 \$_epcgv_group_name_dst \$_epcgv_group_name_dst_uc; rtl_toupper2 \$_epcgv_group_name_src \$_epcgv_group_name_src_uc; for _epcgv_vname in ${_epcgv_build_vars_default}; do if rtl_get_var_unsafe \$_epcgv_vval "${_epcgv_group_name_src_uc}_${_epcgv_vname}"\ && [ "${_epcgv_vval:+1}" = 1 ]; then rtl_set_var_unsafe "${_epcgv_group_name_dst_uc}_${_epcgv_vname}" "${_epcgv_vval}"; fi; done; return 0; }; # # ex_pkg_find_package() - find build group a single named package belongs to # @_rgroup_name: out reference to variable of build group name # @_group_names: build group names # @_pkg_name: single named package # # Returns: zero (0) on success, non-zero (>0) if package not found, group name on stdout if package was found. # ex_pkg_find_package() { local _epfp_rgroup_name="${1#\$}" _epfp_group_names="${2}" _epfp_pkg_name="${3}" \ _epfp_foundfl=0 _epfp_group_name="" _epfp_pkg_names=""; for _epfp_group_name in ${_epfp_group_names}; do if rtl_get_var_unsafe \$_epfp_pkg_names -u "${_epfp_group_name}_PACKAGES"\ && [ "${_epfp_pkg_names:+1}" = 1 ]\ && rtl_lmatch \$_epfp_pkg_names "${_epfp_pkg_name}"; then _epfp_foundfl=1; break; fi; done; case "${_epfp_foundfl:-0}" in 0) eval ${_epfp_rgroup_name}=; return 1; ;; 1) eval ${_epfp_rgroup_name}='${_epfp_group_name}'; return 0; ;; esac; }; # # ex_pkg_get_default() - get single package default value # @_rdefault: out reference to variable of default value or "" on end of list # @_default_idx: one-based single default value index # @_pkg_name: single package name # @_pkg_version: single package version # @_ldefault: SP-separated list of default value names (any of: patches, patches_pre, vars_files) # # Returns: zero (0) on success, non-zero (>0) on invalid default value name or unknown package. # ex_pkg_get_default() { local _epgd_rdefault="${1#\$}" _epgd_default_idx="${2}" _epgd_pkg_name="${3}" \ _epgd_pkg_version="${4}" _epgd_ldefault="${5}" \ _epgd_default="" _epgd_group_name="" _epgd_patch_fname="" \ _epgd_pkg_name_full="" _epgd_pkg_patches_extra="" _epgd_rc=0; set --; _epgd_pkg_name_full="${_epgd_pkg_name}${_epgd_pkg_version:+-${_epgd_pkg_version}}"; _epgd_rc=0; for _epgd_default in ${_epgd_ldefault}; do case "${_epgd_default}" in patches) rtl_get_var_unsafe \$_epgd_pkg_patches_extra -u "PKG_${_epgd_pkg_name}_PATCHES_EXTRA"; set +o noglob; set -- \ "${@}" \ "${MIDIPIX_BUILD_PWD}/patches/${_epgd_pkg_name}/"*.patch \ "${MIDIPIX_BUILD_PWD}/patches/${_epgd_pkg_name_full}.local.patch" \ "${MIDIPIX_BUILD_PWD}/patches/${_epgd_pkg_name_full}.local@${BUILD_HNAME}.patch" \ ${_epgd_pkg_patches_extra}; set -o noglob; ;; patches_pre) set -- \ "${@}" \ "${MIDIPIX_BUILD_PWD}/patches/${_epgd_pkg_name_full}_pre.local.patch" \ "${MIDIPIX_BUILD_PWD}/patches/${_epgd_pkg_name_full}_pre.local@${BUILD_HNAME}.patch"; ;; vars_files) rtl_get_var_unsafe \$_epgd_group_name -u "PKG_${_epgd_pkg_name}_GROUP"; set -- \ "vars/${_epgd_pkg_name}.vars" \ "vars.${_epgd_group_name}/${_epgd_pkg_name}.vars"; ;; *) _epgd_rc=1; break; ;; esac; done; if [ "${_epgd_rc}" = 0 ]; then eval ${_epgd_rdefault}="\${${_epgd_default_idx}:-}"; fi; return "${_epgd_rc}"; }; # # ex_pkg_get_packages() - get list of packages belonging to single named build group # @_rpkg_names: out reference to variable of package names # @_group_name: build group name # # Returns: zero (0) on success, non-zero (>0) on failure, list of package names on stdout on success. # ex_pkg_get_packages() { local _epgp_rpkg_names="${1#\$}" _epgp_group_name="${2}" \ _epgp_pkg_names=""; if rtl_get_var_unsafe \$_epgp_pkg_names -u "${_epgp_group_name}_PACKAGES"\ && [ "${_epgp_pkg_names:+1}" = 1 ]; then eval ${_epgp_rpkg_names}='${_epgp_pkg_names}'; return 0; else eval ${_epgp_rpkg_names}=; return 1; fi; }; # # ex_pkg_get_package_vars() - get package variable names # @_rpkg_vnames: out reference to package variable names variable # @_build_vars_default: list of default build variables # @_pkg_name: single package name # # Returns: zero (0) on success, non-zero (>0) on failure, list of package names on stdout on success. # ex_pkg_get_package_vars() { local _epgpv_rpkg_vnames="${1#\$}" _epgpv_build_vars_default="${2}" _epgpv_pkg_name="${3}" \ _epgpv_pkg_name_uc="" _epgpv_vname="" _epgpv_vnames=""; rtl_toupper2 \$_epgpv_pkg_name \$_epgpv_pkg_name_uc; for _epgpv_vname in ${_epgpv_build_vars_default}; do if eval [ \"\${PKG_${_epgpv_pkg_name_uc}_${_epgpv_vname}:+1}\" = 1 ]; then rtl_lconcat \$_epgpv_vnames "PKG_${_epgpv_pkg_name_uc}_${_epgpv_vname}"; fi; done; eval ${_epgpv_rpkg_vnames}='${_epgpv_vnames}'; return 0; }; # # ex_pkg_load_vars() - load build variables # @_rstatus: out reference to status string # @_rbuild_arch: in reference to build architecture # @_rbuild_kind: in reference to build kind # # Returns: zero (0) on success, non-zero (>0) on failure, build variables post-return on success. # ex_pkg_load_vars() { local _eplv_rstatus="${1#\$}" _eplv_rbuild_arch="${2#\$}" _eplv_rbuild_kind="${3#\$}" \ _eplv_build_arch="" _eplv_rc=0 _eplv_fname=""; if ! rtl_lmatch "${_eplv_rbuild_arch}" "nt32 nt64"; then _eplv_rc=1; rtl_setrstatus "${_eplv_rstatus}" 'invalid architecture \`${'"${_eplv_rbuild_arch}"'}'\''.'; elif ! rtl_lmatch "${_eplv_rbuild_kind}" "debug release"; then _eplv_rc=1; rtl_setrstatus "${_eplv_rstatus}" 'unknown build type \`${'"${_eplv_rbuild_kind}"'}'\''.'; else eval _eplv_build_arch="\${${_eplv_rbuild_arch}}"; case "${_eplv_build_arch}" in nt32) DEFAULT_TARGET="i686-nt32-midipix"; ;; nt64) DEFAULT_TARGET="x86_64-nt64-midipix"; ;; esac; if [ "${PREFIX_ROOT:+1}" ]\ && [ "${PREFIX_ROOT#/}" = "${PREFIX_ROOT}" ]; then PREFIX_ROOT="${PWD%/}/${PREFIX_ROOT}"; fi; if [ "${PREFIX:+1}" ]\ && [ "${PREFIX#/}" = "${PREFIX}" ]; then PREFIX="${PWD%/}/${PREFIX}"; fi; for _eplv_fname in \ "${HOME}/midipix_build.vars" \ "${HOME}/.midipix_build.vars" \ ../midipix_build.vars; do if [ -r "${_eplv_fname}" ]; then rtl_fileop source "${_eplv_fname}"; fi; done; set +o noglob; for _eplv_fname in \ ./vars.env.d/*.env; do set -o noglob; if [ -r "${_eplv_fname}" ]; then rtl_fileop source "${_eplv_fname}"; fi; done; set -o noglob; fi; return "${_eplv_rc}"; }; # # ex_pkg_load_groups() - load all available build groups # @_rgroups: out reference to variable of build groups # @_rgroups_noauoto: optional out reference to variable of build groups not built automatically # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_load_groups() { local _eplg_rgroups="${1#\$}" _eplg_rgroups_noauto="${2#\$}" \ _eplg_build_groups="" _eplg_build_groups_noauto="" _eplg_fname=""; EXP_PKG_REGISTER_GROUP_RGROUPS="${_eplg_rgroups}"; EXP_PKG_REGISTER_GROUP_RGROUPS_NOAUTO="${_eplg_rgroups_noauto}"; for _eplg_fname in $(find ./groups.d -name *.group | sort); do rtl_fileop source_with_fnamevar "${_eplg_fname}"; done; unset EXP_PKG_REGISTER_GROUP_RGROUPS; unset EXP_PKG_REGISTER_GROUP_RGROUPS_NOAUTO; for _eplg_fname in $(find ./groups.d -mindepth 2 -name *.package | sort); do rtl_fileop source_with_fnamevar "${_eplg_fname}"; done; return 0; }; # # ex_pkg_register() - register single package # @_pkg_name: single package name # @_fname: pathname to file package is defined in, relative to midipix_build root # @[_group_name]: optional build group name; inferred from @_fname if not specified # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_register() { local _epr_pkg_name="${1}" _epr_fname="${2}" _epr_group_name="${3:-}" \ _epr_group_name_uc="" _epr_group_noautofl=0; if [ "${_epr_group_name:+1}" != 1 ]; then _epr_group_name="${_epr_fname#./*/}"; _epr_group_name="${_epr_group_name%%/*}"; _epr_group_name="${_epr_group_name%.d}"; _epr_group_name="${_epr_group_name#*.}"; fi; rtl_toupper2 \$_epr_group_name \$_epr_group_name_uc; rtl_lconcat "\$${_epr_group_name_uc}_PACKAGES" "${_epr_pkg_name}"; rtl_set_var_unsafe -u "PKG_${_epr_pkg_name}_GROUP" "${_epr_group_name}"; rtl_set_var_unsafe -u "PKG_${_epr_pkg_name}_GROUP_FNAME" "${_epr_fname}"; return 0; }; # # ex_pkg_register_group() - register single group # @_group_name: single group name # @_fname: pathname to file group is defined in, relative to midipix_build root # @[_ownerfl]: "owner" for groups that own their packages, "copy" for shorthand groups referring to packages from other groups # @[_autofl]: "auto" for groups to build by default, "noauto" for optional groups only built when requested # ${EXP_PKG_REGISTER_GROUP_RGROUPS}: inout reference to variable of build groups # ${EXP_PKG_REGISTER_GROUP_RGROUPS_NOAUTO}: inout reference to variable of build groups only built when requested # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_register_group() { local _eprg_group_name="${1}" _eprg_fname="${2}" \ _eprg_ownerfl="${3:-owner}" _eprg_autofl="${4:-auto}" \ _eprg_pkg_name="" _eprg_pkg_names="" _eprg_rgroups=""; case "${_eprg_autofl}" in auto) _eprg_rgroups="${EXP_PKG_REGISTER_GROUP_RGROUPS}"; ;; noauto) _eprg_rgroups="${EXP_PKG_REGISTER_GROUP_RGROUPS_NOAUTO}"; ;; *) ;; esac; if ! rtl_lmatch "${_eprg_rgroups}" "${_eprg_group_name}"; then rtl_lconcat "${_eprg_rgroups}" "${_eprg_group_name}"; fi; case "${_eprg_ownerfl}" in owner) if rtl_get_var_unsafe \$_eprg_pkg_names -u "${_eprg_group_name}_PACKAGES"\ && [ "${_eprg_pkg_names:+1}" = 1 ]; then for _eprg_pkg_name in ${_eprg_pkg_names}; do rtl_set_var_unsafe -u "PKG_${_eprg_pkg_name}_GROUP" "${_eprg_group_name}"; rtl_set_var_unsafe -u "PKG_${_eprg_pkg_name}_GROUP_FNAME" "${_eprg_fname}"; done; fi; ;; copy) ;; *) ;; esac; return 0; }; # # ex_pkg_unfold_depends() - unfold list of package names into dependency-expanded set of complete, disabled, finished, and outstanding package names # @_rdisabled: in reference to out variable of disabled packages # @_rfinished: in reference to out variable of finished packages # @_rnames: out reference to variable of package names # @_checkfl: enable (1) or inhibit (0) dependency expansion # @_forcefl: enable (1) or inhibit (0) forcibly rebuilding finished packages # @_group_name: build group name # @_pkg_names: list of package names # @_restart: optional whitespace-separated list of package names to rebuild # @_test_finished: only exclude disabled packages (0,) split finished packages # @_workdir: pathname to build-specific temporary directory # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_unfold_depends() { local _epud_rdisabled="${1#\$}" _epud_rfinished="${2#\$}" _epud_rnames="${3#\$}" \ _epud_checkfl="${4}" _epud_forcefl="${5}" _epud_group_name="${6}" \ _epud_pkg_names="${7}" _epud_restart="${8}" _epud_test_finished="${9}" \ _epud_workdir="${10}" \ _epud_depends="" _epud_pkg_disabled="" _epud_pkg_force="" _epud_pkg_name="" \ _epud_pkg_name_depend="" _epud_pkg_names_new="" _epud_pkg_names_set="" \ _epud_pkg_unknown="" _epud_restartfl=0 _epud_unknown_depends=0; if [ "${_epud_restart:+1}" = 1 ]\ && ! rtl_lmatch \$_epud_restart "ALL LAST"; then rtl_lsearch \$_epud_pkg_names "${_epud_restart}"; fi; if [ "${_epud_restart:+1}" = 1 ]\ && [ "${_epud_checkfl:-0}" -eq 1 ]; then rtl_lunfold_dependsV 'PKG_${_rld_name}_DEPENDS' \$_epud_pkg_names ${_epud_pkg_names}; _epud_pkg_names="$(rtl_uniq ${_epud_pkg_names})"; fi; rtl_llift_set \$_epud_pkg_names \$_epud_pkg_names_set; for _epud_pkg_name in ${_epud_pkg_names}; do if rtl_get_var_unsafe \$_epud_depends -u "PKG_"${_epud_pkg_name}"_DEPENDS"\ && [ "${_epud_depends:+1}" = 1 ]; then _epud_pkg_unknown=""; if ! ex_pkg_check_depends_unknown "${_epud_pkg_name}" \$_epud_pkg_names_set \$_epud_pkg_unknown; then for _epud_pkg_name_depend in ${_epud_pkg_unknown}; do rtl_log_msgV "warning" "${MSG_build_unknown_dep}" "${_epud_pkg_name_depend}" "${_epud_pkg_name}"; done; _epud_unknown_depends=1; fi; fi; if [ "${_epud_restart}" = "ALL" ]\ || rtl_lmatch \$_epud_restart "${_epud_pkg_name}"; then _epud_restartfl=1; else _epud_restartfl=0; fi; if rtl_get_var_unsafe \$_epud_pkg_disabled -u "PKG_${_epud_pkg_name}_DISABLED"\ && [ "${_epud_pkg_disabled}" = 1 ]; then rtl_lconcat "${_epud_rdisabled}" "${_epud_pkg_name}"; elif [ "${_epud_test_finished:-1}" -eq 1 ]\ && ex_pkg_state_test2 "${_epud_workdir}" "${_epud_pkg_name}" finish\ && [ "${_epud_restartfl:-0}" -eq 0 ]\ && [ "${_epud_forcefl:-0}" -ne 1 ]\ && rtl_get_var_unsafe \$_epud_pkg_force -u "${_epud_group_name}_FORCE"\ && [ "${_epud_pkg_force}" != 1 ]; then rtl_lconcat "${_epud_rfinished}" "${_epud_pkg_name}"; else rtl_lconcat \$_epud_pkg_names_new "${_epud_pkg_name}"; fi; done; rtl_llift_unset \$_epud_pkg_names_set; if [ "${_epud_unknown_depends}" -eq 1 ]; then rtl_log_msgV "warning" "${MSG_build_unknown_deps}"; fi; eval ${_epud_rdisabled}='$(rtl_uniq2 "${_epud_rdisabled}")'; eval ${_epud_rfinished}='$(rtl_uniq2 "${_epud_rfinished}")'; eval ${_epud_rnames}='$(rtl_uniq "${_epud_pkg_names_new}")'; return 0; }; # # ex_pkg_unfold_rdepends() - unfold list of package names into reverse dependency-expanded set of complete, disabled, finished, and outstanding package names # @_rdisabled: in reference to out variable of disabled packages # @_rfinished: in reference to out variable of finished packages # @_rnames: out reference to variable of package names # @_group_name: build group name # @_pkg_names: list of package names # @_restart: optional whitespace-separated list of package names to rebuild # @_test_finished: only exclude disabled packages (0,) split finished packages # @_workdir: pathname to build-specific temporary directory # @_recursefl: resolve recursively ("recurse") or non-recursively ("norecurse") # # Returns: zero (0) on success, non-zero (>0) on failure. # ex_pkg_unfold_rdepends() { local _epur_rdisabled="${1#\$}" _epur_rfinished="${2#\$}" _epur_rnames="${3#\$}" \ _epur_group_name="${4}" _epur_pkg_names="${5}" _epur_restart="${6}" \ _epur_test_finished="${7}" _epur_workdir="${8}" _epur_recursefl="${9}" \ _epur_depends="" _epur_disabled=0 _epur_force=0 _epur_pkg_depends="" \ _epur_pkg_name="" _epur_pkg_names_new="" _epur_pkg_name_depend="" \ _epur_pkg_name_rdepend="" _epur_pkg_rdepends=""; for _epur_pkg_name_depend in ${_epur_restart}; do for _epur_pkg_name in ${_epur_pkg_names}; do if [ "${_epur_pkg_name}" = "${_epur_pkg_name_depend}" ]; then continue; elif rtl_get_var_unsafe \$_epur_depends -u "PKG_"${_epur_pkg_name}"_DEPENDS"\ && rtl_lunfold_dependsV 'PKG_${_rld_name}_DEPENDS' \$_epur_pkg_depends ${_epur_depends}\ && [ "${_epur_pkg_depends:+1}" = 1 ]\ && rtl_lmatch \$_epur_pkg_depends "${_epur_pkg_name_depend}"; then case "${_epur_recursefl}" in recurse) _epur_pkg_rdepends="${_epur_pkg_name} ${_epur_pkg_depends}"; ;; norecurse) _epur_pkg_rdepends="${_epur_pkg_name}"; ;; esac; for _epur_pkg_name_rdepend in ${_epur_pkg_rdepends}; do if rtl_get_var_unsafe \$_epur_disabled -u "PKG_${_epur_pkg_name_rdepend}_DISABLED"\ && [ "${_epur_disabled}" = 1 ]; then rtl_lconcat "${_epur_rdisabled}" "${_epur_pkg_name_rdepend}"; elif [ "${_epur_test_finished}" -eq 1 ]\ && ex_pkg_state_test2 "${_epur_workdir}" "${_epur_pkg_name_rdepend}" finish\ && rtl_get_var_unsafe \$_epur_force -u "${_epur_group_name}_FORCE"\ && [ "${_epur_force}" != 1 ]; then rtl_lconcat "${_epur_rfinished}" "${_epur_pkg_name_rdepend}"; elif [ "${_epur_test_finished:-1}" -eq 0 ]\ || ! ex_pkg_state_test2 "${_epur_workdir}" "${_epur_pkg_name_rdepend}" finish\ || ( rtl_get_var_unsafe \$_epur_force -u "${_epur_group_name}_FORCE"\ && [ "${_epur_force}" = 1 ] ); then rtl_lconcat \$_epur_pkg_names_new "${_epur_pkg_name_rdepend}"; fi; done; fi; done; done; eval ${_epur_rdisabled}='$(rtl_uniq2 "${_epur_rdisabled}")'; eval ${_epur_rfinished}='$(rtl_uniq2 "${_epur_rfinished}")'; eval ${_epur_rnames}='$(rtl_uniq "${_epur_pkg_names_new}")'; return 0; }; # vim:filetype=sh textwidth=0