include make/targets.mk

UNAME_S ?= $(shell uname -s)

SECTION_GC_LDFLAGS ?=
ifeq ($(UNAME_S),Darwin)
SECTION_GC_LDFLAGS := -Wl,-dead_strip
else
SECTION_GC_LDFLAGS := -Wl,--gc-sections
endif

CLANG ?= clang
SANITIZER_FLAGS ?= -O1 -fno-omit-frame-pointer -fsanitize=address,undefined
ASAN_OPTIONS_BASE ?= abort_on_error=1
ifeq ($(UNAME_S),Linux)
ASAN_OPTIONS_BASE := $(strip $(ASAN_OPTIONS_BASE))
ifeq ($(ASAN_OPTIONS_BASE),)
ASAN_OPTIONS_BASE := detect_leaks=1
else
ASAN_OPTIONS_BASE := $(ASAN_OPTIONS_BASE):detect_leaks=1
endif
endif
SANITIZER_ENV ?= ASAN_OPTIONS=$(ASAN_OPTIONS_BASE) UBSAN_OPTIONS=print_stacktrace=1:halt_on_error=1

.PHONY: unit unit-smoke unit-clang-smoke unit-sanitize-smoke $(addprefix unit-,$(UNIT_NAMES)) integration-c integration-nginx e2e unit-coverage clean

build/unit build/integration build/generated:
	@mkdir -p $@

# Unit test build rule.  The case statement selects per-target flags:
#   streaming_impl  - full streaming pipeline; needs NGINX src headers, nginx_stubs,
#                      Rust FFI headers, streaming enabled, and -lz for decomp.
#   config_handlers_impl / config_core_impl - config-layer unit tests; need
#                      nginx_stubs for NGINX API redefinitions and -ffunction-sections
#                      for dead-code elimination of unused stubs.
#   dynconf_impl     - dynamic config hot-reload; needs nginx_stubs for
#                      NGINX API redefinitions, streaming enabled, and
#                      -ffunction-sections for dead-code elimination.
build/unit/%: unit/%_test.c include/test_common.h include/test_metrics_snapshot.h | build/unit build/generated
	@extra_srcs=""; \
	extra_cflags=""; \
	extra_ldflags=""; \
	case "$*" in \
	  headers) extra_srcs="helpers/headers_standalone.c" ;; \
	  header_compile|reason_code|error_impl|error_classification|reason_code_ffi|diagnostics_accessors|diagnostics_production|header_plan_apply) extra_cflags="-I../src -Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED" ;; \
	  ffi_layout_check) extra_cflags="-I../src -Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED" ;; \
	  gzip_deflate_decompression|decompression_production) extra_cflags="-I../src -Iinclude/nginx_stubs -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS) -lz" ;; \
	  streaming_decomp) extra_cflags="-I../src -Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED"; extra_ldflags="-lz" ;; \
	  streaming) extra_cflags="-DMARKDOWN_STREAMING_ENABLED" ;; \
	  streaming_impl) extra_cflags="-I../src -Iinclude/nginx_stubs -I../../rust-converter/include -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS) -lz" ;; \
	  conversion_impl_base_url) extra_cflags="-Iinclude/nginx_stubs -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  config_handlers_impl) extra_cflags="-Iinclude/nginx_stubs -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  eligibility_impl) extra_cflags="-Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  config_core_impl) extra_cflags="-Iinclude/nginx_stubs -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  v070_default_values) extra_cflags="-Iinclude/nginx_stubs -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  dynconf_impl) extra_cflags="-Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  dynconf_snapshot) extra_cflags="-Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  effective_conf) extra_cflags="-Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	  prometheus_renderer) extra_cflags="-DMARKDOWN_STREAMING_ENABLED" ;; \
	  prometheus_per_path) extra_cflags="-DMARKDOWN_STREAMING_ENABLED" ;; \
	  accept_production|auth_production|conditional_production) extra_cflags="-I../src -Iinclude/nginx_stubs -DMARKDOWN_STREAMING_ENABLED -ffunction-sections" ; extra_ldflags="$(SECTION_GC_LDFLAGS)" ;; \
	esac; \
	$(CC) $(CFLAGS_COMMON) $(LDFLAGS_COMMON) $$extra_cflags -o "$@" "$<" $$extra_srcs $$extra_ldflags

unit: $(UNIT_BINS)
	@set -e; \
	for t in $(UNIT_BINS); do \
	  echo "Running $$t"; \
	  "$$t"; \
	done

# fast smoke subset used by top-level make test
unit-smoke: build/unit/body_filter build/unit/eligibility build/unit/headers
	@build/unit/body_filter
	@build/unit/eligibility
	@build/unit/headers

unit-clang-smoke:
	@$(MAKE) clean
	@$(MAKE) unit-smoke CC=$(CLANG)

unit-sanitize-smoke:
	@$(MAKE) clean
	@$(SANITIZER_ENV) $(MAKE) unit-smoke \
		CC=$(CLANG) \
		CFLAGS_COMMON="-Wall -Wextra -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -g $(SANITIZER_FLAGS) -std=$(CSTD) -Iinclude" \
		LDFLAGS_COMMON="$(SANITIZER_FLAGS)"

$(addprefix unit-,$(UNIT_NAMES)): unit-%: build/unit/%
	@"$<"

$(INTEGRATION_C_BIN): integration/nginx_runtime_integration_test.c include/test_common.h | build/integration
	$(CC) $(CFLAGS_COMMON) -o "$@" "$<"

integration-c: $(INTEGRATION_C_BIN)
	@"$(INTEGRATION_C_BIN)"

integration-nginx:
	@bash integration/run_integration_tests.sh

e2e:
	@bash ../../../tools/e2e/run_e2e_suite.sh

# ── Coverage target ─────────────────────────────────────────────────
# Rebuild all unit tests with gcov instrumentation, run them, and
# collect an lcov report.  The output directory is passed via COV_DIR
# (default: build/coverage).
COV_DIR ?= build/coverage

unit-coverage:
	@$(MAKE) clean
	@$(MAKE) unit \
		CFLAGS_COMMON="-Wall -Wextra -Werror=implicit-function-declaration -Werror=incompatible-pointer-types -g --coverage -std=$(CSTD) -Iinclude" \
		LDFLAGS_COMMON="--coverage"
	@mkdir -p $(COV_DIR)
	lcov --capture --directory build/unit --output-file $(COV_DIR)/raw.lcov \
		--rc branch_coverage=1 --rc geninfo_unexecuted_blocks=1 --ignore-errors inconsistent
	lcov --remove $(COV_DIR)/raw.lcov '*/tests/*' '/usr/*' \
		--output-file $(COV_DIR)/c-coverage.lcov \
		--rc branch_coverage=1 --rc geninfo_unexecuted_blocks=1 --ignore-errors unused --ignore-errors inconsistent
	@rm -f $(COV_DIR)/raw.lcov
	@echo "C coverage report: $(COV_DIR)/c-coverage.lcov"

clean:
	rm -rf build
