aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xgen_compile.sh183
-rwxr-xr-xgen_determineargs.sh11
-rwxr-xr-xgen_funcs.sh217
-rwxr-xr-xgen_worker.sh3
-rw-r--r--worker_modules/gkbuild.sh705
5 files changed, 1119 insertions, 0 deletions
diff --git a/gen_compile.sh b/gen_compile.sh
index 90f5a429..25a5871a 100755
--- a/gen_compile.sh
+++ b/gen_compile.sh
@@ -1048,3 +1048,186 @@ compile_gpg() {
return 0
fi
}
+
+populate_binpkg() {
+ [[ ${#} -gt 2 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at most two arguments (${#} given)!"
+
+ [[ ${#} -lt 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at least one argument (${#} given)!"
+
+ local PN=${1}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ local PV=$(get_gkpkg_version "${PN}")
+ local P=${PN}-${PV}
+
+ local BINPKG=$(get_gkpkg_binpkg "${PN}")
+
+ local -a GKBUILD_CANDIDATES=( "${GK_SHARE}"/gkbuilds/${P}.gkbuild )
+ GKBUILD_CANDIDATES+=( "${GK_SHARE}"/gkbuilds/${PN}.gkbuild )
+
+ if [[ ${#} -eq 1 ]]
+ then
+ local CHECK_LEVEL_CURRENT=0
+ local CHECK_LEVEL_PARENT=0
+ local CHECK_LEVEL_NEXT=${CHECK_LEVEL_CURRENT}
+ else
+ local CHECK_LEVEL_PARENT=${2}
+ local CHECK_LEVEL_CURRENT=$[${CHECK_LEVEL_PARENT}+1]
+ local CHECK_LEVEL_NEXT=${CHECK_LEVEL_CURRENT}
+ fi
+
+ local REQUIRED_BINPKGS_PARENT_VARNAME="CHECK_L${CHECK_LEVEL_PARENT}_REQUIRED_BINPKGS"
+ local REQUIRED_BINPKGS_CURRENT_VARNAME="CHECK_L${CHECK_LEVEL_CURRENT}_REQUIRED_BINPKGS"
+ local REQUIRED_BINPKGS_CURRENT_VARNAME_SEPARATE_WORD="${REQUIRED_BINPKGS_CURRENT_VARNAME}[@]"
+ local REQUIRED_BINPKGS_CURRENT_VARNAME_SINGLE_WORD="${REQUIRED_BINPKGS_CURRENT_VARNAME}[*]"
+
+ # Make sure we start with an empty array just in case ...
+ eval declare -ga ${REQUIRED_BINPKGS_CURRENT_VARNAME}=\(\)
+
+ local CHECK_LEVEL_PREFIX=
+ local i=0
+ while [[ ${i} < ${CHECK_LEVEL_CURRENT} ]]
+ do
+ CHECK_LEVEL_PREFIX="${CHECK_LEVEL_PREFIX% }> "
+ i=$[${i}+1]
+ done
+ unset i
+
+ local -a pkg_deps=( $(get_gkpkg_deps "${PN}") )
+ if [[ ${#pkg_deps[@]} -gt 0 ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}Checking for binpkg(s) required for ${P} (L${CHECK_LEVEL_CURRENT}) ..."
+
+ local pkg_dep=
+ for pkg_dep in "${pkg_deps[@]}"
+ do
+ populate_binpkg ${pkg_dep} ${CHECK_LEVEL_NEXT}
+ done
+ unset pkg_dep
+ else
+ print_info 3 "${CHECK_LEVEL_PREFIX}${P} has no dependencies. (L${CHECK_LEVEL_CURRENT})"
+ fi
+ unset pkg_deps
+
+ if [[ "${PN}" == 'busybox' ]]
+ then
+ determine_busybox_config_file
+
+ # Apply config-based tweaks to the busybox config.
+ # This needs to be done before cache validation.
+ cp "${BUSYBOX_CONFIG}" "${TEMP}/busybox-config" \
+ || gen_die "Failed to copy '${BUSYBOX_CONFIG}' to '${TEMP}/busybox-config'!"
+
+ # If you want mount.nfs to work on older than 2.6.something, you might need to turn this on.
+ #isTrue "${NFS}" && nfs_opt='y'
+ local nfs_opt='n'
+ kconfig_set_opt "${TEMP}/busybox-config" CONFIG_FEATURE_MOUNT_NFS ${nfs_opt}
+
+ # Delete cache if stored config's MD5 does not match one to be used
+ # This exactly just the .config.gk_orig file, and compares it again the
+ # current .config.
+ if [[ -f "${BINPKG}" ]]
+ then
+ local oldconfig_md5="$(tar -xaf "${BINPKG}" -O ./configs/.config.gk_orig 2>/dev/null | md5sum)"
+ local newconfig_md5="$(md5sum < "${TEMP}"/busybox-config)"
+ if [[ "${oldconfig_md5}" != "${newconfig_md5}" ]]
+ then
+ print_info 3 "$(get_indent 2)${PN}: >> Busybox config has changed since binpkg was created; Removing stale ${P} binpkg ..."
+ rm "${BINPKG}" \
+ || gen_die "Failed to remove stale binpkg '${BINPKG}'!"
+ fi
+ fi
+ fi
+
+ if [[ -f "${BINPKG}" ]]
+ then
+ local GKBUILD=
+ for GKBUILD in "${GKBUILD_CANDIDATES[@]}"
+ do
+ if [[ ! -f "${GKBUILD}" ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}GKBUILD '${GKBUILD}' does NOT exist; Skipping ..."
+ continue
+ fi
+
+ if [[ "${BINPKG}" -ot "${GKBUILD}" ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}GKBUILD '${GKBUILD}' is newer than us; Removing stale ${P} binpkg ..."
+ rm "${BINPKG}" || gen_die "Failed to remove stale binpkg '${BINPKG}'!"
+ break
+ fi
+
+ print_info 3 "${CHECK_LEVEL_PREFIX}Existing ${P} binpkg is newer than '${GKBUILD}'; Skipping ..."
+ done
+ fi
+
+ if [[ -f "${BINPKG}" ]]
+ then
+ local required_binpkg=
+ for required_binpkg in "${!REQUIRED_BINPKGS_CURRENT_VARNAME_SEPARATE_WORD}"
+ do
+ # Create shorter variable value so we do not clutter output
+ local required_binpkg_filename=$(basename "${required_binpkg}")
+
+ if [[ "${BINPKG}" -ot "${required_binpkg}" ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}Required binpkg '${required_binpkg_filename}' is newer than us; Removing stale ${P} binpkg ..."
+ rm "${BINPKG}" || gen_die "Failed to remove stale binpkg '${BINPKG}'!"
+ break
+ fi
+
+ print_info 3 "${CHECK_LEVEL_PREFIX}Existing ${P} binpkg is newer than '${required_binpkg_filename}'; Skipping ..."
+ done
+ unset required_binpkg REQUIRED_BINPKGS_CURRENT_VARNAME_SEPARATE_WORD required_binpkg_filename
+ fi
+
+ if [[ -f "${BINPKG}" ]]
+ then
+ local patchdir="${GK_SHARE}/patches/${PN}/${PV}"
+ local patch
+ for patch in "${patchdir}"/*{diff,patch}
+ do
+ [ -f "${patch}" ] || continue
+ if [[ "${BINPKG}" -ot "${patch}" ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}Patch '${patch}' is newer than us; Removing stale ${P} binpkg ..."
+ rm "${BINPKG}" || gen_die "Failed to remove stale binpkg '${BINPKG}'!"
+ break
+ fi
+
+ print_info 3 "${CHECK_LEVEL_PREFIX}Existing ${P} binpkg is newer than '${patch}'; Skipping ..."
+ done
+ unset patch patchdir
+ fi
+
+ if [[ ! -f "${BINPKG}" ]]
+ then
+ print_info 3 "${CHECK_LEVEL_PREFIX}Binpkg '${BINPKG}' does NOT exist; Need to build ${P} ..."
+ gkbuild \
+ ${PN} \
+ ${PV} \
+ $(get_gkpkg_srcdir "${PN}") \
+ $(get_gkpkg_srctar "${PN}") \
+ "${BINPKG}" \
+ "${!REQUIRED_BINPKGS_CURRENT_VARNAME_SINGLE_WORD}"
+ else
+ print_info 3 "${CHECK_LEVEL_PREFIX}Can keep using existing ${P} binpkg from '${BINPKG}'!"
+ [[ ${CHECK_LEVEL_CURRENT} -eq 0 ]] && print_info 2 "$(get_indent 2)${PN}: >> Using ${P} binpkg ..."
+ fi
+
+ if [[ ${CHECK_LEVEL_CURRENT} -eq 0 ]]
+ then
+ # Fertig
+ # REQUIRED_BINPKGS_PARENT_VARNAME
+ unset CHECK_L${CHECK_LEVEL_PARENT}_REQUIRED_BINPKGS
+ else
+ print_info 3 "${CHECK_LEVEL_PREFIX}Binpkg of ${P} is ready; Adding to list '${REQUIRED_BINPKGS_PARENT_VARNAME}' ..."
+ eval ${REQUIRED_BINPKGS_PARENT_VARNAME}+=\( "${BINPKG}" \)
+ fi
+
+ # REQUIRED_BINPKGS_CURRENT_VARNAME
+ unset CHECK_L${CHECK_LEVEL_CURRENT}_REQUIRED_BINPKGS
+}
diff --git a/gen_determineargs.sh b/gen_determineargs.sh
index 187cd66d..9851fae2 100755
--- a/gen_determineargs.sh
+++ b/gen_determineargs.sh
@@ -295,6 +295,17 @@ determine_real_args() {
eval "$v='$(cache_replace "${!v}")'"
done
+ declare -gA GKPKG_LOOKUP_TABLE=
+ local pn_varname= pn=
+ for v in "${pkg_prefixes[@]}"
+ do
+ pn_varname="${v}_PN"
+ pn=${!pn_varname}
+
+ GKPKG_LOOKUP_TABLE[${pn}]=${v}
+ done
+ unset v pn pn_varname pkg_prefixes
+
if [ -n "${CMD_BOOTLOADER}" ]
then
BOOTLOADER="${CMD_BOOTLOADER}"
diff --git a/gen_funcs.sh b/gen_funcs.sh
index eddaf8ed..b2d24758 100755
--- a/gen_funcs.sh
+++ b/gen_funcs.sh
@@ -566,6 +566,88 @@ get_chost_libdir() {
echo "${libdir}"
}
+_get_gkpkg_var_value() {
+ [[ ${#} -ne 2 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly two arguments (${#} given)!"
+
+ local VARNAME=${1}
+ case "${VARNAME}" in
+ BINPKG|DEPS|PN|PV|SRCDIR|SRCTAR)
+ ;;
+ *)
+ # Let's make variable support explicit
+ gen_die "$(get_useful_function_stack)Variable '${VARNAME}' is not supported by ${FUNCNAME}()!"
+ ;;
+ esac
+
+ local PN=${2}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ [[ -z "${GKPKG_LOOKUP_TABLE[${PN}]}" ]] \
+ && gen_die "$(get_useful_function_stack)Internal error: Package '${PN}' is unknown! Was package added to software.sh?"
+
+ local REQUESTED_VARNAME="${GKPKG_LOOKUP_TABLE[${PN}]}_${VARNAME}"
+ local REQUESTED_VALUE="${!REQUESTED_VARNAME}"
+ [[ ${VARNAME} != 'DEPS' && -z "${REQUESTED_VALUE}" ]] \
+ && gen_die "$(get_useful_function_stack)Internal error: Variable '${REQUESTED_VARNAME}' is not set!"
+
+ echo "${REQUESTED_VALUE}"
+}
+
+get_gkpkg_binpkg() {
+ [[ ${#} -ne 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!"
+
+ local PN=${1}
+
+ _get_gkpkg_var_value BINPKG ${PN}
+}
+
+get_gkpkg_deps() {
+ [[ ${#} -ne 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!"
+
+ local PN=${1}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ _get_gkpkg_var_value DEPS ${PN}
+}
+
+get_gkpkg_srcdir() {
+ [[ ${#} -ne 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!"
+
+ local PN=${1}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ _get_gkpkg_var_value SRCDIR ${PN}
+}
+
+get_gkpkg_srctar() {
+ [[ ${#} -ne 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!"
+
+ local PN=${1}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ _get_gkpkg_var_value SRCTAR ${PN}
+}
+
+get_gkpkg_version() {
+ [[ ${#} -ne 1 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes exactly one argument (${#} given)!"
+
+ local PN=${1}
+ [[ -z "${PN}" ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): No package specified!"
+
+ _get_gkpkg_var_value PV ${PN}
+}
+
# @FUNCTION: get_tar_cmd
# @USAGE: <ARCHIVE>
# @DESCRIPTION:
@@ -825,6 +907,141 @@ trap_cleanup() {
exit 1
}
+# @FUNCTION: gkbuild
+# @USAGE: <PKG> <PKG_VERSION> <PKG_SRCDIR> <PKG_SRCTAR> <PKG_BINCACHE> [<PKG_DEPS>]
+# @DESCRIPTION:
+# Builds a package for genkernel's initramfs, with cross-compile support.
+#
+# Genkernel's initramfs uses various utilities like Busybox, LVM,
+# MDADM, cryptsetup or others. gkbuild() will run an ebuild-like script
+# to build such utilities in sandbox environment with cross-compile
+# support (requires existing cross-compile toolchain!).
+#
+# For developers:
+# Any package you want to build using gkbuild() must be correctly added to
+# ${GK_SHARE}/software.sh file, check_distfiles() and determine_real_args()
+# function.
+#
+# For users:
+# Any package you want to add must have set same (initialized!) variables
+# like you can see in ${GK_SHARE}/software.sh.
+#
+# <PKG> Name of the package (as used in ${GK_SHARE}/patches).
+#
+# <PKG_VERSION> Version of the package.
+#
+# <PKG_SRCDIR> Source directory when unpacked.
+#
+# <PKG_SRCTAR> Source file. Only archives supported by `tar -xaf` are
+# supported.
+#
+# <PKG_BINCACHE> File where genkernel will store the package's image.
+#
+# <PKG_DEPS> Single word string of required package's PKG_BINCACHE.
+gkbuild() {
+ [[ ${#} -lt 5 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at least five arguments (${#} given)!"
+ [[ ${#} -gt 7 ]] \
+ && gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): Function takes at most six arguments (${#} given)!"
+
+ if ! hash sandbox &>/dev/null
+ then
+ gen_die "Sandbox not found. Please install sys-apps/sandbox!"
+ fi
+
+ local PKG=${1}
+ local VERSION=${2}
+ local SRCDIR=${3}
+ local SRCTAR=${4}
+ local BINPKG=${5}
+
+ if [[ "$#" -eq '6' ]]
+ then
+ local DEPS=${6}
+ else
+ local DEPS=""
+ fi
+
+ if [ -z "${PKG}" ]
+ then
+ gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): PKG is not set!"
+ elif [ -z "${VERSION}" ]
+ then
+ gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): VERSION is not set!"
+ elif [ -z "${SRCDIR}" ]
+ then
+ gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): SRCDIR is not set!"
+ elif [ -z "${SRCTAR}" ]
+ then
+ gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): SRCTAR is not set!"
+ elif [ -z "${BINPKG}" ]
+ then
+ gen_die "$(get_useful_function_stack "${FUNCNAME}")Invalid usage of ${FUNCNAME}(): BINPKG is not set!"
+ fi
+
+ local -a envvars=(
+ GK_SHARE="${GK_SHARE}"
+ LOGLEVEL="${LOGLEVEL}"
+ LOGFILE="${LOGFILE}"
+ NOCOLOR="${NOCOLOR}"
+ TEMP="${TEMP}"
+ SANDBOX_WRITE="${LOGFILE}:${TEMP}"
+ )
+
+ envvars+=(
+ GKPKG_PN="${PKG}"
+ GKPKG_PV="${VERSION}"
+ GKPKG_SRCDIR="${SRCDIR}"
+ GKPKG_SRCTAR="${SRCTAR}"
+ GKPKG_BINPKG="${BINPKG}"
+ GKPKG_DEPS="${DEPS}"
+ )
+
+ envvars+=(
+ CFLAGS="${CMD_UTILS_CFLAGS}"
+ CXXFLAGS="${CMD_UTILS_CFLAGS}"
+ CBUILD="${CBUILD}"
+ CHOST="${CHOST}"
+ AR="$(tc-getAR)"
+ AS="$(tc-getAS)"
+ CC="$(tc-getCC)"
+ CPP="$(tc-getCPP)"
+ CXX="$(tc-getCXX)"
+ LD="$(tc-getLD)"
+ NM="$(tc-getNM)"
+ MAKE="${CMD_UTILS_MAKE}"
+ OBJCOPY="$(tc-getOBJCOPY)"
+ OBJDUMP="$(tc-getOBJDUMP)"
+ RANLIB="$(tc-getRANLIB)"
+ STRIP="$(tc-getSTRIP)"
+ )
+
+ if [ ${NICE} -ne 0 ]
+ then
+ NICEOPTS="nice -n${NICE} "
+ else
+ NICEOPTS=""
+ fi
+ envvars+=( NICEOPTS="${NICEOPTS}" )
+
+ envvars+=( MAKEOPTS="${MAKEOPTS}" )
+
+ # set up gkbuild signal handler
+ local error_msg="gen_worker.sh aborted: Failed to compile ${PKG}-${VERSION}!"
+ trap "gen_die \"${error_msg}\"" SIGABRT SIGHUP SIGQUIT SIGINT SIGTERM
+
+ env -i \
+ "${envvars[@]}" \
+ sandbox "${GK_SHARE}"/gen_worker.sh build 2>&1
+
+ local RET=$?
+
+ # remove gkbuild signal handler
+ set_default_gk_trap
+
+ [ ${RET} -ne 0 ] && gen_die "$(get_useful_function_stack)Failed to create binpkg of ${PKG}-${VERSION}!"
+}
+
set_default_gk_trap() {
trap trap_cleanup SIGABRT SIGHUP SIGQUIT SIGINT SIGTERM
}
diff --git a/gen_worker.sh b/gen_worker.sh
index 71b221fd..fa0251b2 100755
--- a/gen_worker.sh
+++ b/gen_worker.sh
@@ -137,6 +137,9 @@ then
fi
case "${1}" in
+ build)
+ MODULE="${GK_SHARE}/worker_modules/gkbuild.sh"
+ ;;
*)
die "Unknown module '${1}' specified!"
;;
diff --git a/worker_modules/gkbuild.sh b/worker_modules/gkbuild.sh
new file mode 100644
index 00000000..20de2633
--- /dev/null
+++ b/worker_modules/gkbuild.sh
@@ -0,0 +1,705 @@
+#!/bin/bash
+# Copyright 1999-2019 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+__module_main() {
+ _gkbuild_main
+}
+
+# Remove occurrences of strings from variable given in $1
+# Strings removed are matched as globs, so for example
+# '-O*' would remove -O1, -O2 etc.
+_filter-var() {
+ local f x var=$1 new=()
+ shift
+
+ for f in ${!var} ; do
+ for x in "$@" ; do
+ # Note this should work with globs like -O*
+ [[ ${f} == ${x} ]] && continue 2
+ done
+ new+=( "${f}" )
+ done
+ export ${var}="${new[*]}"
+}
+
+_gkbuild_main() {
+ _initialize
+
+ addwrite "${TEMP}"
+
+ local all_phases="src_unpack src_prepare src_configure
+ src_compile src_install"
+ local x
+
+ # Set up the default functions
+ for x in ${all_phases} ; do
+ case "${x}" in
+ src_unpack)
+ default_src_unpack() { _src_unpack; }
+ ;;
+
+ src_prepare)
+ default_src_prepare() { _src_prepare; }
+ ;;
+
+ src_configure)
+ default_src_configure() { _src_configure; }
+ ;;
+
+ src_compile)
+ default_src_compile() { _src_compile; }
+ ;;
+
+ src_install)
+ default_src_install() { _src_install; }
+ ;;
+
+ *)
+ eval "default_${x}() {
+ die \"${x}() has no default function!\"
+ }"
+ ;;
+ esac
+
+ if ! declare -F ${x} >/dev/null && declare -F default_${x} >/dev/null
+ then
+ eval "${x}() { default; }"
+ fi
+ done
+
+ local current_phase=
+ for current_phase in ${all_phases}
+ do
+ export GKBUILD_PHASE=${current_phase}
+
+ # Make sure default() points to the correct phase
+ eval "default() {
+ default_${current_phase}
+ }"
+
+ case "${current_phase}" in
+ src_compile)
+ print_info 2 "$(get_indent 2)${P}: >> Compiling source ..."
+ ;;
+
+ src_configure)
+ print_info 2 "$(get_indent 2)${P}: >> Configuring source ..."
+ declare -ga CONFIGUREOPTS
+ ;;
+
+ src_install)
+ print_info 2 "$(get_indent 2)${P}: >> Install to DESTDIR ..."
+ ;;
+
+ src_prepare)
+ print_info 2 "$(get_indent 2)${P}: >> Preparing source ..."
+ ;;
+
+ src_unpack)
+ print_info 2 "$(get_indent 2)${P}: >> Unpacking source ..."
+ ;;
+ esac
+
+ ${current_phase} || die "${P} failed in '${current_phase}' phase!"
+
+ # sanity check
+ [[ "${current_phase}" == "src_unpack" && ! -d "${S}" ]] \
+ && die "The source directory '${S}' does NOT exist!"
+ done
+
+ # We don't use .la files; Let's get rid of them to avoid problems
+ # due to invalid paths.
+ find "${D}" -name '*.la' -type f -delete
+
+ local BINCACHEDIR=$(dirname "${GKPKG_BINPKG}")
+ addwrite "${BINCACHEDIR}"
+
+ print_info 2 "$(get_indent 2)${P}: >> Creating binpkg ..."
+ cd "${D}" || die "Failed to chdir to '${D}'!"
+
+ if ! hash scanelf &>/dev/null
+ then
+ print_warning 3 "'scanelf' not found; Will not ensure that binpkg will not contain dynamically linked binaries."
+ else
+ print_info 5 "Scanning for dynamically linked programs ..."
+
+ # Limiting scan to /{bin,sbin,usr/bin,usr/sbin} will allow us to keep
+ # dynamically linked libs in binpkg which is sometimes required to build
+ # other packages.
+ local -a executable_files_to_scan=()
+ local executable_file_to_scan=
+ local executable_file_to_scan_wo_broot= pattern_to_ignore=
+ while IFS= read -r -u 3 -d $'\0' executable_file_to_scan
+ do
+ executable_file_to_scan_wo_broot=${executable_file_to_scan#${D}}
+
+ if [[ -n "${QA_IGNORE_DYNAMICALLY_LINKED_PROGRAM}" ]]
+ then
+ local pattern_to_ignore=
+ for pattern_to_ignore in ${QA_IGNORE_DYNAMICALLY_LINKED_PROGRAM}
+ do
+ print_info 5 "Using pattern '${pattern_to_ignore}' ..."
+ if [[ "${executable_file_to_scan_wo_broot}" =~ ${pattern_to_ignore} ]]
+ then
+ print_info 5 "Match on '${executable_file_to_scan_wo_broot}'; Will ignore ..."
+ executable_file_to_scan=
+ break
+ else
+ print_info 5 "No match on '${executable_file_to_scan_wo_broot}'!"
+ fi
+ done
+ else
+ print_info 5 "QA_IGNORE_DYNAMICALLY_LINKED_PROGRAM is not set; Not checking '${executable_file_to_scan_wo_broot}' for exclusion ..."
+ fi
+
+ if [[ -n "${executable_file_to_scan}" ]]
+ then
+ executable_files_to_scan+=( "${executable_file_to_scan}" )
+ fi
+ done 3< <(find "${D}"/{bin,sbin,usr/bin,usr/sbin} -type f -perm -a+x -print0 2>/dev/null)
+ IFS="${GK_DEFAULT_IFS}"
+ unset executable_file_to_scan executable_file_to_scan_wo_broot pattern_to_ignore
+
+ local found_dyn_files=
+ if [[ -n "${executable_files_to_scan}" ]]
+ then
+ found_dyn_files=$(scanelf -E ET_DYN "${executable_files_to_scan[@]}" 2>/dev/null)
+ fi
+
+ if [[ -n "${found_dyn_files}" ]]
+ then
+ print_error 1 "Found the following dynamically linked programs:"
+ print_error 1 "=================================================================" 1 0 1
+ print_error 1 "${found_dyn_files}" 1 0 1
+ print_error 1 "=================================================================" 1 0 1
+ die "Dynamically linked program(s) found in ${P} image!"
+ fi
+ unset found_dyn_files
+ fi
+
+ tar -caf "${GKPKG_BINPKG}" . \
+ || die "Failed to create binpkg of ${P} in '${GKPKG_BINPKG}'!"
+}
+
+_initialize() {
+ if [[ -z "${GKPKG_PN}" ]]
+ then
+ die "Unable to build: GKPKG_PN not set!"
+ elif [[ -z "${GKPKG_PV}" ]]
+ then
+ die "Unable to build '${PN}': GKPKG_PV not set!"
+ else
+ declare -gr PN=${GKPKG_PN}
+ declare -gr PV=${GKPKG_PV}
+ declare -gr P="${PN}-${PV}"
+ fi
+
+ if [[ -z "${GKPKG_SRCDIR}" ]]
+ then
+ die "Unable to build ${P}: GKPKG_SRCDIR is not set!"
+ elif [[ -z "${GKPKG_SRCTAR}" ]]
+ then
+ die "Unable to build ${P}: GKPKG_SRCTAR is not set!"
+ elif [[ ! -r "${GKPKG_SRCTAR}" ]]
+ then
+ die "Unable to build ${P}: '${GKPKG_SRCTAR}' does NOT exist or is not readable!"
+ elif [[ -z "${GKPKG_BINPKG}" ]]
+ then
+ die "Unable to build ${P}: GKPKG_BINPKG is not set!"
+ elif ! declare -p GKPKG_DEPS >/dev/null
+ then
+ die "Unable to build ${P}: GKPKG_DEPS is not set!"
+ elif [[ -z "${CBUILD}" ]]
+ then
+ die "Unable to build ${P}: CBUILD not set!"
+ elif [[ -z "${CHOST}" ]]
+ then
+ die "Unable to build ${P}: CHOST is not set!"
+ elif [[ -z "${TEMP}" ]]
+ then
+ die "Unable to build ${P}: TEMP is not set!"
+ fi
+
+ print_info 3 "Trying to determine gkbuild for ${P} ..."
+ local GKBUILD= f=
+ local GKBUILD_CANDIDATES=( "${GK_SHARE}/gkbuilds/${P}.gkbuild" )
+ GKBUILD_CANDIDATES+=( "${GK_SHARE}/gkbuilds/${PN}.gkbuild" )
+ for f in "${GKBUILD_CANDIDATES[@]}"
+ do
+ if [[ ! -e "${f}" ]]
+ then
+ print_info 3 "'${f}' not found; Skipping ..."
+ continue
+ else
+ print_info 3 "Will use '${f}' to build ${P} ..."
+ GKBUILD="${f}"
+ break
+ fi
+ done
+ unset f GKBUILD_CANDIDATES
+
+ if [[ -z "${GKBUILD}" ]]
+ then
+ die "Unable to build ${P}: '${GK_SHARE}/gkbuilds/${PN}.gkbuild' does NOT exist!"
+ fi
+
+ source "${GKBUILD}" \
+ || die "Failed to source '${GKBUILD}'!"
+
+ declare -gr WORKDIR=$(mktemp -d -p "${TEMP}" ${PN}.XXXXXXXX 2>/dev/null)
+ [ -z "${WORKDIR}" ] && die "mktemp failed!"
+
+ declare -gr BROOT="${WORKDIR}/buildroot"
+ mkdir "${BROOT}" || die "Failed to create '${BROOT}'!"
+
+ declare -gr DESTDIR="${WORKDIR}/image"
+ mkdir "${DESTDIR}" || die "Failed to create '${DESTDIR}'!"
+
+ declare -gr HOME="${WORKDIR}/home"
+ mkdir "${HOME}" || die "Failed to create '${HOME}'!"
+
+ # Set up some known variables used in ebuilds for smooth gkbuild
+ # transition
+ declare -gr ED=${DESTDIR}
+ declare -gr D=${DESTDIR}
+
+ local libdir=$(get_chost_libdir)
+ if [[ "${libdir}" =~ ^/(lib|usr/lib) ]]
+ then
+ declare -gr SYSROOT="/"
+ else
+ declare -gr SYSROOT="/usr/${CHOST}"
+ fi
+ unset libdir
+ print_info 4 "SYSROOT set to '${SYSROOT}'!"
+
+ declare -gr T="${WORKDIR}/temp"
+ mkdir "${T}" || die "Failed to create '${T}'!"
+
+ S="${WORKDIR}/${GKPKG_SRCDIR}"
+
+ # Some tools like eltpatch (libtoolize) depend on these variables
+ export S D
+
+ if [[ -n "${GKPKG_DEPS}" ]]
+ then
+ # GKPKG_DEPS is ${ARRAY[*]} value (single word), not ${ARRAY[@]} (separate word)!
+ GKPKG_DEPS=( ${GKPKG_DEPS} )
+ local GKPKG_DEP=
+ for GKPKG_DEP in "${GKPKG_DEPS[@]}"
+ do
+ if [[ ! -r "${GKPKG_DEP}" ]]
+ then
+ die "Unable to build ${P}: Required binpkg '${GKPKG_DEP}' does NOT exist or is not readable!"
+ fi
+
+ print_info 2 "$(get_indent 2)${P}: >> Unpacking required binpkg '${GKPKG_DEP}' ..."
+ tar -xaf "${GKPKG_DEP}" -C "${BROOT}" \
+ || die "Unable to build ${P}: Failed to extract required binpkg '${GKPKG_DEP}' to '${BROOT}'!"
+ done
+ unset GKPKG_DEP
+
+ append-cflags -I"${BROOT}"/usr/include
+ append-cppflags -I"${BROOT}"/usr/include
+ append-ldflags -L"${BROOT}"/usr/lib
+ fi
+
+ if [[ ! -d "${BROOT}/usr/bin" ]]
+ then
+ mkdir -p "${BROOT}"/usr/bin || die "Failed to create '${BROOT}/usr/bin'!"
+ fi
+
+ cat >"${BROOT}"/usr/bin/pkg-config-wrapper <<-EOF
+ #!/bin/sh
+
+ SYSROOT=\$(dirname "\$(dirname "\$(dirname "\$(readlink -fm "\$0")")")")
+
+ # https://git.dereferenced.org/pkgconf/pkgconf/issues/30
+ unset PKG_CONFIG_PATH PKG_CONFIG_DIR LIBRARY_PATH
+
+ export PKG_CONFIG_LIBDIR=\${SYSROOT}/usr/lib/pkgconfig
+ export PKG_CONFIG_SYSROOT_DIR=\${SYSROOT}
+
+ exec pkg-config "\$@"
+ EOF
+
+ chmod +x "${BROOT}"/usr/bin/pkg-config-wrapper \
+ || die "Failed to chmod of '${BROOT}/usr/bin/pkg-config-wrapper'!"
+
+ export PATH="${BROOT}/usr/sbin:${BROOT}/usr/bin:${BROOT}/sbin:${BROOT}/bin:${PATH}"
+ export PKG_CONFIG="${BROOT}/usr/bin/pkg-config-wrapper"
+}
+
+_src_compile() {
+ cd "${S}" || die "Failed to chdir to '${S}'!"
+
+ if [ -f Makefile ] || [ -f GNUmakefile ] || [ -f makefile ]
+ then
+ gkmake V=1
+ fi
+}
+
+_src_configure() {
+ cd "${S}" || die "Failed to chdir to '${S}'!"
+
+ if [[ -x ${GKCONF_SOURCE:-.}/configure ]]
+ then
+ gkconf
+ fi
+}
+
+_src_install() {
+ cd "${S}" || die "Failed to chdir to '${S}'!"
+
+ if [ -f Makefile ] || [ -f GNUmakefile ] || [ -f makefile ]
+ then
+ gkmake V=1 DESTDIR="${D}" install
+ fi
+}
+
+_src_prepare() {
+ cd "${S}" || die "Failed to chdir to '${S}'!"
+
+ # let's try to be smart and run autoreconf only when needed
+ local want_autoreconf=${WANT_AUTORECONF}
+
+ # by default always run libtoolize
+ local want_libtoolize=${WANT_LIBTOOLIZE:-yes}
+
+ local patchdir="${GK_SHARE}/patches/${PN}/${PV}"
+
+ uses_autoconf() {
+ if [[ -f configure.ac || -f configure.in ]]
+ then
+ return 0
+ fi
+
+ return 1
+ }
+
+ at_checksum() {
+ find '(' -name 'Makefile.am' \
+ -o -name 'configure.ac' \
+ -o -name 'configure.in' ')' \
+ -exec cksum {} + | sort -k2
+ }
+
+ if $(uses_autoconf) && ! isTrue "${want_autoreconf}"
+ then
+ local checksum=$(at_checksum)
+ fi
+ if [[ -d "${patchdir}" ]]
+ then
+ local silent="-s "
+ if [[ "${LOGLEVEL}" -gt 3 ]]
+ then
+ silent=
+ fi
+
+ print_info 2 "$(get_indent 2)${P}: >> Applying patches ..."
+ local i
+ for i in "${patchdir}"/*{diff,patch}
+ do
+ [ -f "${i}" ] || continue
+ local patch_success=0
+ local j=
+ for j in $(seq 0 5)
+ do
+ patch -p${j} --backup-if-mismatch -f < "${i}" --dry-run >/dev/null \
+ && patch ${silent}-p${j} --backup-if-mismatch -f < "${i}"
+ if [ $? = 0 ]
+ then
+ patch_success=1
+ break
+ fi
+ done
+ if [ ${patch_success} -eq 1 ]
+ then
+ print_info 3 "$(get_indent 3) - $(basename "${i}")"
+ else
+ die "Failed to apply patch '${i}' for '${P}'!"
+ fi
+ done
+ unset i j patch_success
+ else
+ print_info 2 "$(get_indent 2)${P}: >> No patches found in '$patchdir'; Skipping ..."
+ fi
+
+ if $(uses_autoconf) && ! isTrue "${want_autoreconf}"
+ then
+ if [[ ${checksum} != $(at_checksum) ]]
+ then
+ print_info 3 "$(get_indent 2)${P}: >> Will autoreconfigure due applied patches ..."
+ want_autoreconf=yes
+ fi
+ fi
+
+ if $(uses_autoconf) && isTrue "${want_autoreconf}"
+ then
+ gkautoreconf
+ fi
+
+ if isTrue "${want_libtoolize}"
+ then
+ gklibtoolize
+ fi
+}
+
+_src_unpack() {
+ cd "${WORKDIR}" || die "Failed to chdir to '${WORKDIR}'!"
+ tar -xaf "${GKPKG_SRCTAR}" \
+ || die "Failed to unpack '${GKPKG_SRCTAR}' to '${WORKDIR}'!"
+}
+
+# Return all the flag variables that our high level funcs operate on.
+all-flag-vars() {
+ echo {ADA,C,CPP,CXX,CCAS,F,FC,LD}FLAGS
+}
+
+# @FUNCTION: append-cflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to the current CFLAGS. If a flag might not be supported
+# with different compilers (or versions), then use test-flags-CC like so:
+# @CODE
+# append-cflags $(test-flags-CC -funky-flag)
+# @CODE
+append-cflags() {
+ [[ $# -eq 0 ]] && return 0
+ # Do not do automatic flag testing ourselves. #417047
+ export CFLAGS+=" $*"
+ return 0
+}
+
+# @FUNCTION: append-cppflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to the current CPPFLAGS.
+append-cppflags() {
+ [[ $# -eq 0 ]] && return 0
+ export CPPFLAGS+=" $*"
+ return 0
+}
+
+# @FUNCTION: append-cxxflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to the current CXXFLAGS. If a flag might not be supported
+# with different compilers (or versions), then use test-flags-CXX like so:
+# @CODE
+# append-cxxflags $(test-flags-CXX -funky-flag)
+# @CODE
+append-cxxflags() {
+ [[ $# -eq 0 ]] && return 0
+ # Do not do automatic flag testing ourselves. #417047
+ export CXXFLAGS+=" $*"
+ return 0
+}
+
+# @FUNCTION: append-fflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to the current {F,FC}FLAGS. If a flag might not be supported
+# with different compilers (or versions), then use test-flags-F77 like so:
+# @CODE
+# append-fflags $(test-flags-F77 -funky-flag)
+# @CODE
+append-fflags() {
+ [[ $# -eq 0 ]] && return 0
+ # Do not do automatic flag testing ourselves. #417047
+ export FFLAGS+=" $*"
+ export FCFLAGS+=" $*"
+ return 0
+}
+
+# @FUNCTION: append-flags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to your current {C,CXX,F,FC}FLAGS.
+append-flags() {
+ [[ $# -eq 0 ]] && return 0
+ case " $* " in
+ *' '-[DIU]*) die 'please use append-cppflags for preprocessor flags' ;;
+ *' '-L*|\
+ *' '-Wl,*) die 'please use append-ldflags for linker flags' ;;
+ esac
+ append-cflags "$@"
+ append-cxxflags "$@"
+ append-fflags "$@"
+ return 0
+}
+
+# @FUNCTION: append-ldflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Add extra <flags> to the current LDFLAGS.
+append-ldflags() {
+ [[ $# -eq 0 ]] && return 0
+ export LDFLAGS="${LDFLAGS} $*"
+ return 0
+}
+
+# @FUNCTION: append-lfs-flags
+# @DESCRIPTION:
+# Add flags that enable Large File Support.
+append-lfs-flags() {
+ [[ $# -ne 0 ]] && die "append-lfs-flags takes no arguments"
+ # see comments in filter-lfs-flags func for meaning of these
+ append-cppflags -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
+}
+
+
+# @FUNCTION: filter-flags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Remove particular <flags> from {C,CPP,CXX,CCAS,F,FC,LD}FLAGS. Accepts shell globs.
+filter-flags() {
+ local v
+ for v in $(all-flag-vars) ; do
+ _filter-var ${v} "$@"
+ done
+ return 0
+}
+
+# @FUNCTION: filter-ldflags
+# @USAGE: <flags>
+# @DESCRIPTION:
+# Remove particular <flags> from LDFLAGS. Accepts shell globs.
+filter-ldflags() {
+ _filter-var LDFLAGS "$@"
+ return 0
+}
+
+# @FUNCTION: gkautomake
+# @USAGE: [<additional-automake-parameter>]
+# @DESCRIPTION:
+# Wrapper for automake.
+# Will die when command will exit with nonzero exit status.
+gkautomake() {
+ if [[ -n "${WANT_AUTOMAKE}" ]]
+ then
+ gkexec "WANT_AUTOMAKE=${WANT_AUTOMAKE} automake ${*}"
+ else
+ gkexec "automake ${*}"
+ fi
+}
+
+# @FUNCTION: gkautoreconf
+# @USAGE: [<additional-autoreconf-parameter>]
+# @DESCRIPTION:
+# Wrapper for autoreconf.
+# Will die when command will exit with nonzero exit status.
+gkautoreconf() {
+ gkexec "autoreconf --force --install ${*}"
+}
+
+# @FUNCTION: gkconf
+# @USAGE: [<additional-configure-parameter>]
+# @DESCRIPTION:
+# Wrapper for configure.
+# Will die when command will exit with nonzero exit status.
+gkconf() {
+ : ${GKCONF_SOURCE:=.}
+ if [ -x "${GKCONF_SOURCE}/configure" ]
+ then
+ local -a conf_args=()
+ local conf_help=$("${GKCONF_SOURCE}/configure" --help 2>/dev/null)
+
+ if [[ ${conf_help} == *--disable-dependency-tracking* ]]; then
+ conf_args+=( --disable-dependency-tracking )
+ fi
+
+ if [[ ${conf_help} == *--disable-silent-rules* ]]; then
+ conf_args+=( --disable-silent-rules )
+ fi
+
+ if [[ ${conf_help} == *--docdir* ]]; then
+ conf_args+=( --docdir=/usr/share/doc/${P} )
+ fi
+
+ if [[ ${conf_help} == *--htmldir* ]]; then
+ conf_args+=( --htmldir=/usr/share/doc/${P}/html )
+ fi
+
+ if [[ ${conf_help} == *--with-sysroot* ]]; then
+ conf_args+=( --with-sysroot="${BROOT}/usr:${SYSROOT}" )
+ fi
+
+ # Handle arguments containing quoted whitespace (see bug #457136).
+ eval "local -a EXTRA_ECONF=(${EXTRA_ECONF})"
+
+ set -- \
+ --prefix=/usr \
+ ${CBUILD:+--build=${CBUILD}} \
+ --host=${CHOST} \
+ ${CTARGET:+--target=${CTARGET}} \
+ --mandir=/usr/share/man \
+ --infodir=/usr/share/info \
+ --datadir=/usr/share \
+ --sysconfdir=/etc \
+ --localstatedir=/var/lib \
+ "${conf_args[@]}" \
+ "$@" \
+ "${EXTRA_ECONF[@]}"
+
+ gkexec "${GKCONF_SOURCE}/configure $*"
+ elif [ -f "${GKCONF_SOURCE}/configure" ]; then
+ die "configure is not executable"
+ else
+ die "no configure script found"
+ fi
+}
+
+# @FUNCTION: gklibtoolize
+# @USAGE: [dirs] [--portage] [--reverse-deps] [--patch-only] [--remove-internal-dep=xxx] [--shallow] [--no-uclibc]
+# @DESCRIPTION:
+# Apply a smorgasbord of patches to bundled libtool files. This function
+# should always be safe to run. If no directories are specified, then
+# ${S} will be searched for appropriate files.
+#
+# If the --shallow option is used, then only ${S}/ltmain.sh will be patched.
+#
+# The other options should be avoided in general unless you know what's going on.
+gklibtoolize() {
+ type -P eltpatch &>/dev/null || die "eltpatch not found; is app-portage/elt-patches installed?"
+
+ gkexec "ELT_LOGDIR=\"${T}\" LD=\"$(tc-getLD)\" eltpatch ${*}"
+}
+
+# @FUNCTION: gkmake
+# @USAGE: [<additional-make-parameter>]
+# @DESCRIPTION:
+# Wrapper for make.
+# Will die when command will exit with nonzero exit status.
+gkmake() {
+ local command=( "${NICEOPTS}${MAKE} ${MAKEOPTS}" )
+ command+=( "${@}" )
+
+ gkexec "${command[*]}"
+}
+
+# @FUNCTION: replace-flags
+# @USAGE: <old> <new>
+# @DESCRIPTION:
+# Replace the <old> flag with <new>. Accepts shell globs for <old>.
+replace-flags() {
+ [[ $# != 2 ]] && die "Usage: replace-flags <old flag> <new flag>"
+
+ local f var new
+ for var in $(all-flag-vars) ; do
+ # Looping over the flags instead of using a global
+ # substitution ensures that we're working with flag atoms.
+ # Otherwise globs like -O* have the potential to wipe out the
+ # list of flags.
+ new=()
+ for f in ${!var} ; do
+ # Note this should work with globs like -O*
+ [[ ${f} == ${1} ]] && f=${2}
+ new+=( "${f}" )
+ done
+ export ${var}="${new[*]}"
+ done
+
+ return 0
+}