CXX = g++-13
CPPFLAGS ?=
CXXFLAGS ?= -O2
WARN = -Wall -Wextra -Wpedantic -Wconversion -Wshadow
SOURCES = restored/vanilla1.cpp restored/script.cpp restored/math.cpp
HEADERS = restored/script.h restored/utilities.inc restored/stdlib.inc restored/worklog.inc restored/remote_sql.inc restored/web_cgi.inc restored/sockets.inc restored/socket_dns.inc restored/socket_tls.inc restored/socket_foundations.inc restored/socket_udp.inc restored/websocket_protocol.inc restored/websocket.inc
LDLIBS = $(shell pkg-config --libs libcurl sqlite3 libcares openssl libmariadb odbc)
CPPFLAGS += $(shell pkg-config --cflags libcurl libcares openssl libmariadb odbc)

.PHONY: all release sanitize test test-sanitize clean
.PHONY: test-sql test-sql-sanitize test-cgi test-cgi-sanitize
.PHONY: test-stdlib test-stdlib-sanitize
all: release
release: build/vanilla1
sanitize: build/vanilla1-asan

build:
	mkdir -p build

build/vanilla1: $(SOURCES) $(HEADERS) | build
	$(CXX) $(CPPFLAGS) -std=c++17 $(WARN) $(CXXFLAGS) $(SOURCES) -o $@ $(LDLIBS)

build/vanilla1-asan: $(SOURCES) $(HEADERS) | build
	$(CXX) $(CPPFLAGS) -std=c++17 $(WARN) -O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined -fno-pie -no-pie $(SOURCES) -o $@ $(LDLIBS)

test: build/vanilla1
	python3 tests/test_stdlib.py ./build/vanilla1
	python3 tests/test.py ./build/vanilla1
	python3 tests/test_cache.py ./build/vanilla1
	VANILLA_BASELINE=./baselines/pre-utilities/vanilla1 python3 tests/test_cache.py ./build/vanilla1
	python3 tests/test_utilities.py ./build/vanilla1
	python3 tests/test_permissions.py ./build/vanilla1
	python3 tests/run_utilities_demo.py ./build/vanilla1
	python3 tests/test_worklog.py ./build/vanilla1
	python3 tests/test_sockets.py ./build/vanilla1
	python3 tests/run_sockets_demo.py ./build/vanilla1
	python3 tests/test_dns_tls.py ./build/vanilla1
	python3 tests/run_irc_demo.py ./build/vanilla1
	python3 tests/test_foundations.py ./build/vanilla1
	python3 tests/run_foundations_demos.py ./build/vanilla1
	build/ws-venv/bin/python tests/test_websockets.py ./build/vanilla1
	build/ws-venv/bin/python tests/test_websocket_limits.py ./build/vanilla1
	build/ws-venv/bin/python tests/run_websocket_dashboard.py ./build/vanilla1

test-sanitize: build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_stdlib.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_cache.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 VANILLA_BASELINE=./baselines/pre-utilities/vanilla1 python3 tests/test_cache.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_utilities.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_permissions.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/run_utilities_demo.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_worklog.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_sockets.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/run_sockets_demo.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_dns_tls.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/run_irc_demo.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_foundations.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/run_foundations_demos.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 build/ws-venv/bin/python tests/test_websockets.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 build/ws-venv/bin/python tests/test_websocket_limits.py ./build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 build/ws-venv/bin/python tests/run_websocket_dashboard.py ./build/vanilla1-asan

clean:
	rm -f build/vanilla1 build/vanilla1-asan

# Pure helpers need no external fixtures.
test-stdlib: build/vanilla1
	python3 tests/test_stdlib.py ./build/vanilla1

test-stdlib-sanitize: build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_stdlib.py ./build/vanilla1-asan

# Opt-in: provision disposable servers separately; never start them in default tests.
test-sql: build/vanilla1
	python3 tests/test_remote_sql.py ./build/vanilla1

test-sql-sanitize: build/vanilla1-asan
	ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 python3 tests/test_remote_sql.py ./build/vanilla1-asan

# Root harness drops privileges; isolated Apache binary must be extracted first.
test-cgi: build/vanilla1
	python3 tests/test_cgi.py ./build/vanilla1

test-cgi-sanitize: build/vanilla1-asan
	python3 tests/test_cgi.py ./build/vanilla1-asan
