[PATCH 09/10] nginx-module.eclass: add ngx_force_module()
Zurab Kvachadze <[email protected]> Sat, 18 Jul 2026 19:37:06 +0300
| Newsgroups | gmane.linux.gentoo.devel |
|---|---|
| Message-ID | <[email protected]> |
This is similar to gtk's GENTOO_GTK_HIDE_{X11,WAYLAND}. Many third-party
modules do automagic dependencies on first-party NGINX modules. This
adds a function that allows to selectively enable or disable specified
modules.
The actual enabling/disabling occurs in nginx-module_src_configure,
where an internal function _ngx_mod_enforce_module_flags (for the lack
of better name) does some heuristics to find the correct ./configure
flag(s) to enable/disable the specified module(s).
Signed-off-by: Zurab Kvachadze <[email protected]>
---
eclass/nginx-module.eclass | 239 ++++++++++++++++++++++++++++++++++++-
1 file changed, 237 insertions(+), 2 deletions(-)
diff --git a/eclass/nginx-module.eclass b/eclass/nginx-module.eclass
index 0bb3f207ed39..682a889375ac 100644
--- a/eclass/nginx-module.eclass
+++ b/eclass/nginx-module.eclass
@@ -92,7 +92,7 @@ if [[ -z ${_NGINX_MODULE_ECLASS} ]]; then
_NGINX_MODULE_ECLASS=1
case ${EAPI} in
- 8) inherit edo ;;
+ 8) inherit edo eapi9-pipestatus ;;
9) ;;
*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
esac
@@ -101,6 +101,167 @@ inherit flag-o-matic toolchain-funcs
#-----> Generic helper functions <-----
+# @FUNCTION: _ngx_mod_assert_argfile_exists
+# @INTERNAL
+# @USAGE: <argfile>
+# @DESCRIPTION:
+# Checks whether the specified configure flags file exists and die's with a
+# explanatory message otherwise.
+_ngx_mod_assert_argfile_exists() {
+ debug-print-function "${FUNCNAME[0]}" "$@"
+ [[ $# -eq 1 ]] || die "${FUNCNAME[0]} must receive exactly one argument"
+
+ if [[ ! -f "$1" ]]; then
+ eerror "The file with NGINX configure flags has not been found at the"
+ eerror "following path: \"$1\""
+ eerror ""
+ eerror "The most probable cause is a stale installation of www-servers/nginx."
+ eerror "Please make sure to reemerge NGINX like shown below, and attempt"
+ eerror "to emerge this package again."
+ eerror ""
+ eerror "To reemerge www-servers/nginx, issue the following command."
+ eerror " emerge --ask --oneshot www-servers/nginx"
+ eerror ""
+ eerror "If a reinstallation of www-servers/nginx still results in this"
+ eerror "error, please seek guidance on Gentoo social channels and/or file"
+ eerror "a bug as described on Gentoo Wiki."
+
+ die "Unable to find the required NGINX ./configure flags file"
+ fi
+ return 0
+}
+
+# @FUNCTION: _ngx_mod_enforce_module_flags
+# @INTERNAL
+# @USAGE: <flags var name> <module name> <module state>
+# @DESCRIPTION:
+# Takes three parameters: (1) the name of the variable holding ./configure flags
+# used to build NGINX, (2) the name of the module which needs to be
+# enabled/disabled, (3) and the requested state.
+#
+# Let state be the requested state of the module. If state > 0, the module is
+# enabled, if state < 0, the module is disabled. If abs(state) == 1, the
+# function die's if the specified module is not found, if abs(state) == 2, the
+# function does not die and returns 1 in such case.
+#
+# Let mod be the requested module to be enabled/disabled, let flags be the
+# read-write variable holding flags used to build NGINX (those flags will also
+# be used to build mod). mod is enabled/disabled as follows:
+#
+# 1. Strings corresponding to ./configure flags to set mod in the desired
+# (target_string) and inverse (inverse_string) configurations are
+# constructed.
+#
+# 2. We iterate over flags. If we see an element matching target_string, we
+# know that mod is already in its desired configuration and return. If we
+# see inverse_string, we remove it from flags. This guarantees that NGINX
+# builds mod in the desired configuration. This is because NGINX does not
+# allow to specify ./configure flags that repeat default settings, so if we
+# see inverse_string, we know that the default configuration of mod is our
+# desired configuration.
+#
+# 3. If flags do not contain either target_string or inverse_string, we grep
+# ./configure --help to find out whether the desired configuration is the
+# default and if module is present at all.
+#
+# 3.1. If we see target_string in the output of ./configure --help, we know
+# that this is the flag that needs to be supplied to get the desired
+# configuration of mod. We add target_string to flags and return.
+#
+# 3.2. If we do not see target_string but see inverse_string, we know that
+# the module exists and its default state corresponds to the desired state.
+# We return.
+#
+# 3.3. If neither target_string nor inverse_string are found, the module
+# does not exist. If abs(state) == 1, we die. If abs(state) == 2, we
+# return 1.
+_ngx_mod_enforce_module_flags() {
+ debug-print-function "${FUNCNAME[0]}" "$@"
+ [[ $# -eq 3 ]] || die "${FUNCNAME[0]} must receive exactly three arguments"
+
+ local -n ref_target="$1"
+ local mod="$2"
+ local state="$3"
+
+ if ! [[ ${state} -ge -2 && ${state} -le 2 && ${state} != 0 ]]; then
+ die "${FUNCNAME[0]}: invalid state value: ${state}. Please file a bug"
+ fi
+
+ # First, construct target_string and inverse_string.
+ local target_string inverse_string
+ if [[ ${state} -gt 0 ]]; then
+ target_string="--with-${mod}_module"
+ inverse_string="--without-${mod}_module"
+ else
+ target_string="--without-${mod}_module"
+ inverse_string="--with-${mod}_module"
+ fi
+
+ # Check whether we already have the target_string or inverse_string in
+ # the specified flag variable.
+ local key
+ for key in "${!ref_target[@]}"; do
+ case "${ref_target[${key}]}" in
+ "${target_string}")
+ # We already have the module in the desired configuration,
+ # simply return.
+ return 0
+ ;;
+ "${inverse_string}")
+ # We have a flag that does the opposite of we want: remove the
+ # flag and we are done with this module.
+ unset 'ref_target[${key}]'
+ return 0
+ ;;
+ *)
+ # Some other flag -- continue to the next entry in the flags
+ # variable.
+ continue
+ ;;
+ esac
+ done
+
+ # If we are still here, we have not found either target_string or
+ # inverse_string in the flags variable.
+ #
+ # Now, we grep for target_string in ./configure --help output. If we find
+ # it, we append target_string to the flags variable. If not, the default
+ # state of the module _is_ the desired state (if the module exists), so we
+ # do not need to do anything to force module to the requested state.
+ local status
+ econf_ngx --help |& grep -q -F -- "${target_string}"
+ pipestatus
+ status=$?
+ if [[ ${status} -eq 0 ]]; then
+ ref_target+=( "${target_string}" )
+ return 0
+ elif [[ ${status} -ne 1 ]]; then
+ die "grep failed"
+ fi
+
+ # Check whether the specified module exists at all.
+ econf_ngx --help |& grep -q -F -- "${inverse_string}"
+ pipestatus
+ status=$?
+ if [[ ${status} -eq 0 ]]; then
+ # If inverse_string exists, we know that the module is present: we
+ # can safely return.
+ return 0
+ elif [[ ${status} -ne 1 ]]; then
+ die "grep failed"
+ fi
+
+ if [[ ${state} -ne 2 && ${state} -ne -2 ]]; then
+ # Neither target_string, nor inverse_string are found in
+ # ./configure --help: either the module genuinely does not exist or
+ # something has gone really wrong.
+ die "ngx_force_module: module \"${mod}\" not found and '-n' has not been supplied"
+ else
+ # If we do not die, we just return 1.
+ return 1
+ fi
+}
+
# @FUNCTION: econf_ngx
# @USAGE: [<args>...]
# @DESCRIPTION:
@@ -366,6 +527,64 @@ ngx_gen_dep() {
printf '%s\n' "${out}"
}
+# @FUNCTION: ngx_force_module
+# @USAGE: [-t] <module> [<module>...]
+# @DESCRIPTION:
+# Enable or disable the specified first-party NGINX module(s). To disable a
+# module, prefix it with a bang: '!'. If the same module is supplied multiple
+# times, the later module overrides the previous ones.
+#
+# If the '-t' option is specified, the not found module is not treated as an
+# error and is instead ignored. If '-t' is not specified, if the module is not
+# found, the build is aborted with die. The option might be useful for newer or
+# older modules, that might not be present in all NGINX versions.
+#
+# Example:
+# @CODE
+# # Force enable the http_ssl module.
+# ngx_force_module http_ssl
+#
+# # Force disable the stream_ssl module
+# ngx_force_module !stream_ssl
+#
+# # The following call overrides the first call, forcing http_ssl off.
+# ngx_force_module !http_ssl
+#
+# # Do not die if http_foo_bar is not found, but do try to force enable it if
+# # present.
+# ngx_force_module -t http_foo_bar
+# @CODE
+ngx_force_module() {
+ debug-print-function "${FUNCNAME[0]}" "$@"
+ [[ $# -ge 1 ]] ||
+ die "${FUNCNAME[0]} must receive one or more non-option arguments"
+ _ngx_mod_assert_argfile_exists "${_NGX_MOD_CONFIG_FLAGS_FILE}"
+
+ local nonfatal=0
+ if [[ $1 = '-t' ]]; then
+ nonfatal=1
+ shift
+ [[ $# -ge 1 ]] ||
+ die "${FUNCNAME[0]} must receive one or more non-option arguments"
+ fi
+
+ local mod
+ local offstate=-1 onstate=1
+ if [[ ${nonfatal} -eq 1 ]]; then
+ offstate=-2
+ onstate=2
+ fi
+
+ for mod; do
+ if [[ ${mod:0:1} = '!' ]]; then
+ mod="${mod#\!}"
+ _NGX_MOD_FORCED_MODULES[${mod}]="${offstate}"
+ else
+ _NGX_MOD_FORCED_MODULES[${mod}]="${onstate}"
+ fi
+ done
+}
+
#-----> ebuild-defined variables <-----
# @ECLASS_VARIABLE: NGINX_MOD_S
@@ -418,6 +637,16 @@ NGINX_S="${WORKDIR}/nginx"
# build www-servers/nginx.
_NGX_MOD_CONFIG_FLAGS_FILE="${BROOT}/usr/src/nginx/configure-flags"
+# @ECLASS_VARIABLE: _NGX_MOD_FORCED_MODULES
+# @INTERNAL
+# @OUTPUT_VARIABLE
+# @DESCRIPTION:
+# An associative array containing first-party NGINX modules forced on or off by
+# a call to ngx_force_module(). See the description of
+# _ngx_mod_enforce_module_flags() for the valid values of each key stored in
+# this array.
+declare -g -A _NGX_MOD_FORCED_MODULES=()
+
# @ECLASS_VARIABLE: NGINX_MOD_SHARED_OBJECTS
# @OUTPUT_VARIABLE
# @DESCRIPTION:
@@ -776,6 +1005,13 @@ nginx-module_src_configure() {
# come with and install their own headers, e.g. ngx_devel_kit.
append-cflags "-isystem src/modules"
+ # Process _NGX_MOD_FORCED_MODULES by iterating over each forced module.
+ local mod
+ for mod in "${!_NGX_MOD_FORCED_MODULES[@]}"; do
+ local state="${_NGX_MOD_FORCED_MODULES[${mod}]}"
+ _ngx_mod_enforce_module_flags ngx_mod_flags "${mod}" "${state}"
+ done
+
# Some NGINX modules that depend on ngx_devel_kit (NDK) check whether the
# NDK_SRCS variable is non-empty and error out if it is empty or not
# defined. ngx_devel_kit sets this variable during its build but due to the
@@ -795,7 +1031,6 @@ nginx-module_src_configure() {
# Add the required linking flags required for the modules specified in the
# NGINX_MOD_LINK_MODULES array.
- local mod
for mod in "${NGINX_MOD_LINK_MODULES[@]}"; do
ngx_mod_link_module "${mod}"
done
--
2.54.0