Introduces a VERSION variable in the top-level Makefile as the authoritative source for the module's reported version. A new version-header target writes src/version.h only when the content would change, so no-op rebuilds don't rewrite the file. The C source #includes that header in place of a hardcoded #define; the user-guide's install example is wildcarded (libnginx-mod-http-ipng-stats_*_amd64.deb) so it doesn't drift. The design doc still references v0.2.0 by name — operators read it as a point-in-time description, not a moving target. debian/changelog keeps its own 0.2.0-1 entry because dpkg reads the package version from there directly; the e2e test is updated to match the JSON schema bump to 2. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
178 lines
6.8 KiB
Makefile
178 lines
6.8 KiB
Makefile
# SPDX-License-Identifier: Apache-2.0
|
|
# Makefile for nginx-ipng-stats-plugin
|
|
#
|
|
# Targets:
|
|
# build - build ngx_http_ipng_stats_module.so out-of-tree.
|
|
# pkg-deb - build a .deb via dpkg-buildpackage for the current release.
|
|
# robot-test - build .deb, then run Robot Framework end-to-end tests
|
|
# in containerlab (requires docker + containerlab).
|
|
# install-deps - install build and test dependencies via apt.
|
|
# clean - remove build artifacts and the fetched nginx source tree.
|
|
# help - print this help.
|
|
#
|
|
# Overridable variables:
|
|
# NGINX_SRC - path to an unpacked nginx source tree. If unset, the
|
|
# `build` target will apt-source one into ./build/nginx-src.
|
|
|
|
MODULE_NAME := ngx_http_ipng_stats_module
|
|
MODULE_DIR := $(CURDIR)
|
|
BUILD_DIR := $(CURDIR)/build
|
|
|
|
# Single source of truth for the module version. When cutting a release,
|
|
# bump this AND add a matching top entry to debian/changelog — dpkg reads
|
|
# the package version from there directly. The C code picks up VERSION
|
|
# via the generated src/version.h (written by the version-header target
|
|
# below and depended on by the module build).
|
|
VERSION := 0.2.0
|
|
|
|
NGINX_SRC ?=
|
|
|
|
.PHONY: help build pkg-deb robot-test install-deps clean fetch-nginx-src version-header
|
|
|
|
TEST ?= tests/
|
|
|
|
help:
|
|
@echo "nginx-ipng-stats-plugin — make targets"
|
|
@echo ""
|
|
@echo " make build Build $(MODULE_NAME).so out-of-tree."
|
|
@echo " make pkg-deb Build a Debian package via dpkg-buildpackage."
|
|
@echo " make robot-test Build .deb, then run Robot Framework e2e tests."
|
|
@echo " make install-deps Install build and test dependencies (apt)."
|
|
@echo " make clean Remove build artifacts."
|
|
@echo ""
|
|
@echo "Overridable:"
|
|
@echo " NGINX_SRC=<path> Use an existing nginx source tree."
|
|
@echo " TEST=<path> Run a specific .robot file (default: tests/)."
|
|
|
|
# ----------------------------------------------------------------------
|
|
# build: out-of-tree dynamic module build
|
|
# ----------------------------------------------------------------------
|
|
|
|
build: $(BUILD_DIR)/$(MODULE_NAME).so
|
|
@echo ""
|
|
@echo "Built: $(BUILD_DIR)/$(MODULE_NAME).so"
|
|
@echo ""
|
|
@echo "To try it locally without installing a .deb:"
|
|
@echo " sudo install -m 0644 $(BUILD_DIR)/$(MODULE_NAME).so /usr/lib/nginx/modules/"
|
|
@echo " echo 'load_module modules/$(MODULE_NAME).so;' | sudo tee /etc/nginx/modules-enabled/50-mod-http-ipng-stats.conf"
|
|
@echo " sudo nginx -t && sudo nginx -s reload"
|
|
|
|
# version-header: write src/version.h iff its contents would change. The
|
|
# target is .PHONY so it's re-evaluated every build, but the file itself
|
|
# is only touched on VERSION bumps — keeps the .so from rebuilding when
|
|
# nothing has actually changed.
|
|
version-header:
|
|
@NEW='#define NGX_HTTP_IPNG_STATS_VERSION "$(VERSION)"'; \
|
|
if [ ! -f $(MODULE_DIR)/src/version.h ] \
|
|
|| [ "$$NEW" != "$$(cat $(MODULE_DIR)/src/version.h)" ]; then \
|
|
echo "Generating src/version.h (VERSION=$(VERSION))"; \
|
|
echo "$$NEW" > $(MODULE_DIR)/src/version.h; \
|
|
fi
|
|
|
|
$(BUILD_DIR)/$(MODULE_NAME).so: version-header fetch-nginx-src
|
|
@set -e; \
|
|
if [ -z "$(NGINX_SRC)" ]; then \
|
|
NGX_SRC="$(BUILD_DIR)/nginx-src"; \
|
|
else \
|
|
NGX_SRC="$(NGINX_SRC)"; \
|
|
fi; \
|
|
echo "Configuring nginx in $$NGX_SRC against module at $(MODULE_DIR)"; \
|
|
cd "$$NGX_SRC" && ./configure --with-compat --add-dynamic-module=$(MODULE_DIR); \
|
|
echo "Building module"; \
|
|
$(MAKE) -C "$$NGX_SRC" -f objs/Makefile modules; \
|
|
mkdir -p $(BUILD_DIR); \
|
|
cp "$$NGX_SRC/objs/$(MODULE_NAME).so" $(BUILD_DIR)/$(MODULE_NAME).so
|
|
|
|
fetch-nginx-src:
|
|
@set -e; \
|
|
if [ -n "$(NGINX_SRC)" ]; then \
|
|
echo "Using NGINX_SRC=$(NGINX_SRC)"; \
|
|
exit 0; \
|
|
fi; \
|
|
if [ -d "$(BUILD_DIR)/nginx-src" ] && [ -f "$(BUILD_DIR)/nginx-src/configure" ]; then \
|
|
echo "Reusing $(BUILD_DIR)/nginx-src"; \
|
|
exit 0; \
|
|
fi; \
|
|
mkdir -p $(BUILD_DIR); \
|
|
if [ -d /usr/share/nginx/src ] && [ -f /usr/share/nginx/src/configure ]; then \
|
|
echo "Copying /usr/share/nginx/src (from nginx-dev) to $(BUILD_DIR)/nginx-src"; \
|
|
rm -rf $(BUILD_DIR)/nginx-src; \
|
|
cp -a /usr/share/nginx/src $(BUILD_DIR)/nginx-src; \
|
|
chmod -R u+w $(BUILD_DIR)/nginx-src; \
|
|
exit 0; \
|
|
fi; \
|
|
rm -rf $(BUILD_DIR)/apt-src; \
|
|
mkdir -p $(BUILD_DIR)/apt-src; \
|
|
echo "Fetching nginx source via \`apt source nginx\` in $(BUILD_DIR)/apt-src"; \
|
|
cd $(BUILD_DIR)/apt-src && apt source nginx; \
|
|
NGX_DIR=$$(find $(BUILD_DIR)/apt-src -maxdepth 1 -type d -name 'nginx-*' | head -n1); \
|
|
if [ -z "$$NGX_DIR" ]; then \
|
|
echo "error: could not find unpacked nginx source tree under $(BUILD_DIR)/apt-src" >&2; \
|
|
exit 1; \
|
|
fi; \
|
|
rm -rf $(BUILD_DIR)/nginx-src; \
|
|
mv "$$NGX_DIR" $(BUILD_DIR)/nginx-src; \
|
|
rm -rf $(BUILD_DIR)/apt-src
|
|
|
|
# ----------------------------------------------------------------------
|
|
# pkg-deb: build a .deb
|
|
# ----------------------------------------------------------------------
|
|
|
|
pkg-deb:
|
|
dpkg-buildpackage -us -uc -b
|
|
@mkdir -p $(BUILD_DIR)
|
|
@# dpkg-buildpackage writes artifacts to ../ — relocate them into
|
|
@# $(BUILD_DIR) so everything ephemeral lives under build/.
|
|
@for f in ../libnginx-mod-http-ipng-stats*.deb \
|
|
../libnginx-mod-http-ipng-stats*.ddeb \
|
|
../nginx-ipng-stats-plugin_*.buildinfo \
|
|
../nginx-ipng-stats-plugin_*.changes; do \
|
|
if [ -f "$$f" ]; then mv -f "$$f" $(BUILD_DIR)/; fi; \
|
|
done
|
|
@echo ""
|
|
@echo "Resulting .deb(s):"
|
|
@ls -1 $(BUILD_DIR)/*.deb 2>/dev/null || true
|
|
|
|
# ----------------------------------------------------------------------
|
|
# clean
|
|
# ----------------------------------------------------------------------
|
|
|
|
# ----------------------------------------------------------------------
|
|
# robot-test: containerlab + Robot Framework end-to-end tests
|
|
# ----------------------------------------------------------------------
|
|
|
|
tests/.venv: tests/requirements.txt
|
|
python3 -m venv tests/.venv
|
|
tests/.venv/bin/pip install -q -r tests/requirements.txt
|
|
|
|
robot-test: tests/.venv
|
|
@if [ ! -f $(BUILD_DIR)/libnginx-mod-http-ipng-stats_*.deb ]; then \
|
|
echo "error: no .deb found in $(BUILD_DIR)/. Run 'make pkg-deb' first." >&2; \
|
|
exit 1; \
|
|
fi
|
|
tests/rf-run.sh docker $(TEST)
|
|
|
|
# ----------------------------------------------------------------------
|
|
# install-deps: install build and test dependencies
|
|
# ----------------------------------------------------------------------
|
|
|
|
install-deps:
|
|
sudo apt-get update -qq
|
|
sudo apt-get install -y \
|
|
nginx-dev dpkg-dev debhelper \
|
|
python3 python3-venv \
|
|
curl
|
|
@echo ""
|
|
@echo "Build dependencies installed. For 'make robot-test' you also need:"
|
|
@echo " - docker: https://docs.docker.com/engine/install/debian/"
|
|
@echo " - containerlab: https://containerlab.dev/install/"
|
|
|
|
# ----------------------------------------------------------------------
|
|
# clean
|
|
# ----------------------------------------------------------------------
|
|
|
|
clean:
|
|
rm -rf $(BUILD_DIR) tests/.venv tests/out
|
|
rm -f $(MODULE_DIR)/src/version.h
|
|
-dh_clean 2>/dev/null || true
|