[PATCH 08/10] nginx{,-module}.eclass: save NGINX build config by storing ./configure flags
Zurab Kvachadze <[email protected]> Sat, 18 Jul 2026 19:37:05 +0300
| Newsgroups | gmane.linux.gentoo.devel |
|---|---|
| Message-ID | <[email protected]> |
Background
==========
NGINX's ABI and API can change depending on supplied ./configure flags
(most notoriously, enabling/disabling many first-party modules can
change ABI and API of NGINX as a whole). Perhaps unrelated, but
third-party modules are expected to be built in-tree, at the same time
NGINX is built. It is because of these two factors that we have to
freeze/preserve NGINX configuration.
Configuration-saving methods
============================
In general, I have identified two approaches as to how to preserve NGINX
configuration for building third-party modules out-of-tree.
The current implementation saves the generated headers:
ngx_auto_config.h and ngx_auto_headers.h. When third-party modules are
built, the ./configure flags are mostly ignored. It is straightforward
and easy and allowed us to cut some parts of configuration out.
Unfortunately, due to headers not being first-class configuration in the
build system, it has proven to be quite difficult to change some parts
of the build using headers alone.
For instance, my initial header-mangling-based implementation of
ngx_force_module (see the following commit) proved to be quite limited
and not really robust. The reason why I used this approach initially is
because when nginx-module.eclass was written, none of the
ngx_force_module fancy crossed my mind.
Second method is saving the ./configure flags themselves. Although
increasing the src_configure time (since we no longer skip phases), this
allows to build modules and edit the build configuration more easily and
correctly. This also gives users/ebuild authors more control since, as
stated above, most ./configure flags are ignored in the header
implementation.
Compatibility
=============
While nginx.eclass completely removes support for emitting
ngx_auto_{config,headers}.h, generating only ./configure flags,
nginx-module.eclass will support both configuration-saving methods for
the time being, allowing users to update www-servers/nginx.
Notes
=====
Passing ./configure flags around makes modules transitively depend on
NGINX's dependencies.
-Wl,--as-needed is added to LDFLAGS since NGINX links external
libraries needed by first-party modules also to third-party modules.
Signed-off-by: Zurab Kvachadze <[email protected]>
---
eclass/nginx-module.eclass | 185 +++++++++++-------
eclass/nginx.eclass | 36 ++--
....29.5-r1.ebuild => nginx-1.29.5-r2.ebuild} | 0
....29.7-r2.ebuild => nginx-1.29.7-r3.ebuild} | 0
....30.0-r1.ebuild => nginx-1.30.0-r2.ebuild} | 0
....30.2-r1.ebuild => nginx-1.30.2-r2.ebuild} | 0
....30.3-r1.ebuild => nginx-1.30.3-r2.ebuild} | 0
...x-1.30.4.ebuild => nginx-1.30.4-r1.ebuild} | 0
....31.1-r1.ebuild => nginx-1.31.1-r2.ebuild} | 0
....31.2-r1.ebuild => nginx-1.31.2-r2.ebuild} | 0
...x-1.31.3.ebuild => nginx-1.31.3-r1.ebuild} | 0
11 files changed, 130 insertions(+), 91 deletions(-)
rename www-servers/nginx/{nginx-1.29.5-r1.ebuild => nginx-1.29.5-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.29.7-r2.ebuild => nginx-1.29.7-r3.ebuild} (100%)
rename www-servers/nginx/{nginx-1.30.0-r1.ebuild => nginx-1.30.0-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.30.2-r1.ebuild => nginx-1.30.2-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.30.3-r1.ebuild => nginx-1.30.3-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.30.4.ebuild => nginx-1.30.4-r1.ebuild} (100%)
rename www-servers/nginx/{nginx-1.31.1-r1.ebuild => nginx-1.31.1-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.31.2-r1.ebuild => nginx-1.31.2-r2.ebuild} (100%)
rename www-servers/nginx/{nginx-1.31.3.ebuild => nginx-1.31.3-r1.ebuild} (100%)
diff --git a/eclass/nginx-module.eclass b/eclass/nginx-module.eclass
index 51a0a54d3bf0..0bb3f207ed39 100644
--- a/eclass/nginx-module.eclass
+++ b/eclass/nginx-module.eclass
@@ -411,6 +411,13 @@ fi
# NGINX's headers are created in the nginx-module_src_prepare() phase function.
NGINX_S="${WORKDIR}/nginx"
+# @ECLASS_VARIABLE: _NGX_MOD_CONFIG_FLAGS_FILE
+# @INTERNAL
+# @DESCRIPTION:
+# Holds the path to the file containing NUL-separated ./configure flags used to
+# build www-servers/nginx.
+_NGX_MOD_CONFIG_FLAGS_FILE="${BROOT}/usr/src/nginx/configure-flags"
+
# @ECLASS_VARIABLE: NGINX_MOD_SHARED_OBJECTS
# @OUTPUT_VARIABLE
# @DESCRIPTION:
@@ -634,8 +641,7 @@ unset -f _ngx_mod_set_test_env
# @FUNCTION: nginx-module_src_prepare
# @DESCRIPTION:
-# Creates a fake build environment and patches the module's initialisation code
-# to play nicely with it.
+# Creates a fake build environment.
#
# In the build environment initialisation part, the following symbolic links are
# created (to not copy files over):
@@ -645,12 +651,7 @@ unset -f _ngx_mod_set_test_env
# For additional information of what resides under linked paths, see the
# nginx.eclass source, namely the nginx_src_install() function.
#
-# The second part of the function patches module's initialisation code so that
-# any module's preprocessor definitions appear in the separate
-# '__ngx_gentoo_mod_config.h' file inside the 'build' directory. This function
-# also makes module's "config" script clear whatever content
-# build/ngx_auto_config.h may have at the time of invocation. Then,
-# default_src_prepare() is called.
+# In the end, default_src_prepare() is called.
nginx-module_src_prepare() {
debug-print-function "${FUNCNAME[0]}" "$@"
@@ -665,45 +666,54 @@ nginx-module_src_prepare() {
popd >/dev/null || die "popd failed"
eend 0
- pushd "${S}/${NGINX_MOD_CONFIG_DIR}" >/dev/null ||
- die "pushd failed"
-
- ebegin "Patching module's config"
- # Since NGINX does not guarantee ABI or API stability, we utilise
- # preprocessor macros that were used to compile NGINX itself, to build third
- # party modules. As such, we do not want for the dummy preprocessor macros
- # produced by NGINX build system during module compilation to leak into the
- # building environment. However, we do need to "capture" preprocessor macros
- # set by the module itself, so we are required to somehow get these
- # separately.
- #
- # To achieve that, the following sed script inserts ': >
- # build/ngx_auto_config.h' line at the start of a module's 'config' shell
- # script which gets sourced by NGINX build system midway during
- # configuration. It has an effect of truncating the file containing NGINX
- # preprocessor macros. This results in the file containing only module's
- # macros at the end of the module's configuration.
- #
- # The following command renames the file with module's preprocessor macros
- # to __ngx_gentoo_mod_config.h to be later merged with the system NGINX
- # header into the actual header used during compilation. Due to the fact
- # that executing the config shell script is not the last thing that NGINX
- # build system does during configuration, we can not simply rename the
- # header after the whole configuration, as it may contain other preprocessor
- # macros than only the module's ones.
- sed -i -e '1i\' -e ': > build/ngx_auto_config.h' config ||
- { eend $? || die "sed failed"; }
-
- # Add one extra LF before the command in case the 'config' script does not
- # have a trailing newline already.
- printf "\n%s\n" 'mv build/ngx_auto_config.h build/__ngx_gentoo_mod_config.h' \
- >> config
- # We specifically need the $? of printf.
- # shellcheck disable=SC2320
- eend $? || die "printf failed"
-
- # Get back into the module root and apply patches.
- popd >/dev/null || die "popd failed"
+ ebegin "Determining NGINX configuration on-disk format"
+
+ if [[ -f "${_NGX_MOD_CONFIG_FLAGS_FILE}" ]]; then
+ eend 0
+ einfo "Using ./configure flags file"
+ else
+ eend 0
+ einfo "Using saved ngx_auto_{config,headers}.h headers"
+ pushd "${S}/${NGINX_MOD_CONFIG_DIR}" >/dev/null ||
+ die "pushd failed"
+
+ ebegin "Patching module's config"
+ # Since NGINX does not guarantee ABI or API stability, we utilise
+ # preprocessor macros that were used to compile NGINX itself, to build
+ # third party modules. As such, we do not want for the dummy
+ # preprocessor macros produced by NGINX build system during module
+ # compilation to leak into the building environment. However, we do need
+ # to "capture" preprocessor macros set by the module itself, so we are
+ # required to somehow get these separately.
+ #
+ # To achieve that, the following sed script inserts ': >
+ # build/ngx_auto_config.h' line at the start of a module's 'config'
+ # shell script which gets sourced by NGINX build system midway during
+ # configuration. It has an effect of truncating the file containing
+ # NGINX preprocessor macros. This results in the file containing only
+ # module's macros at the end of the module's configuration.
+ #
+ # The following command renames the file with module's preprocessor
+ # macros to __ngx_gentoo_mod_config.h to be later merged with the system
+ # NGINX header into the actual header used during compilation. Due to
+ # the fact that executing the config shell script is not the last thing
+ # that NGINX build system does during configuration, we can not simply
+ # rename the header after the whole configuration, as it may contain
+ # other preprocessor macros than only the module's ones.
+ sed -i -e '1i\' -e ': > build/ngx_auto_config.h' config ||
+ { eend $? || die "sed failed"; }
+
+ # Add one extra LF before the command in case the 'config' script does
+ # not have a trailing newline already.
+ printf "\n%s\n" 'mv build/ngx_auto_config.h build/__ngx_gentoo_mod_config.h' \
+ >> config
+ # We specifically need the $? of printf.
+ # shellcheck disable=SC2320
+ eend $? || die "printf failed"
+ # Get back into the module root and apply patches.
+ popd >/dev/null || die "popd failed"
+ fi
+
default_src_prepare
}
@@ -712,38 +722,59 @@ nginx-module_src_prepare() {
# Configures the dynamic module by calling NGINX's ./configure script.
# Custom flags can be supplied as arguments to the function, taking precedence
# over eclass's flags.
-# This assembles ngx_auto_config.h from the system ngx_auto_config.h and
-# __ngx_gentoo_mod_config.h (see nginx-module_src_prepare()), and
-# ngx_auto_headers.h from the system ngx_auto_headers.h.
+#
+# This restores ./configure flags, if the respective file is present.
+# Otherwise, this function assembles ngx_auto_config.h from the system
+# ngx_auto_config.h and __ngx_gentoo_mod_config.h (see
+# nginx-module_src_prepare()), and ngx_auto_headers.h from the system
+# ngx_auto_headers.h.
+#
# Also, sets environment variables and appends necessary libraries if
# NGINX_MOD_LINK_MODULES is set.
nginx-module_src_configure() {
debug-print-function "${FUNCNAME[0]}" "$@"
pushd "${NGINX_S}" >/dev/null || die "pushd failed"
- local ngx_mod_flags
- ngx_mod_flags=(
- --with-cc="$(tc-getCC)"
- --with-cpp="$(tc-getCPP)"
- # The '-isystem' flag is used instead of '-I', so as for the installed
- # (system) modules' headers to be of lower priority than the headers of
- # the currently built module. This only affects the modules that both
- # come with and install their own headers, e.g. ngx_devel_kit.
- --with-cc-opt="-isystem src/modules"
- --with-ld-opt="${LDFLAGS}"
- --builddir=build
+ local ngx_mod_flags=()
+ if [[ -f "${_NGX_MOD_CONFIG_FLAGS_FILE}" ]]; then
+ # Restore the stored configure flags into ngx_mod_flags.
+ mapfile -d '' ngx_mod_flags < "${_NGX_MOD_CONFIG_FLAGS_FILE}"
+
+ # When we save compilation flags, NGINX passes all the -l flags to
+ # modules too, including stuff like -lperl -lcrypt etc. I am not sure
+ # what to do with this yet so for now we just pass the following to
+ # limit unnecessary linkage.
+ ngx_mod_append_libs "$(test-flags-CC '-Wl,--as-needed')"
+ else
+ # Otherwise, just replicate a sane subset of configure flags for
+ # backwards compatibility.
+ ngx_mod_flags=(
+ --with-cc="$(tc-getCC)"
+ --with-cpp="$(tc-getCPP)"
+ --with-ld-opt="${LDFLAGS}"
+ --builddir=build
+ )
+
+ # NGINX build system adds directories under src/ to the include path based
+ # on the specified configuration flags. Since this is the branch where
+ # we do not use ./configure flags we have to add the directories to the
+ # include path manually.
+ #
+ # The src/os is added automatically by the auto/unix script and the
+ # src/modules directory is included below.
+ append-cflags "$(find -H src -mindepth 1 -type d \! \( \( -path 'src/os' -o \
+ -path 'src/modules' \) -prune \) -printf '-I %p ')"
+ fi
+
+ ngx_mod_flags+=(
--add-dynamic-module="${S}/${NGINX_MOD_CONFIG_DIR}"
)
- # NGINX build system adds directories under src/ to the include path based
- # on the specified configuration flags. Since nginx.eclass does not
- # save/restore the configuration flags, we have to add the directories to
- # the include path manually.
- # The src/os is added automatically by the auto/unix script and the
- # src/modules directory is included by the '--with-cc-opt' configuration
- # flag.
- append-cflags "$(find -H src -mindepth 1 -type d \! \( \( -path 'src/os' -o \
- -path 'src/modules' \) -prune \) -printf '-I %p ')"
+ # The '-isystem' flag is used instead of '-I', so as for the installed
+ # (system) modules' headers to be of lower priority than the headers of
+ # the currently built module. This only affects the modules that both
+ # come with and install their own headers, e.g. ngx_devel_kit.
+ append-cflags "-isystem src/modules"
# 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
@@ -771,6 +802,7 @@ nginx-module_src_configure() {
eval "local -a EXTRA_ECONF=( ${EXTRA_ECONF} )"
+ # Backwards compatibility shim for header saving setups:
# Setting the required environment variable to skip the unnecessary
# execution of certain scripts (see nginx_src_install() in nginx.eclass).
_NGINX_GENTOO_SKIP_PHASES=1 econf_ngx \
@@ -778,11 +810,14 @@ nginx-module_src_configure() {
"$@" \
"${EXTRA_ECONF[@]}"
- cat "${ESYSROOT}/usr/include/nginx/ngx_auto_config.h" \
- build/__ngx_gentoo_mod_config.h > build/ngx_auto_config.h ||
- die "cat failed"
- cp "${ESYSROOT}/usr/include/nginx/ngx_auto_headers.h" build ||
- die "cp failed"
+ # Backwards compatibility.
+ if [[ ! -f "${_NGX_MOD_CONFIG_FLAGS_FILE}" ]]; then
+ cat "${ESYSROOT}/usr/include/nginx/ngx_auto_config.h" \
+ build/__ngx_gentoo_mod_config.h > build/ngx_auto_config.h ||
+ die "cat failed"
+ cp "${ESYSROOT}/usr/include/nginx/ngx_auto_headers.h" build ||
+ die "cp failed"
+ fi
popd >/dev/null || die "popd failed"
}
diff --git a/eclass/nginx.eclass b/eclass/nginx.eclass
index 1075fa6da23f..9783f7c7fa25 100644
--- a/eclass/nginx.eclass
+++ b/eclass/nginx.eclass
@@ -237,6 +237,16 @@ esac
# In EAPI 9, the functionality is unconditionally enabled.
[[ ${EAPI} != 8 ]] && readonly NGINX_SUPPORT_MODULE_STUBS=1
+#-----> Internal variables <-----
+
+# @ECLASS_VARIABLE: _NGX_CONFIG_FLAGS_FILE
+# @INTERNAL
+# @DESCRIPTION:
+# Holds the path to the temporary copy of ./configure flags used to configure
+# NGINX. Installed to /usr/src/nginx. Used in nginx_src_configure() and
+# nginx_src_install().
+_NGX_CONFIG_FLAGS_FILE="${T}/nginx-configure-flags"
+
#-----> ebuild setup <-----
# NGINX does not guarantee ABI stability (required by dynamic modules), subslot is
@@ -673,6 +683,13 @@ nginx_src_configure() {
"$@" \
"${EXTRA_ECONF[@]}"
+ # Store the configuration flags to install to /usr/src/nginx later for
+ # module building.
+ if use modules; then
+ printf '%s\0' "${nginx_flags[@]}" "$@" "${EXTRA_ECONF[@]}" \
+ >> "${_NGX_CONFIG_FLAGS_FILE}"
+ fi
+
sed -E -i \
-e '/^\s*LIB= \\$/ d' \
-e '/^\s*INSTALLSITEMAN3DIR= \\$/ d' \
@@ -880,23 +897,10 @@ nginx_src_install() {
# Copy the build system of NGINX to /usr/src/nginx.
insinto /usr/src/nginx
doins -r auto
+ # Save the configure flags so that modules have easier time manipulating
+ # the build environment.
+ newins "${_NGX_CONFIG_FLAGS_FILE}" configure-flags
- # Disable several checks if the _NGINX_GENTOO_SKIP_PHASES variable is
- # set to a non-empty value during the invocation of ./configure script.
- # This is done since (1) these scripts do not have any effect on the
- # build process of third-party modules and (2) they considerably
- # increase configuration time.
- sed -E -i \
- 's#^\s*\. auto/(unix|summary)$# \
- [ -z "${_NGINX_GENTOO_SKIP_PHASES}" ] \&\& &#' \
- configure || die "sed failed"
-
- # The last statement in ./configure is [ -z "${_NGINX_GENTOO... ]. If
- # _NGINX_GENTOO_SKIP_PHASES is non-empty, it evaluates to false and the
- # whole ./configure script exits with a non-zero exit status. 'exit 0'
- # is appended to the end of the script to always exit with a zero exit
- # status, regardless of what the last statement evaluates to.
- echo 'exit 0' >> configure || die "echo failed"
exeinto /usr/src/nginx
doexe configure
diff --git a/www-servers/nginx/nginx-1.29.5-r1.ebuild b/www-servers/nginx/nginx-1.29.5-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.29.5-r1.ebuild
rename to www-servers/nginx/nginx-1.29.5-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.29.7-r2.ebuild b/www-servers/nginx/nginx-1.29.7-r3.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.29.7-r2.ebuild
rename to www-servers/nginx/nginx-1.29.7-r3.ebuild
diff --git a/www-servers/nginx/nginx-1.30.0-r1.ebuild b/www-servers/nginx/nginx-1.30.0-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.30.0-r1.ebuild
rename to www-servers/nginx/nginx-1.30.0-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.30.2-r1.ebuild b/www-servers/nginx/nginx-1.30.2-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.30.2-r1.ebuild
rename to www-servers/nginx/nginx-1.30.2-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.30.3-r1.ebuild b/www-servers/nginx/nginx-1.30.3-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.30.3-r1.ebuild
rename to www-servers/nginx/nginx-1.30.3-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.30.4.ebuild b/www-servers/nginx/nginx-1.30.4-r1.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.30.4.ebuild
rename to www-servers/nginx/nginx-1.30.4-r1.ebuild
diff --git a/www-servers/nginx/nginx-1.31.1-r1.ebuild b/www-servers/nginx/nginx-1.31.1-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.31.1-r1.ebuild
rename to www-servers/nginx/nginx-1.31.1-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.31.2-r1.ebuild b/www-servers/nginx/nginx-1.31.2-r2.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.31.2-r1.ebuild
rename to www-servers/nginx/nginx-1.31.2-r2.ebuild
diff --git a/www-servers/nginx/nginx-1.31.3.ebuild b/www-servers/nginx/nginx-1.31.3-r1.ebuild
similarity index 100%
rename from www-servers/nginx/nginx-1.31.3.ebuild
rename to www-servers/nginx/nginx-1.31.3-r1.ebuild
--
2.54.0