Add a lot of new functions to lib/ossbuild-common.bash
This commit is contained in:
parent
e7e9990871
commit
664827d55a
531
lib/ossbuild-common.bash
Normal file → Executable file
531
lib/ossbuild-common.bash
Normal file → Executable file
@ -1,6 +1,535 @@
|
||||
# Helper functions for project build scripts.
|
||||
|
||||
# Check is current system is running GNU/Linux based QNAP QTS OS.
|
||||
[ -d "${BSL_PATH:=${HOME}/.local/lib/bash/bsl}" ] || {
|
||||
echo "[ERR] please set BSL_PATH" >&2
|
||||
exit 1
|
||||
}
|
||||
source "${BSL_PATH}/init.bash"
|
||||
bsl_load
|
||||
|
||||
unset QUIET OSSBUILD_PROJECT
|
||||
|
||||
# fail on errors when non-interactive
|
||||
[ -n "${PS1:-}" ] || set -euo pipefail
|
||||
|
||||
#D# Check is current system is running GNU/Linux based QNAP QTS OS.
|
||||
is-qnap-qts() {
|
||||
[ -r '/etc/os-release' ] && grep -q '^NAME="QTS"$' '/etc/os-release'
|
||||
}
|
||||
|
||||
#D# Check if variable DRY_RUN has a value greater than ``0``.
|
||||
is-dry-run() {
|
||||
! [ ${DRY_RUN:-0} -eq 0 ]
|
||||
}
|
||||
|
||||
#D# Wrapper around pushd.
|
||||
#
|
||||
# The wrapper provides the following features:
|
||||
#
|
||||
# - return ``1`` if the provided directory does not exist
|
||||
# - log directory changes
|
||||
ossbuild-pushd() {
|
||||
local d="${1}"
|
||||
bsl_run_cmd_quiet pushd "${d}" || {
|
||||
[ -d "${d}" ] || {
|
||||
bsl_logfe "no such dir: '$(realpath -Lm "${d}")'"
|
||||
return 1
|
||||
}
|
||||
bsl_logfe "failed to change directory to '$(realpath -Lm "${d}")'"
|
||||
return 2
|
||||
}
|
||||
bsl_logi "directory: '${PWD}'"
|
||||
}
|
||||
|
||||
#D# Logged popd.
|
||||
ossbuild-popd() {
|
||||
bsl_run_cmd_quiet popd || return 0
|
||||
bsl_logi "directory: '${PWD}'"
|
||||
}
|
||||
|
||||
#D# Run a shell command.
|
||||
#
|
||||
# This wrapper provides to following features:
|
||||
#
|
||||
# - write executed command to stdout (set QUIET=1 to disable the logging)
|
||||
# - skip the command if func:is-dry-run returns a truthy value
|
||||
ossbuild-cmd() {
|
||||
local cmd=("${@}")
|
||||
if is-dry-run; then
|
||||
echo "[DRYRUN] ${cmd[@]}" >&2
|
||||
else
|
||||
[ -n "${QUIET:-}" ] || echo "${cmd[@]}" >&2
|
||||
"${cmd[@]}"
|
||||
fi
|
||||
}
|
||||
|
||||
#D# Writes name of project specific variable to stdout.
|
||||
ossbuild-project-var() {
|
||||
local name="${OSSBUILD_PROJECT^^}_${1^^}"
|
||||
printf '%s' "${name//-/_}"
|
||||
}
|
||||
|
||||
#D# Write value of project specific variable to stdout.
|
||||
#
|
||||
# Args:
|
||||
# name (str): the name of the project specific variable
|
||||
# default (any): default value to be used if variable does not exist
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0`` in case of sucecess, ``1`` in case that the
|
||||
# variable does not exist and no default value was provided
|
||||
#
|
||||
# stdout (str): value of the variable
|
||||
ossbuild-project-var-get() {
|
||||
#echo "1/ossbuild-project-var-get: ${@}" >&2
|
||||
local quiet=0 name vname
|
||||
local -a positional
|
||||
while [ ${#} -gt 0 ]; do
|
||||
case "${1}" in
|
||||
-q | --quiet)
|
||||
((++quiet))
|
||||
;;
|
||||
-v)
|
||||
local outvar="${2}"
|
||||
shift
|
||||
;;
|
||||
-*)
|
||||
# ignore unknown option
|
||||
;;
|
||||
*)
|
||||
positional+=("${1}")
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
||||
|
||||
[ "${#positional[*]}" -gt 0 ] || {
|
||||
bsl_logfe "missing project variable name"
|
||||
return 10
|
||||
}
|
||||
name="${positional[0]}"
|
||||
|
||||
unset default
|
||||
[ "${#positional[*]}" -le 1 ] || local default="${positional[1]}"
|
||||
|
||||
vname="$(ossbuild-project-var "${name}")"
|
||||
#echo "2/ossbuild-project-var-get: ${vname}${default:+, default=${default}}" >&2
|
||||
[[ -v "${vname}" ]] || {
|
||||
if [ -v default ]; then
|
||||
#echo "using default: '${vname}=${default}'" >&2
|
||||
local "${vname}=${default}"
|
||||
else
|
||||
[ "${quiet}" -gt 0 ] || bsl_loge "project variable not set: '${vname}'"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
#echo "R/ossbuild-project-var-get: ${vname}='${!vname}'" >&2
|
||||
if [ -v outvar ]; then
|
||||
local -n ovar_ref="${outvar}"
|
||||
# shellcheck disable=SC2034
|
||||
printf -v ovar_ref '%s' "${!vname}"
|
||||
else
|
||||
printf '%s' "${!vname}"
|
||||
fi
|
||||
}
|
||||
|
||||
#D# Set value of project specific variable.
|
||||
#
|
||||
# Args:
|
||||
# name (str): the name of the project specific variable
|
||||
# value (any): value to be assigned to the variable
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0`` (the function should never fail)
|
||||
#
|
||||
# stdout (str): na
|
||||
ossbuild-project-var-set() {
|
||||
local name="${1}" value="${2}" vname
|
||||
vname="$(ossbuild-project-var "${name}")"
|
||||
bsl_logi "set project variable: ${vname}='${value}'"
|
||||
declare -g "${vname}=${value}"
|
||||
}
|
||||
|
||||
#D# Unset (delete) project specific variable.
|
||||
#
|
||||
# Args:
|
||||
# name (str): the name of the project specific variable
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0`` (the function should never fail)
|
||||
#
|
||||
# stdout (str): na
|
||||
ossbuild-project-var-unset() {
|
||||
local name="${1}" vname
|
||||
vname="$(ossbuild-project-var "${name}")"
|
||||
bsl_logi "unset project variable: ${vname}"
|
||||
unset "${vname}"
|
||||
}
|
||||
|
||||
#D# Run a git command (see func:ossbuild-cmd).
|
||||
ossbuild-git() {
|
||||
ossbuild-cmd git "${@}"
|
||||
}
|
||||
|
||||
#D# Write latest tagged version of a github project to stdout.
|
||||
ossbuild-gh-version-latest() {
|
||||
local owner="${1:-$(ossbuild-project-var-get GH_OWNER '')}" \
|
||||
repo="${2:-$(ossbuild-project-var-get GH_REPO '')}"
|
||||
|
||||
[[ -n "${owner}" && -n "${repo}" ]] || return 1
|
||||
printf '%s' "$(bsl_rtrim -s 'v' "$(bsl_ghapi_releases_tag_latest "${owner}" "${repo}")")"
|
||||
}
|
||||
|
||||
# #D# WiP: Write download URL of ...
|
||||
# ossbuild-gh-download-url() {
|
||||
# local owner="${1:-$(ossbuild-project-var-get GH_OWNER '')}" \
|
||||
# repo="${2:-$(ossbuild-project-var-get GH_REPO '')}"
|
||||
#
|
||||
# [[ -n "${owner}" && -n "${repo}" ]] || return 1
|
||||
# #https://github.com/${owner}/${repo}/releases/download/v23.3/protobuf-23.3.tar.gz
|
||||
# }
|
||||
|
||||
#D# Write the version string of OSSBUILD_PROJECT to stdout.
|
||||
#
|
||||
# The first of the following steps which has a non-empty result is used as
|
||||
# version string:
|
||||
#
|
||||
# 1. get value of project variable VERSION
|
||||
# 2. get value of project variable DEFAULT_VERSION
|
||||
# 3. value returned by ``ossbuild-gh-version-latest`` #d#
|
||||
# shellcheck disable=SC2120
|
||||
ossbuild-project-version() {
|
||||
local version
|
||||
version="$(ossbuild-project-var-get -q VERSION)" || {
|
||||
version="$(ossbuild-project-var-get -q DEFAULT_VERSION)" || {
|
||||
local owner="${1:-$(ossbuild-project-var-get GH_OWNER '')}" \
|
||||
repo="${2:-$(ossbuild-project-var-get GH_REPO '')}"
|
||||
version="$(bsl_ltrim -s 'v' "$(ossbuild-gh-version-latest "${owner}" "${repo}")")" || return 10
|
||||
}
|
||||
}
|
||||
|
||||
printf '%s' "${version}"
|
||||
}
|
||||
|
||||
#D# Initialize a project hosted on github.com.
|
||||
ossbuild-project-gh-init() {
|
||||
local owner="${1}" repo="${2}" name="${3:-}"
|
||||
|
||||
declare -g OSSBUILD_PROJECT="${name}"
|
||||
[ -n "${OSSBUILD_PROJECT}" ] || OSSBUILD_PROJECT="${repo}"
|
||||
bsl_logi "initialize github project: ${OSSBUILD_PROJECT} (${owner}/${repo})"
|
||||
|
||||
ossbuild-project-var-set GH_OWNER "${owner}"
|
||||
ossbuild-project-var-set GH_REPO "${repo}"
|
||||
ossbuild-project-var-set GH_URL "https://github.com/${owner}/${repo}"
|
||||
# shellcheck disable=SC2119
|
||||
ossbuild-project-var-set VERSION "$(ossbuild-project-version)"
|
||||
}
|
||||
|
||||
#D# Write value of source base path (default: ``${HOME}/work/oss``) to stdout.
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0``
|
||||
#
|
||||
# stdout (str): value of OSSBUILD_SRC_BASE_PATH
|
||||
ossbuild-src-base() {
|
||||
printf '%s' "${OSSBUILD_SRC_BASE_PATH:-${HOME}/work/oss}"
|
||||
}
|
||||
|
||||
#D# Create OSSBUILD_SRC_BASE_PATH if it does not exist.
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0``
|
||||
#
|
||||
# stdout (str): na
|
||||
ossbuild-src-base-create() {
|
||||
local src_base
|
||||
src_base="$(ossbuild-src-base)"
|
||||
[ -d "${src_base}" ] || ossbuild-cmd mkdir "${src_base}"
|
||||
}
|
||||
|
||||
#D# Write versioned project name to stdout.
|
||||
#
|
||||
# Args:
|
||||
# version (str): [optional] project version
|
||||
# name (any): [optional] project name
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0``
|
||||
#
|
||||
# stdout (str): project name inclusing version string
|
||||
ossbuild-project-namever-gnu() {
|
||||
# shellcheck disable=SC2119
|
||||
local version="${1:-$(ossbuild-project-version)}" name="${2:-${OSSBUILD_PROJECT}}"
|
||||
printf '%s' "${name}${version:+-${version}}"
|
||||
}
|
||||
|
||||
#D# Write project specific archive file name to stdout.
|
||||
#
|
||||
# Args:
|
||||
# version (str): [optional] project version
|
||||
# name (any): [optional] project name
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0``
|
||||
#
|
||||
# stdout (str): archive file name
|
||||
ossbuild-project-archive-gnu() {
|
||||
# shellcheck disable=SC2119
|
||||
local version="${1:-$(ossbuild-project-version)}" name="${2:-${OSSBUILD_PROJECT}}"
|
||||
printf '%s' "$(ossbuild-project-namever-gnu "${@}").tar.gz"
|
||||
}
|
||||
|
||||
#D# ...
|
||||
ossbuild-project-src-path() {
|
||||
local name="${1}"
|
||||
printf '%s' "$(ossbuild-src-base)/${name}"
|
||||
}
|
||||
|
||||
#D# Download a file.
|
||||
ossbuild-dl() {
|
||||
local url="${1}" file_or_dir="${2:-$(basename "${1}")}"
|
||||
|
||||
local dst
|
||||
if [ -d "${file_or_dir}" ]; then
|
||||
dst="${file_or_dir}/$(basename "${url}")"
|
||||
elif bsl_path_relative_p "${file_or_dir}"; then
|
||||
dst="$(ossbuild-project-src-path "${file_or_dir}")"
|
||||
else
|
||||
dst="${file_or_dir}"
|
||||
fi
|
||||
|
||||
[ -e "${dst}" ] || ossbuild-cmd curl -qLs --fail -o "${dst}" "${url}"
|
||||
[ -n "${QUIET:-}" ] || printf '%s' "${dst}"
|
||||
}
|
||||
|
||||
#D# Download a TAR archive to OSSBUILD_SRC_BASE_PATH and unpack it.
|
||||
ossbuild-src-tar() {
|
||||
local url="${1}" file_or_dir="${2:-$(basename "${1}")}"
|
||||
|
||||
local archive
|
||||
archive="$(ossbuild-dl "${url}" "${file_or_dir}")"
|
||||
bsl_logd "archive:'${archive}'"
|
||||
ossbuild-cmd tar -xf "${archive}" -C "$(dirname "${archive}")"
|
||||
}
|
||||
|
||||
#D# ...
|
||||
ossbuild-src-git() {
|
||||
local url="${1}" prj_name="${2:-$(basename "${1}" .git)}"
|
||||
|
||||
local src_tree
|
||||
src_tre="$(ossbuild-project-src-path "${prj_name}")"
|
||||
ossbuild-git clone "${url}" "${src_tree}"
|
||||
}
|
||||
|
||||
#D# Check if PATH is writable.
|
||||
#
|
||||
# Args:
|
||||
# path (str): path to be checked
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0`` if PATH is writable, ``1`` otherwise
|
||||
#
|
||||
# stdout (str): na
|
||||
ossbuild-writable-p() {
|
||||
local tgt="${1}"
|
||||
if [ -e "${tgt}" ]; then
|
||||
test -w "${tgt}"
|
||||
else
|
||||
test -w "$(dirname "${p}")"
|
||||
fi
|
||||
}
|
||||
|
||||
#D# Install a file (automatically uses ``sudo`` if required).
|
||||
ossbuild-install() {
|
||||
local src="${1}" dst="${2}"
|
||||
|
||||
local cmd=('install')
|
||||
ossbuild-writable-p "${dst}" || cmd=(sudo "${cmd}")
|
||||
ossbuild-cmd "${cmd[@]}" "${src}" "${dst}"
|
||||
}
|
||||
|
||||
#D# Create a symlink (automatically uses ``sudo`` if required).
|
||||
ossbuild-symlink() {
|
||||
local src="${1}" dst="${2}"
|
||||
|
||||
local cmd=('ln' '-s' '-fr')
|
||||
ossbuild-writable-p "${dst}" || cmd=(sudo "${cmd}")
|
||||
ossbuild-cmd "${cmd[@]}" "${src}" "${dst}"
|
||||
}
|
||||
|
||||
#D# Check if tests are enabled.
|
||||
#
|
||||
# Evaluates global and project specific BUILD_TESTS variable. Tests are enabled
|
||||
# if:
|
||||
#
|
||||
# - the project specific value of BUILD_TESTS > 0 or
|
||||
# - the global value of BUILD_TESTS > 0 and the project specific value is
|
||||
# not explicitly set to ``0``.
|
||||
#
|
||||
# Returns:
|
||||
# exit status (int): ``0`` if tests should run, ``1`` otherwise
|
||||
#
|
||||
# stdout (str): na
|
||||
ossbuild-run-tests-p() {
|
||||
[ "$(ossbuild-project-var-get BUILD_TESTS "${BUILD_TESTS:-0}")" -gt 0 ]
|
||||
}
|
||||
|
||||
#D# Write name of project build step function to stdoutif (it exists).
|
||||
ossbuild-project-build-step-fn() {
|
||||
local step_fn="ossbuild-${OSSBUILD_PROJECT}-${1}"
|
||||
bsl_run_cmd_nostdout declare -F "${step_fn}" || return 1
|
||||
printf '%s' "${step_fn}"
|
||||
}
|
||||
|
||||
#D# Run project build step function (if it exists).
|
||||
ossbuild-project-build-step-run() {
|
||||
local step_fn
|
||||
step_fn="$(ossbuild-project-build-step-fn "${@}")" || return 1
|
||||
shift
|
||||
bsl_logi "${OSSBUILD_STEP} '${OSSBUILD_PROJECT}'"
|
||||
"${step_fn}" "${@}"
|
||||
}
|
||||
|
||||
#D# Function to be called in case of errors during a project build.
|
||||
ossbuild-report-error() {
|
||||
bsl_loge "failed"
|
||||
bsl_loge "${OSSBUILD_PROJECT}: failed to ${OSSBUILD_STEP}"
|
||||
}
|
||||
|
||||
#D# Initialize a project.
|
||||
ossbuild-project-init() {
|
||||
trap ossbuild-report-error ERR
|
||||
|
||||
[ -v OSSBUILD_PROJECT ] || {
|
||||
declare -g OSSBUILD_STEP='init'
|
||||
OSSBUILD_PROJECT="$(basename "$(dirname "${BASH_SOURCE[-1]}")")"
|
||||
}
|
||||
|
||||
ossbuild-src-base-create
|
||||
|
||||
[ -v PREFIX ] || {
|
||||
declare -g PREFIX
|
||||
if is-qnap-qts; then
|
||||
PREFIX='/opt/local'
|
||||
else
|
||||
PREFIX='/usr/local'
|
||||
fi
|
||||
}
|
||||
|
||||
local version
|
||||
ossbuild-project-var-get -q -v version VERSION || {
|
||||
# shellcheck disable=SC2119
|
||||
version="$(ossbuild-project-version)"
|
||||
ossbuild-project-var-set VERSION "${version}"
|
||||
}
|
||||
}
|
||||
|
||||
#D# Check if project is configured to build in the source tree.
|
||||
ossbuild-project-build-in-tree-p() {
|
||||
[ "$(ossbuild-project-var-get SRC_TREE)" \
|
||||
= "${ossbuild-project-var-get BUILD_TREE}" ]
|
||||
}
|
||||
|
||||
ossbuild-archive-generic-prepare() {
|
||||
local archive_url="${1}" src_tree="${2:-}" archive="${3:-}"
|
||||
|
||||
[ -n "${src_tree}" ] || \
|
||||
src_tree="$(ossbuild-src-base)/$(ossbuild-project-namever-gnu)"
|
||||
[ -n "${archive}" ] || archive="${src_tree}.tar.gz"
|
||||
|
||||
ossbuild-project-var-set ARCHIVE "${archive}"
|
||||
ossbuild-project-var-set ARCHIVE_URL "${archive_url}"
|
||||
ossbuild-project-var-set SRC_TREE "${src_tree}"
|
||||
|
||||
[ -e "${src_tree}" ] || ossbuild-src-tar "${archive_url}"
|
||||
|
||||
[ -d "${src_tree}" ] || {
|
||||
bsl_loge "failed to create '${src_tree}'"
|
||||
ossbuild-project-var-unset SRC_TREE
|
||||
return 2
|
||||
}
|
||||
}
|
||||
|
||||
ossbuild-archive-gnu-prepare() {
|
||||
local archive_base_url="${1}"
|
||||
local src_tree archive archive_url
|
||||
# shellcheck disable=SC2119
|
||||
archive="$(ossbuild-project-archive-gnu)"
|
||||
src_tree="$(ossbuild-src-base)/$(basename "${archive}" .tar.gz)"
|
||||
archive_url="${archive_base_url}/${archive}"
|
||||
|
||||
ossbuild-archive-generic-prepare \
|
||||
"${archive_url}" \
|
||||
"${src_tree}" \
|
||||
"${archive}"
|
||||
}
|
||||
|
||||
#D# ...
|
||||
ossbuild-autotools-configure-ok-p() {
|
||||
local build_tree="${1}"
|
||||
[ -n "${build_tree}" ] || ossbuild-project-var-get -v build_tree BUILD_TREE
|
||||
local config_log="${build_tree}/config.log"
|
||||
|
||||
[ -e "${config_log}" ] && grep -qE '^configure: exit 0$' "${config_log}"
|
||||
}
|
||||
|
||||
#D# ...
|
||||
ossbuild-autotools-generic-build() {
|
||||
local configure_extra_opts=(${@})
|
||||
|
||||
local src_tree build_tree
|
||||
ossbuild-project-var-get -v src_tree SRC_TREE
|
||||
ossbuild-project-var-get -q -v build_tree BUILD_TREE || {
|
||||
build_tree="${src_tree}/ossbuild"
|
||||
ossbuild-project-var-set BUILD_TREE "${build_tree}"
|
||||
}
|
||||
|
||||
[ -d "${build_tree}" ] || mkdir -p "${build_tree}"
|
||||
ossbuild-pushd "${build_tree}"
|
||||
|
||||
if ossbuild-autotools-configure-ok-p "${build_tree}"; then
|
||||
bsl_logi "skip configure (found config.status)"
|
||||
else
|
||||
bsl_logi "run configure ..."
|
||||
local configure=(
|
||||
"${src_tree}/configure"
|
||||
--prefix="${PREFIX}"
|
||||
"${configure_extra_opts[@]}"
|
||||
)
|
||||
ossbuild-cmd "${configure[@]}"
|
||||
fi
|
||||
ossbuild-cmd make
|
||||
|
||||
ossbuild-popd
|
||||
}
|
||||
|
||||
#D# ...
|
||||
ossbuild-autotools-generic-install() {
|
||||
local build_tree
|
||||
ossbuild-project-var-get -v build_tree BUILD_tree
|
||||
|
||||
ossbuild-pushd "${build_tree}"
|
||||
|
||||
ossbuild-cmd sudo make install
|
||||
|
||||
ossbuild-popd
|
||||
}
|
||||
|
||||
#D# Run all known project build steps.
|
||||
ossbuild-project-build-steps-all() {
|
||||
ossbuild-project-init
|
||||
|
||||
local msg=(
|
||||
"building project: '${OSSBUILD_PROJECT}'"
|
||||
)
|
||||
local version
|
||||
ossbuild-project-var-get -v version VERSION
|
||||
[ -z "${version}" ] || msg+=("(${version})")
|
||||
bsl_logi "${msg[@]}"
|
||||
|
||||
declare -g OSSBUILD_STEP
|
||||
for OSSBUILD_STEP in prepare build install; do
|
||||
ossbuild-project-build-step-run "${OSSBUILD_STEP}" "${@}"
|
||||
done
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user