From 8a27f992e5b7c62e144dbbfc3435a90c470d92a4 Mon Sep 17 00:00:00 2001 From: Lucio Andrés Illanes Albornoz Date: Mar 11 2020 16:09:22 +0000 Subject: Initial implementation of pkgtool.sh. build.sh:build(): move cd(1) to $(dirname "${0}"). etc/{build.usage,README.md}: updated. midipix.env:${DEFAULT_CLEAR_ENV_VARS_EXCEPT}: allow inheriting ARCH, BUILD, BUILD_DLCACHEDIR, BUILD_WORKDIR, and PREFIX* from the environment. pkgtool.sh: initial implementation. subr/build_init.subr:buildp_init_defaults(): allow inheriting ARCH, BUILD, BUILD_DLCACHEDIR, BUILD_WORKDIR, and PREFIX* from the environment. subr/build_init.subr:buildp_init_env(): move cd(1) to $(dirname "${0}"). subr/build_init.subr:buildp_init_files(): correctly pass ${_status} from rtl_check_path_vars(). subr/ex_pkg_exec.subr:ex_pkg_exec(): dump subset of variables and exported variables on build failure and --dump-on-abort. subr/pkgtool_init.subr: adapted from subr/build_init.subr. subr/rtl_complex.subr:rtl_filter_vars(): initial implementation. subr/rtl_string.subr:rtl_subst(): initial implementation. --- diff --git a/build.sh b/build.sh index 51c2a23..72883c1 100755 --- a/build.sh +++ b/build.sh @@ -35,12 +35,20 @@ buildp_dispatch_fail_pkg() { : $((BUILD_NFAIL+=1)); BUILD_PKGS_FAILED="$(rtl_lconcat "${BUILD_PKGS_FAILED}" "${_pkg_name}")"; if [ "${ARG_RELAXED:-0}" -eq 1 ]; then rtl_log_msg fail "$(printf "Build failed in \`%s', check \`%s' for details." "${_pkg_name}" "${BUILD_WORKDIR}/${_pkg_name}_stderrout.log")"; + if [ "${ARG_DUMP_ON_ABORT:-0}" -eq 1 ]; then + rtl_log_msg vnfo "Logged environment dump for failed package \`${_pkg_name}' to \`${BUILD_WORKDIR}/${_pkg_name}.dump'."; + fi; else rtl_log_msg fail "${BUILD_WORKDIR}/${_pkg_name}_stderrout.log:"; cat "${BUILD_WORKDIR}/${_pkg_name}_stderrout.log"; if [ -n "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}" ]; then printf "%s" "${_pkg_name}" > "${DEFAULT_BUILD_LAST_FAILED_PKG_FNAME}"; fi; - rtl_log_msg failexit "$(printf "Build failed in \`%s'." "${_pkg_name}")"; + rtl_log_msg fail "$(printf "Build failed in \`%s', check \`%s' for details." "${_pkg_name}" "${BUILD_WORKDIR}/${_pkg_name}_stderrout.log")"; + if [ "${ARG_DUMP_ON_ABORT:-0}" -eq 1 ]; then + rtl_log_msg vnfo "Logged environment dump for failed package \`${_pkg_name}' to \`${BUILD_WORKDIR}/${_pkg_name}.dump'."; + rtl_log_msg vnfo "Enter an interactive package build shell w/ the command line: ./pkgtool.sh -a ${ARCH} -b ${BUILD} ${_pkg_name} PREFIX=\"${PREFIX}\""; + fi; + exit 1; fi; }; @@ -94,9 +102,11 @@ build() { local _build_time_hours=0 _build_time_mins=0 _build_time_secs=0 _pkg_name="" \ BUILD_DATE_START="" BUILD_NFAIL=0 BUILD_NFINI=0 BUILD_NSKIP=0 \ BUILD_PKGS_FAILED="" EX_PKG_DISPATCH_UNKNOWN=""; - if trap "buildp_ast abort" HUP INT TERM USR1 USR2\ - && trap "buildp_ast exit" EXIT\ - && . ./subr/build_init.subr && build_init "${@}"; then + if ! cd "$(dirname "${0}")"; then + printf "Error: failed to setup environment.\n"; exit 1; + elif trap "buildp_ast abort" HUP INT TERM USR1 USR2\ + && trap "buildp_ast exit" EXIT\ + && . ./subr/build_init.subr && build_init "${@}"; then BUILD_DATE_START="$(rtl_date %Y-%m-%d-%H-%M-%S)"; _build_time_secs="$(rtl_date %s)"; rtl_log_msg info "Build started by ${BUILD_USER:=${USER}}@${BUILD_HNAME:=$(hostname)} at ${BUILD_DATE_START}."; rtl_log_env_vars "build (global)" ${DEFAULT_LOG_ENV_VARS}; diff --git a/etc/README.md b/etc/README.md index e0418e6..4d95db9 100644 --- a/etc/README.md +++ b/etc/README.md @@ -178,10 +178,11 @@ Rebuild entire build group: ## 3.1. Fault-tolerant & highly optimised 3D laser show-equipped usage screen ``` -usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-D kind[,..]] - [-F ipv4|ipv6|offline] [-h] [-p jobs] [-P] [-r ALL|LAST] - [-r [*[*[*]]]name[,..][:step,..]] [-R] [-v[v[v[v]]]] [--as-needed] - [--debug-minipix] [[*]|=[ ..]] +usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-d] [-D kind[,..]] + [-F ipv4|ipv6|offline] [-h] [-p jobs] [-P] [-r ALL|LAST] + [-r [*[*[*]]]name[,..][:step,..]] [-R] [-v[v[v[v]]]] [--as-needed] + [--debug-minipix] [--dump-on-abort] + [[*]|=[ ..]] -a nt32|nt64 Selects 32-bit or 64-bit architecture; defaults to nt64. -b debug|release Selects debug or release build; defaults to debug. @@ -226,11 +227,16 @@ usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-D kind[, --as-needed Don't build unless the midipix_build repository has received new commits. --debug-minipix Don't strip(1) minipix binaries to facilitate debugging minipix. + --dump-on-abort Produce package environment dump files on build failure to be + used in conjuction with pkg_shell.sh script. [ ..] One of: dev_packages, dist, host_deps, host_deps_rpm, host_toolchain, host_tools, minipix, native_packages, native_runtime, native_toolchain, native_tools. Prepend w/ `*' to inhibit group-group dependency expansion. + + =[ ..] + Override build or package variable. ``` [Back to top](#table-of-contents) @@ -275,17 +281,27 @@ output. If ``-vvv`` was specified, ``xtrace`` will be set during package builds rudimentary debugging purposes. Additionally, packages using GNU autotools will, if package configuration failed or appears relevant, log the configuration process in detail in, most usually, ``${PKG_BUILD_DIR}/config.log``. + +If ``--dump-on-abort`` was specified, a subset of the variables set and environment +variables will be written to ``${BUILD_WORKDIR}/${PKG_NAME}.dump`` which may subsequently +be used in order to obtain a package build shell environment with ``pkgtool.sh``, e.g.: -Execute the following command line in order to obtain a package build shell environment: ```shell -export MAKE="make LIBTOOL=slibtool"; # Unless ${PKG_LIBTOOL} is set to any value other than `slibtool' -export PATH="/bin:${PATH:+:${PATH}}"; -cd "/tmp/-*/"; +midipix_build@sandbox:(src/midipix_build)> $ ./pkgtool.sh mc +==> 2020/03/11 15:46:28 Launching shell `/usr/bin/zsh' within package environment and `/home/midipix_build/midipix/nt64/debug/tmp'. +==> 2020/03/11 15:46:28 Run $R to rebuild `mc'. +==> 2020/03/11 15:46:28 Run $RS to restart the specified build step of `mc' +==> 2020/03/11 15:46:28 Run $D to automatically regenerate the patch for `mc'. +midipix_build@sandbox:(src/midipix_build)> $ ``` Consult sections [3.2](#32-adding-a-package), [3.4](#34-patches-and-vars-files), [4](#4-build-variables), [4.1](#41-build-steps), and [4.2](#42-package-variables) for further information -concerning the package build process. +concerning the package build process. + +> N.B. When using ``pkgtool.sh`` on a build w/ build variables (see [4](#4-build-variables)) +overriden on command line or via the environment, ensure that they are included in the +``pkgtool.sh`` command line or exported. [Back to top](#table-of-contents) @@ -323,16 +339,14 @@ for a list of package build steps and how they are overriden. The following variables are primarily defined in ``midipix.env`` and may be overriden on a per-build basis on the command-line after the last option -argument, if any, e.g.: +argument, if any, the environment, and/or ``${HOME}/midipix_build.vars``, +``${HOME}/.midipix_build.vars``, and/or ``../midipix_build.vars``, e.g.: ```shell ./build.sh -a nt64 -b release -D minipix,zipdist -P -v PREFIX_ROOT="${HOME}/midipix_tmp" +env ARCH=nt64 BUILD=release PREFIX_ROOT="${HOME}/midipix_tmp" ./build.sh -D minipix,zipdist -P -v ``` -Furthermore, ``${HOME}/midipix_build.vars``, ``${HOME}/.midipix_build.vars``, -and/or ``../midipix_build.vars`` are sourced during build initialisation and -may contain additional overrides, particularly ``${DEFAULT_GITROOT_HEAD}``. - | Variable name | Default value | Description | | ---------------- | ------------------------------- | ----------------------------------------------------------------------------- | | ARCH | nt64 | Target 32-bit (nt32) or 64-bit (nt64) architecture | diff --git a/etc/build.usage b/etc/build.usage index fe87b13..d945317 100644 --- a/etc/build.usage +++ b/etc/build.usage @@ -1,7 +1,8 @@ -usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-D kind[,..]] - [-F ipv4|ipv6|offline] [-h] [-p jobs] [-P] [-r ALL|LAST] - [-r [*[*[*]]]name[,..][:step,..]] [-R] [-v[v[v[v]]]] [--as-needed] - [--debug-minipix] [[*]|=[ ..]] +usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-d] [-D kind[,..]] + [-F ipv4|ipv6|offline] [-h] [-p jobs] [-P] [-r ALL|LAST] + [-r [*[*[*]]]name[,..][:step,..]] [-R] [-v[v[v[v]]]] [--as-needed] + [--debug-minipix] [--dump-on-abort] + [[*]|=[ ..]] -a nt32|nt64 Selects 32-bit or 64-bit architecture; defaults to nt64. -b debug|release Selects debug or release build; defaults to debug. @@ -46,8 +47,13 @@ usage: ./build.sh [-a nt32|nt64] [-b debug|release] [-C dir[,..]] [-D kind[, --as-needed Don't build unless the midipix_build repository has received new commits. --debug-minipix Don't strip(1) minipix binaries to facilitate debugging minipix. + --dump-on-abort Produce package environment dump files on build failure to be + used in conjuction with pkg_shell.sh script. [ ..] One of: dev_packages, dist, host_deps, host_deps_rpm, host_toolchain, host_tools, minipix, native_packages, native_runtime, native_toolchain, native_tools. Prepend w/ `*' to inhibit group-group dependency expansion. + + =[ ..] + Override build or package variable. diff --git a/midipix.env b/midipix.env index f72cb72..38408e8 100644 --- a/midipix.env +++ b/midipix.env @@ -41,7 +41,11 @@ DEFAULT_BUILD_VARS=" : ${BUILD_DLCACHEDIR:="${PREFIX_ROOT}/dlcache"}; : ${BUILD_WORKDIR:="${PREFIX}/tmp"}; : ${DEFAULT_CHECK_PATH_VARS:="PREFIX PREFIX_NATIVE PREFIX_CROSS BUILD_DLCACHEDIR BUILD_WORKDIR"}; -: ${DEFAULT_CLEAR_ENV_VARS_EXCEPT:="HOME PATH TERM USER"}; +: ${DEFAULT_CLEAR_ENV_VARS_EXCEPT:=" + HOME PATH TERM USER \ + ARCH BUILD + BUILD_DLCACHEDIR BUILD_WORKDIR + PREFIX PREFIX_CROSS PREFIX_MINGW32 PREFIX_MINIPIX PREFIX_NATIVE PREFIX_ROOT PREFIX_RPM"}; : ${DEFAULT_CLEAR_PREFIX_PATHS:=" bin i686-nt32-midipix doc include info lib lib64 libexec man minipix minipix_dist native rpm sbin share tmp usr x86_64-nt64-midipix x86_64-w64-mingw32 pkglist.cross pkglist.host diff --git a/pkgtool.sh b/pkgtool.sh new file mode 100755 index 0000000..ec17cc0 --- /dev/null +++ b/pkgtool.sh @@ -0,0 +1,80 @@ +#!/bin/sh +# Copyright (c) 2019 Lucio Andrés Illanes Albornoz +# + +pkgtoolp_restart_at() { + case "${ARG_RESTART_AT}" in + ALL) "${MIDIPIX_BUILD_PWD}/build.sh" -P -r "${PKG_NAME}" -v; ;; + *) "${MIDIPIX_BUILD_PWD}/build.sh" -P -r "${PKG_NAME}:${ARG_RESTART_AT}" -v; ;; + esac; +}; + +pkgtoolp_shell() { + rtl_log_msg info "Launching shell \`${SHELL}' within package environment and \`${PKG_BUILD_DIR}'."; + rtl_log_msg info "Run \$R to rebuild \`${PKG_NAME}'."; + rtl_log_msg info "Run \$RS to restart the specified build step of \`${PKG_NAME}'"; + rtl_log_msg info "Run \$D to automatically regenerate the patch for \`${PKG_NAME}'."; + export ARCH BUILD \ + BUILD_DLCACHEDIR BUILD_WORKDIR \ + MAKE="make LIBTOOL=${PKG_LIBTOOL:-slibtool}" \ + MIDIPIX_BUILD_PWD \ + PKG_NAME \ + PREFIX PREFIX_CROSS PREFIX_MINGW32 PREFIX_MINIPIX \ + PREFIX_NATIVE PREFIX_ROOT PREFIX_RPM; + D="${MIDIPIX_BUILD_PWD}/${0##*/} --update-diff" \ + R="${MIDIPIX_BUILD_PWD}/${0##*/} --restart-at ALL" \ + RS="${MIDIPIX_BUILD_PWD}/${0##*/} --restart-at " \ + "${SHELL}"; +}; + +pkgtoolp_update_diff() { + local _diff_fname_dst="" _diff_fname_src="" _fname="" _fname_base=""; + if [ -n "${PKG_VERSION}" ]; then + _diff_fname_dst="${PKG_NAME}-${PKG_VERSION}.local.patch"; + else + _diff_fname_dst="${PKG_NAME}.local.patch"; + fi; + if ! _diff_fname_src="$(mktemp)"; then + rtl_log_msg failexit "Error: failed to create temporary target diff(1) file."; + else trap "rm -f \"${_diff_fname_src}\" >/dev/null 2>&1" EXIT HUP INT TERM USR1 USR2; + (cd "${PKG_BASE_DIR}" && printf "" > "${_diff_fname_src}"; + for _fname in $(find "${PKG_SUBDIR}" -iname \*.orig); do + _fname_base="${_fname##*/}"; _fname_base="${_fname_base%.orig}"; + case "${_fname_base}" in + config.sub) + continue; ;; + *) diff -u "${_fname}" "${_fname%.orig}" >> "${_diff_fname_src}"; ;; + esac; + done); + if [ "${?}" -ne 0 ]; then + rtl_log_msg failexit "Error: failed to create diff(1)."; + elif ! rtl_fileop mv "${_diff_fname_src}" "${MIDIPIX_BUILD_PWD}/patches/${_diff_fname_dst}"; then + rtl_log_msg failexit "Error: failed to rename diff(1) to \`${MIDIPIX_BUILD_PWD}/patches/${_diff_fname_dst}'."; + else trap - EXIT HUP INT TERM USR1 USR2; + rtl_log_msg info "Updated \`${MIDIPIX_BUILD_PWD}/patches/${_diff_fname_dst}'."; + fi; + fi; +}; + +pkgtool() { + if ! cd "$(dirname "${0}")"\ + || ! . ./subr/pkgtool_init.subr\ + || ! pkgtool_init "${@}"; then + printf "Error: failed to setup environment.\n"; exit 1; + elif [ ! -e "${BUILD_WORKDIR}/${PKG_NAME}.dump" ]; then + rtl_log_msg failexit "Error: failed to locate environment dump for package \`${PKG_NAME}' in \`${BUILD_WORKDIR}'."; + elif ! . "${BUILD_WORKDIR}/${PKG_NAME}.dump"; then + rtl_log_msg failexit "Error: failed to source environment dump for package \`${PKG_NAME}' from \`${BUILD_WORKDIR}'."; + elif ! rtl_fileop cd "${PKG_BUILD_DIR}"; then + rtl_log_msg failexit "Error: failed to change working directory to \`${PKG_BUILD_DIR}'."; + elif [ -n "${ARG_RESTART_AT}" ]; then + pkgtoolp_restart_at; + elif [ "${ARG_UPDATE_DIFF:-0}" -eq 1 ]; then + pkgtoolp_update_diff; + else pkgtoolp_shell; + fi; +}; + +set +o errexit -o noglob; pkgtool "${@}"; + +# vim:filetype=sh textwidth=0 diff --git a/subr/build_init.subr b/subr/build_init.subr index 95641d5..e3bf7b3 100644 --- a/subr/build_init.subr +++ b/subr/build_init.subr @@ -48,14 +48,14 @@ buildp_init_defaults() { local _rc=0; _status=""; # Command-line arguments - ARCH="nt64"; BUILD="debug"; - ARG_AS_NEEDED=0; ARG_CLEAN_BUILDS=""; ARG_DEBUG_MINIPIX=0; ARG_DIST=""; - ARG_FETCH_FORCE=0; ARG_PARALLEL=1; ARG_RELAXED=0; ARG_RESTART=""; ARG_VERBOSE=0; + : ${ARCH:="nt64"}; : ${BUILD:="debug"}; + ARG_AS_NEEDED=0; ARG_CLEAN_BUILDS=""; ARG_DEBUG_MINIPIX=0; ARG_DUMP_ON_ABORT=0; + ARG_DIST=""; ARG_FETCH_FORCE=0; ARG_PARALLEL=1; ARG_RELAXED=0; ARG_RESTART=""; + ARG_VERBOSE=0; # Build parameters & state - BUILD_DLCACHEDIR=""; BUILD_HNAME=""; BUILD_IS_PARENT=1; BUILD_GROUPS=""; - BUILD_GROUPS_INHIBIT_DEPS=0; BUILD_TARGET=""; BUILD_USER=""; BUILD_WORKDIR=""; - MIDIPIX_BUILD_PWD=""; PREFIX=""; PREFIX_RPM=""; + BUILD_HNAME=""; BUILD_IS_PARENT=1; BUILD_GROUPS=""; BUILD_GROUPS_INHIBIT_DEPS=0; + BUILD_TARGET=""; BUILD_USER=""; MIDIPIX_BUILD_PWD=""; # Global defaults DEFAULT_BUILD_CPUS=1; @@ -76,7 +76,7 @@ buildp_init_defaults() { buildp_init_env() { local _fname="" _rc=0; _status=""; - if ! cd "$(dirname "${0}")" || ! umask 022; then + if ! umask 022; then printf "Error: failed to setup environment.\n"; exit 1; else for _fname in $(find subr -name *.subr); do if ! . "${_fname}"; then @@ -97,7 +97,7 @@ buildp_init_files() { elif ! rtl_clean_env "${DEFAULT_CLEAR_ENV_VARS_EXCEPT}"; then _rc=1; _status="Error: failed to clean environment."; elif ! rtl_check_path_vars "${DEFAULT_CHECK_PATH_VARS}"; then - _rc=1; _status="Error: one or more variable containing pathname(s) contains whitespace character(s)."; + _rc=1; _status="${_status}"; else touch "${DEFAULT_BUILD_STATUS_IN_PROGRESS_FNAME}"; if [ -e "${DEFAULT_BUILD_LOG_FNAME}" ]; then @@ -126,6 +126,8 @@ buildp_init_getopts() { while [ "${#}" -gt 0 ]; do case "${1}" in --as-needed) ARG_AS_NEEDED=1; _shiftfl=1; ;; + --dump-on-abort) + ARG_DUMP_ON_ABORT=1; _shiftfl=1; ;; --debug-minipx) ARG_DEBUG_MINIPIX=1; _shiftfl=1; ;; -v*) _opt="${1#-}"; while [ -n "${_opt}" ]; do : $((ARG_VERBOSE+=1)); _opt="${_opt#?}"; diff --git a/subr/ex_pkg_exec.subr b/subr/ex_pkg_exec.subr index 9e4629b..f21bc3d 100644 --- a/subr/ex_pkg_exec.subr +++ b/subr/ex_pkg_exec.subr @@ -2,6 +2,21 @@ # set +o errexit -o noglob is assumed. # +exp_pkg_exec_filter_vars_fn() { + local _vname="${1}"; + case "${_vname}" in + DEFAULT|PKG_*) + return 0; ;; + BUILD_DLCACHEDIR|BUILD_WORKDIR|MIDIPIX_BUILD_PWD) + return 0; ;; + CONFIG_CACHE_GNULIB) + return 0; ;; + PREFIX|PREFIX_CROSS|PREFIX_MINGW32|PREFIX_MINIPIX|PREFIX_NATIVE|PREFIX_RPM) + return 0; ;; + *) return 1; ;; + esac; +}; + # # exp_pkg_exec_pre() - XXX # @_group_name: build group name @@ -102,6 +117,11 @@ ex_pkg_exec() { || [ "${_restart_at}" = "ALL" ]; then ex_pkg_state_set "${_pkg_name}" finish; 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; fi; return "${_rc}"; diff --git a/subr/pkgtool_init.subr b/subr/pkgtool_init.subr new file mode 100644 index 0000000..da6a664 --- /dev/null +++ b/subr/pkgtool_init.subr @@ -0,0 +1,133 @@ +# +# set +o errexit -o noglob is assumed. +# + +pkgtoolp_init_defaults() { + : ${ARCH:="nt64"}; : ${BUILD:="debug"}; : ${PKG_NAME:=""}; + : ${BUILD_WORKDIR:=""}; : ${PREFIX=""}; + ARG_RESTART_AT=""; ARG_UPDATE_DIFF=0; +}; + +pkgtoolp_init_env() { + local _fname="" _rc=0; _status=""; + if ! umask 022; then + printf "Error: failed to setup environment.\n"; exit 1; + else for _fname in $(find subr -name *.subr); do + if ! . "${_fname}"; then + printf "Error: failed to source \`%s'.\n" "${_fname}"; exit 1; + fi; + done; fi; + return "${_rc}"; +}; + +pkgtoolp_init_getopts() { + local _opt="" _shiftfl=0 _rc=0 OPTIND=0; _status=""; + while [ "${#}" -gt 0 ]; do + case "${1}" in + --update-diff) + ARG_UPDATE_DIFF=1; _shiftfl=1; ;; + --restart-at) + if [ "${#}" -lt 2 ]\ + || [ -z "${2}" ]; then + _rc=1; _status="Error: missing argument for option --restart-at."; + else + ARG_RESTART_AT="${2}"; _shiftfl=2; + fi; ;; + *) _shiftfl=0; ;; + esac; + if [ "${_rc:-0}" -ne 0 ]; then + break; + elif [ "${_shiftfl:-0}" -gt 0 ]; then + shift "${_shiftfl}"; continue; + elif getopts a:b:C:D:Fhp:Pr:R _opt; then + case "${_opt}" in + a) ARCH="${OPTARG}"; ;; + b) BUILD="${OPTARG}"; ;; + h) pkgtoolp_usage; exit 0; ;; + *) pkgtoolp_usage; exit 1; ;; + esac; shift $((${OPTIND}-1)); OPTIND=1; + else + break; + fi; + done; + if [ "${_rc}" -eq 0 ]; then + while [ "${#}" -gt 0 ]; do + case "${1}" in + *=*) rtl_set_var_unsafe "${1%%=*}" "${1#*=}"; ;; + *) if [ "${#}" -ne 1 ]; then + _rc=1; _status="Error: invalid argument \`${1}'."; + fi; break; ;; + esac; shift; done; + if [ "${_rc:-0}" -eq 0 ]; then + if [ "${#}" -ne 1 ]\ + && [ -z "${PKG_NAME}" ]; then + _rc=1; _status="Error: missing package name."; + elif [ "${#}" -eq 1 ]; then + PKG_NAME="${1}"; + fi; + fi; + fi; + return "${_rc}"; +}; + +pkgtoolp_init_prereqs() { + local _cmd="" _cmds_missing="" _rc=0; _status=""; + for _cmd in \ + awk bunzip2 cat chmod cmake cp date find flock g++ \ + gcc git grep gunzip gzip hostname install kill \ + ln lzip make mkdir mkfifo mv paste patch perl \ + pgrep pkill printf readlink rm sed seq sha256sum \ + sort stat tail tar test touch tr wget xz zip; do + if ! which "${_cmd}" >/dev/null 2>&1; then + _cmds_missing="${_cmds_missing:+${_cmds_missing} }${_cmd}"; + fi; + done; + if [ -n "${_cmds_missing}" ]; then + _rc=1; _status="Error: missing prerequisite package(s): ${_cmds_missing}"; + elif ! awk -V 2>/dev/null | grep -q "^GNU Awk "; then + _rc=1; _status="Error: awk(1) in \$PATH must be GNU Awk."; + elif ! sed --version 2>/dev/null | grep -q "^GNU sed "; then + _rc=1; _status="Error: sed(1) in \$PATH must be GNU sed."; + fi; + return "${_rc}"; +}; + +pkgtoolp_init_vars() { + local _rc=0; _status=""; + if ! rtl_lmatch "${ARCH}" "nt32 nt64"; then + _rc=1; _status="Error: invalid architecture \`${ARCH}'."; + elif ! rtl_lmatch "${BUILD}" "debug release"; then + _rc=1; _status="Error: unknown build type \`${BUILD}'."; + else case "${ARCH}" in + nt32) DEFAULT_TARGET="i686-nt32-midipix"; ;; + nt64) DEFAULT_TARGET="x86_64-nt64-midipix"; ;; + esac; + rtl_fileop source_opt \ + "${HOME}/midipix_build.vars" "${HOME}/.midipix_build.vars" \ + ../midipix_build.vars ./midipix.env; + if [ -z "${PREFIX}" ]; then + _rc=1; _status="Error: \${PREFIX} empty or unset."; + fi; fi; + return "${_rc}"; +}; + +pkgtoolp_usage() { + echo "usage: ./pkgtool.sh [-a nt32|nt64] [-b debug|release] name" >&2; +}; + +pkgtool_init() { + local _fname="" _rc=0 _status=""; + if ! pkgtoolp_init_env \ + || ! pkgtoolp_init_defaults \ + || ! pkgtoolp_init_getopts "${@}" \ + || ! pkgtoolp_init_prereqs \ + || ! pkgtoolp_init_vars; then + _rc="${?}"; rtl_log_msg fail "${_status}"; exit "${_rc}"; + elif [ -n "${_status}" ]; then + rtl_log_msg info "${_status}"; exit 0; + else + return "${_rc}"; + fi; +}; + +# vim:filetype=sh diff --git a/subr/rtl_complex.subr b/subr/rtl_complex.subr index e727e3c..41f0b2b 100644 --- a/subr/rtl_complex.subr +++ b/subr/rtl_complex.subr @@ -52,6 +52,41 @@ rtl_export_vars() { done; }; +rtl_filter_vars() { + local _fn="${1}" _fnfl=0 _qchar="" _var_spec="" _vars="" _vname="" IFS=" +"; for _var_spec in $(set); do + case "${_qchar}" in + "\"") if [ "${_var_spec%\"}" != "${_var_spec}" ]; then + _qchar=""; + fi; + if [ "${_fnfl:-0}" -eq 1 ]; then + _vars="$(rtl_lconcat "${_vars}" "${_var_spec}" "\n")"; + fi; + continue; ;; + "\'") if [ "${_var_spec%\'}" != "${_var_spec}" ]; then + _qchar=""; + fi; + if [ "${_fnfl:-0}" -eq 1 ]; then + _vars="$(rtl_lconcat "${_vars}" "${_var_spec}" "\n")"; + fi; + continue; ;; + *) case "${_var_spec}" in + [^=]*=\"*\") _qchar=""; _vname="${_var_spec%%=\"*}"; ;; + [^=]*=\"*) _qchar="\""; _vname="${_var_spec%%=\"*}"; ;; + [^=]*=\'*\') _qchar=""; _vname="${_var_spec%%=\'*}"; ;; + [^=]*=\'*) _qchar="\'"; _vname="${_var_spec%%=\'*}"; ;; + [^=]*=*) _qchar=""; _vname="${_var_spec%%=*}"; ;; + esac; ;; + esac; + if "${_fn}" "${_vname}"; then + _vars="$(rtl_lconcat "${_vars}" "${_var_spec}" "\n")"; _fnfl=1; + else + _fnfl=0; + fi; + done; + echo "${_vars}"; +}; + rtl_get_var_unsafe() { local _vname=""; if [ "x${1}" = "x-u" ]; then diff --git a/subr/rtl_string.subr b/subr/rtl_string.subr index 0e549d3..2d52978 100644 --- a/subr/rtl_string.subr +++ b/subr/rtl_string.subr @@ -12,6 +12,17 @@ rtl_isnumber() { return "${_rc}"; }; +rtl_subst() { + local _s="${1}" _find="${2}" _replace="${3}" _prefix="" _s_new=""; + while [ -n "${_s}" ]; do + case "${_s}" in + *${_find}*) _prefix="${_s%%${_find}*}"; _s="${_s#*${_find}}"; + _s_new="${_s_new:+${_s_new}}${_prefix}${_replace}"; ;; + *) _s_new="${_s_new:+${_s_new}}${_s}"; _s=""; ;; + esac; done; + echo "${_s_new}"; +}; + rtl_tolower() { local _s="${1}" _s_new=""; while [ -n "${_s}" ]; do