diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f778718 --- /dev/null +++ b/Makefile @@ -0,0 +1,138 @@ +# Root Makefile for uTun - Out-of-tree build wrapper +# This Makefile provides convenient targets for building in a separate directory +# while keeping binaries in the project root. + +# Build directory +BUILD_DIR = build + +# Detect source directory (where this Makefile is located) +SRC_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) + +# Check if build directory is configured +BUILD_CONFIGURED := $(shell test -f $(BUILD_DIR)/Makefile && echo yes || echo no) + +# Default target: build everything +.PHONY: all +all: +ifeq ($(BUILD_CONFIGURED),yes) + @$(MAKE) -C $(BUILD_DIR) all +else + @echo "Build directory not configured. Run 'make setup' first." + @exit 1 +endif + +# Setup target: create build directory and configure +.PHONY: setup +setup: + @echo "Setting up build in $(BUILD_DIR)/..." + @mkdir -p $(BUILD_DIR) + @if test ! -f $(BUILD_DIR)/Makefile; then \ + echo "Running configure..."; \ + cd $(BUILD_DIR) && $(SRC_DIR)/configure; \ + else \ + echo "Build already configured."; \ + fi + @echo "Setup complete. Run 'make' to build." + +# Reconfigure target +.PHONY: reconfigure +reconfigure: + @rm -rf $(BUILD_DIR) + @$(MAKE) setup + +# Build just the main binary (skip tests) +.PHONY: utun +utun: +ifeq ($(BUILD_CONFIGURED),yes) + @$(MAKE) -C $(BUILD_DIR)/lib + @$(MAKE) -C $(BUILD_DIR)/src + @echo "utun binary built successfully." +else + @echo "Build directory not configured. Run 'make setup' first." + @exit 1 +endif + +# Run tests (make all builds everything including tests) +.PHONY: check test +check: all +ifeq ($(BUILD_CONFIGURED),yes) + @$(MAKE) -C $(BUILD_DIR) check +else + @echo "Build directory not configured. Run 'make setup' first." + @exit 1 +endif + +test: check + +# Clean build directory +.PHONY: clean +clean: +ifeq ($(BUILD_CONFIGURED),yes) + @$(MAKE) -C $(BUILD_DIR) clean +else + @echo "Build directory not configured." +endif + +# Full clean - remove build directory and generated files +.PHONY: distclean +distclean: + @rm -rf $(BUILD_DIR) + @echo "Build directory removed." + +# Install from build directory +.PHONY: install +install: all + @$(MAKE) -C $(BUILD_DIR) install + +# Debug build setup +.PHONY: setup-debug +setup-debug: + @echo "Setting up debug build in $(BUILD_DIR)/..." + @mkdir -p $(BUILD_DIR) + cd $(BUILD_DIR) && $(SRC_DIR)/configure --enable-debug + +# Release build setup +.PHONY: setup-release +setup-release: + @echo "Setting up release build in $(BUILD_DIR)/..." + @mkdir -p $(BUILD_DIR) + cd $(BUILD_DIR) && $(SRC_DIR)/configure --disable-debug + +# Print help +.PHONY: help +help: + @echo "uTun Build System (Out-of-tree build)" + @echo "======================================" + @echo "" + @echo "Setup targets:" + @echo " setup - Configure the build directory" + @echo " setup-debug - Configure for debug build" + @echo " setup-release - Configure for release build" + @echo " reconfigure - Clean and reconfigure build" + @echo "" + @echo "Build targets:" + @echo " all - Build everything: lib, src, tests" + @echo " utun - Build only main utun binary (faster)" + @echo " check - Run all tests (builds if needed)" + @echo " test - Alias for check" + @echo " install - Install binaries" + @echo "" + @echo "Maintenance:" + @echo " clean - Clean build artifacts" + @echo " distclean - Remove build directory completely" + @echo " help - Show this help" + @echo "" + @echo "Build directory: $(BUILD_DIR)/" + @echo "Source directory: $(SRC_DIR)/" + @echo "" + @echo "Usage: make setup && make" + +# Pass through any unknown targets to the build directory if configured +.PHONY: % +%: +ifeq ($(BUILD_CONFIGURED),yes) + @$(MAKE) -C $(BUILD_DIR) $@ +else + @echo "Build directory not configured. Run 'make setup' first." + @exit 1 +endif diff --git a/Makefile.am b/Makefile.am index 9fb037e..521908d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -3,8 +3,24 @@ # This is the root Makefile.am - tests are defined in tests/Makefile.am # Basic configuration for root directory +# Order matters: lib -> src -> tests (tests depend on src objects) SUBDIRS = lib src tests -# Clean object directories from root +# Build directory for out-of-tree builds +BUILD_DIR = build + +# Custom target to run full build in separate directory +.PHONY: fullbuild +fullbuild: + @echo "Building in $(BUILD_DIR)/ directory..." + @$(MKDIR_P) $(BUILD_DIR) + @if test ! -f $(BUILD_DIR)/Makefile; then \ + echo "Running configure in $(BUILD_DIR)..."; \ + cd $(BUILD_DIR) && $(top_srcdir)/configure; \ + fi + @$(MAKE) -C $(BUILD_DIR) all + @echo "Build complete. Binaries copied to project root." + +# Clean build directory clean-local: - -rm -rf $(top_builddir)/.objs + -rm -rf $(BUILD_DIR) diff --git a/lib/Makefile.am b/lib/Makefile.am index 3b61fe6..3f670a6 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,20 +20,6 @@ libuasync_a_CFLAGS = \ -I$(top_srcdir)/src \ -I$(top_srcdir)/lib -# Object directory for shadow build artifacts -OBJDIR = $(top_builddir)/.objs/lib - -# After building, move object files to shadow directory -all-local: shadow-objects - -shadow-objects: libuasync.a - @$(MKDIR_P) $(OBJDIR) - @for obj in $(libuasync_a_OBJECTS); do \ - if test -f "$$obj"; then \ - mv -f "$$obj" $(OBJDIR)/ 2>/dev/null || true; \ - fi; \ - done - -# Clean shadow directory along with regular clean +# Clean build directory clean-local: - -rm -rf $(OBJDIR) + -rm -rf $(top_builddir)/build diff --git a/src/Makefile.am b/src/Makefile.am index 7c05551..299d277 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -61,32 +61,70 @@ else utun_LDADD = $(utun_CORE_LDADD) endif -# Object directory for shadow build artifacts -OBJDIR = $(top_builddir)/.objs/src -TINYCRYPT_OBJDIR = $(top_builddir)/.objs/tinycrypt - -# After building, move object files to shadow directory -all-local: shadow-objects - -shadow-objects: utun$(EXEEXT) - @$(MKDIR_P) $(OBJDIR) $(TINYCRYPT_OBJDIR) - @for obj in $(utun_OBJECTS); do \ - if test -f "$$obj"; then \ - case "$$obj" in \ - *lib/source/*.o) \ - base=$$(basename $$obj | sed 's/^utun-//'); \ - mv -f "$$obj" $(TINYCRYPT_OBJDIR)/"$$base" 2>/dev/null || true; \ - ;; \ - *) \ - mv -f "$$obj" $(OBJDIR)/ 2>/dev/null || true; \ - ;; \ - esac; \ - fi; \ - done - -# Clean shadow directories along with regular clean +# TinyCrypt object files (for tests that need them) +TINYCRYPT_SRCDIR = $(top_srcdir)/tinycrypt/lib/source + +TINYCRYPT_OBJS = \ + utun-aes_encrypt.o \ + utun-aes_decrypt.o \ + utun-ccm_mode.o \ + utun-cmac_mode.o \ + utun-ctr_mode.o \ + utun-ecc.o \ + utun-ecc_dh.o \ + utun-ecc_dsa.o \ + utun-sha256.o \ + utun-ecc_platform_specific.o \ + utun-utils.o + +# Rules to build TinyCrypt objects (for tests) +TINYCRYPT_CFLAGS = -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source + +utun-aes_encrypt.o: $(TINYCRYPT_SRCDIR)/aes_encrypt.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-aes_decrypt.o: $(TINYCRYPT_SRCDIR)/aes_decrypt.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ccm_mode.o: $(TINYCRYPT_SRCDIR)/ccm_mode.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-cmac_mode.o: $(TINYCRYPT_SRCDIR)/cmac_mode.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ctr_mode.o: $(TINYCRYPT_SRCDIR)/ctr_mode.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ecc.o: $(TINYCRYPT_SRCDIR)/ecc.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ecc_dh.o: $(TINYCRYPT_SRCDIR)/ecc_dh.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ecc_dsa.o: $(TINYCRYPT_SRCDIR)/ecc_dsa.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-sha256.o: $(TINYCRYPT_SRCDIR)/sha256.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-ecc_platform_specific.o: $(TINYCRYPT_SRCDIR)/ecc_platform_specific.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +utun-utils.o: $(TINYCRYPT_SRCDIR)/utils.c + $(AM_V_CC)$(COMPILE) $(TINYCRYPT_CFLAGS) -c -o $@ $< + +# Build TinyCrypt objects for tests (convenience target) +tinycrypt-objects: $(TINYCRYPT_OBJS) + +# Copy binary to project root after building +all-local: copy-to-root + +copy-to-root: utun$(EXEEXT) + @cp -f utun$(EXEEXT) $(top_srcdir)/ + +# Clean clean-local: - -rm -rf $(OBJDIR) $(TINYCRYPT_OBJDIR) + @true # Install directories install-exec-hook: diff --git a/tests/Makefile.am b/tests/Makefile.am index d0aa41e..8c977f0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,10 +1,5 @@ # Tests Makefile.am for utun - all tests with new ll_queue library -# Object directories -OBJDIR = $(top_builddir)/.objs/tests -SRC_OBJDIR = $(top_builddir)/.objs/src -TINYCRYPT_OBJDIR = $(top_builddir)/.objs/tinycrypt - # All available tests check_PROGRAMS = \ test_etcp_crypto \ @@ -33,42 +28,42 @@ AM_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/li # TinyCrypt source files TINYCRYPT_SRCDIR = $(top_srcdir)/tinycrypt/lib/source -# TinyCrypt object files (with utun- prefix as built by automake) +# TinyCrypt object files (built by src/Makefile.am with utun- prefix) TINYCRYPT_OBJS = \ - $(TINYCRYPT_OBJDIR)/utun-aes_encrypt.o \ - $(TINYCRYPT_OBJDIR)/utun-aes_decrypt.o \ - $(TINYCRYPT_OBJDIR)/utun-ccm_mode.o \ - $(TINYCRYPT_OBJDIR)/utun-cmac_mode.o \ - $(TINYCRYPT_OBJDIR)/utun-ctr_mode.o \ - $(TINYCRYPT_OBJDIR)/utun-ecc.o \ - $(TINYCRYPT_OBJDIR)/utun-ecc_dh.o \ - $(TINYCRYPT_OBJDIR)/utun-ecc_dsa.o \ - $(TINYCRYPT_OBJDIR)/utun-sha256.o \ - $(TINYCRYPT_OBJDIR)/utun-ecc_platform_specific.o \ - $(TINYCRYPT_OBJDIR)/utun-utils.o - -# Secure channel and CRC objects -SECURE_CHANNEL_OBJS = $(SRC_OBJDIR)/utun-secure_channel.o $(SRC_OBJDIR)/utun-crc32.o + $(top_builddir)/src/utun-aes_encrypt.o \ + $(top_builddir)/src/utun-aes_decrypt.o \ + $(top_builddir)/src/utun-ccm_mode.o \ + $(top_builddir)/src/utun-cmac_mode.o \ + $(top_builddir)/src/utun-ctr_mode.o \ + $(top_builddir)/src/utun-ecc.o \ + $(top_builddir)/src/utun-ecc_dh.o \ + $(top_builddir)/src/utun-ecc_dsa.o \ + $(top_builddir)/src/utun-sha256.o \ + $(top_builddir)/src/utun-ecc_platform_specific.o \ + $(top_builddir)/src/utun-utils.o + +# Secure channel and CRC objects (built in src directory) +SECURE_CHANNEL_OBJS = $(top_builddir)/src/utun-secure_channel.o $(top_builddir)/src/utun-crc32.o # ETCP core objects ETCP_CORE_OBJS = \ - $(SRC_OBJDIR)/utun-etcp.o \ - $(SRC_OBJDIR)/utun-etcp_connections.o \ - $(SRC_OBJDIR)/utun-etcp_loadbalancer.o \ - $(SRC_OBJDIR)/utun-pkt_normalizer.o \ - $(SRC_OBJDIR)/utun-etcp_api.o + $(top_builddir)/src/utun-etcp.o \ + $(top_builddir)/src/utun-etcp_connections.o \ + $(top_builddir)/src/utun-etcp_loadbalancer.o \ + $(top_builddir)/src/utun-pkt_normalizer.o \ + $(top_builddir)/src/utun-etcp_api.o # Full ETCP objects ETCP_FULL_OBJS = \ - $(SRC_OBJDIR)/utun-config_parser.o \ - $(SRC_OBJDIR)/utun-config_updater.o \ - $(SRC_OBJDIR)/utun-route_lib.o \ - $(SRC_OBJDIR)/utun-routing.o \ - $(SRC_OBJDIR)/utun-tun_if.o \ - $(SRC_OBJDIR)/utun-utun_instance.o \ + $(top_builddir)/src/utun-config_parser.o \ + $(top_builddir)/src/utun-config_updater.o \ + $(top_builddir)/src/utun-route_lib.o \ + $(top_builddir)/src/utun-routing.o \ + $(top_builddir)/src/utun-tun_if.o \ + $(top_builddir)/src/utun-utun_instance.o \ $(ETCP_CORE_OBJS) -# Common libraries +# Common libraries (libuasync.a from lib directory) COMMON_LIBS = $(top_builddir)/lib/libuasync.a -lpthread # Crypto libraries (conditional) @@ -86,30 +81,11 @@ TESTS = $(check_PROGRAMS) # Build TinyCrypt objects as a group tinycrypt-objects: $(TINYCRYPT_OBJS) -# Explicit rules for TinyCrypt objects - NOTE: no newlines in recipe -$(TINYCRYPT_OBJDIR)/utun-aes_encrypt.o: $(TINYCRYPT_SRCDIR)/aes_encrypt.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-aes_decrypt.o: $(TINYCRYPT_SRCDIR)/aes_decrypt.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-ccm_mode.o: $(TINYCRYPT_SRCDIR)/ccm_mode.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-cmac_mode.o: $(TINYCRYPT_SRCDIR)/cmac_mode.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-ctr_mode.o: $(TINYCRYPT_SRCDIR)/ctr_mode.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-ecc.o: $(TINYCRYPT_SRCDIR)/ecc.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-ecc_dh.o: $(TINYCRYPT_SRCDIR)/ecc_dh.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< +# Ensure TinyCrypt objects are built before tests that need them +$(TINYCRYPT_OBJS): + @$(MAKE) -C $(top_builddir)/src tinycrypt-objects -$(TINYCRYPT_OBJDIR)/utun-ecc_dsa.o: $(TINYCRYPT_SRCDIR)/ecc_dsa.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-sha256.o: $(TINYCRYPT_SRCDIR)/sha256.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-ecc_platform_specific.o: $(TINYCRYPT_SRCDIR)/ecc_platform_specific.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -$(TINYCRYPT_OBJDIR)/utun-utils.o: $(TINYCRYPT_SRCDIR)/utils.c ; @$(MKDIR_P) $(TINYCRYPT_OBJDIR) ; $(AM_V_CC)$(COMPILE) -c -o $@ $< - -# Test definitions with standard automake variables +# Test definitions test_etcp_crypto_SOURCES = test_etcp_crypto.c test_etcp_crypto_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source test_etcp_crypto_LDADD = $(SECURE_CHANNEL_OBJS) $(CRYPTO_LIBS) $(COMMON_LIBS) @@ -140,7 +116,7 @@ test_pkt_normalizer_etcp_LDADD = $(ETCP_FULL_OBJS) $(SECURE_CHANNEL_OBJS) $(CRYP test_pkt_normalizer_standalone_SOURCES = test_pkt_normalizer_standalone.c test_pkt_normalizer_standalone_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -I$(top_srcdir)/tinycrypt/lib/include -I$(top_srcdir)/tinycrypt/lib/source -test_pkt_normalizer_standalone_LDADD = $(SRC_OBJDIR)/utun-pkt_normalizer.o $(SRC_OBJDIR)/utun-route_lib.o $(SRC_OBJDIR)/utun-routing.o $(SRC_OBJDIR)/utun-etcp_api.o $(TINYCRYPT_OBJS) $(COMMON_LIBS) +test_pkt_normalizer_standalone_LDADD = $(top_builddir)/src/utun-pkt_normalizer.o $(top_builddir)/src/utun-route_lib.o $(top_builddir)/src/utun-routing.o $(top_builddir)/src/utun-etcp_api.o $(TINYCRYPT_OBJS) $(COMMON_LIBS) test_ll_queue_SOURCES = test_ll_queue.c test_ll_queue_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib @@ -176,7 +152,7 @@ test_debug_categories_LDADD = $(COMMON_LIBS) test_config_debug_SOURCES = test_config_debug.c test_config_debug_CFLAGS = -I$(top_srcdir)/src -I$(top_srcdir)/lib -test_config_debug_LDADD = $(SRC_OBJDIR)/utun-config_parser.o $(COMMON_LIBS) +test_config_debug_LDADD = $(top_builddir)/src/utun-config_parser.o $(COMMON_LIBS) bench_timeout_heap_SOURCES = bench_timeout_heap.c bench_timeout_heap_CFLAGS = -I$(top_srcdir)/lib @@ -189,22 +165,62 @@ bench_uasync_timeouts_LDADD = $(COMMON_LIBS) # Build tinycrypt objects before tests that need them BUILT_SOURCES = $(TINYCRYPT_BUILT) -# After building tests, move their object files to shadow directory -all-local: shadow-test-objects - -shadow-test-objects: $(check_PROGRAMS) - @$(MKDIR_P) $(OBJDIR) - @for prog in $(check_PROGRAMS); do \ - prog_obj=$${prog}_OBJECTS; \ - eval "objs=\"\$$prog_obj\""; \ - for obj in $$objs; do \ - if test -f "$$obj"; then \ - mv -f "$$obj" $(OBJDIR)/ 2>/dev/null || true; \ - fi; \ - done; \ - done +# Copy test configs to build directory (tests run from build/tests/) +all-local: copy-test-configs + +copy-test-configs: $(check_PROGRAMS) + @for conf in $(srcdir)/test_*.conf $(srcdir)/test_*.json; do \ + if test -f "$$conf"; then \ + cp -f "$$conf" "$(top_builddir)/tests/" 2>/dev/null || true; \ + fi; \ + done 2>/dev/null || true # Clean clean-local: -rm -f $(check_PROGRAMS) - -rm -rf $(OBJDIR) + -rm -f $(top_builddir)/tests/test_*.conf $(top_builddir)/tests/test_*.json 2>/dev/null || true + -rm -rf $(top_builddir)/tests/logs 2>/dev/null || true + +# Test logs directory +TEST_LOG_DIR = $(top_builddir)/tests/logs + +# Custom check target that runs tests and saves logs to files +check-local: + @$(MKDIR_P) $(TEST_LOG_DIR); \ + passed=0; \ + failed=0; \ + skipped=0; \ + total=0; \ + failed_tests=""; \ + for test in $(check_PROGRAMS); do \ + total=$$((total + 1)); \ + logfile="$(TEST_LOG_DIR)/$$test.log"; \ + if test -f "./$$test"; then \ + if "./$$test" > "$$logfile" 2>&1; then \ + echo "[PASS] $$test"; \ + passed=$$((passed + 1)); \ + else \ + echo "[FAIL] $$test (see $$logfile)"; \ + failed=$$((failed + 1)); \ + if test -z "$$failed_tests"; then \ + failed_tests="$$test"; \ + else \ + failed_tests="$$failed_tests $$test"; \ + fi; \ + fi; \ + else \ + echo "[SKIP] $$test (not built)"; \ + skipped=$$((skipped + 1)); \ + fi; \ + done; \ + echo ""; \ + echo "=========================================="; \ + echo "Test Results: $$passed passed, $$failed failed, $$skipped skipped ($$total total)"; \ + echo "Log directory: $(TEST_LOG_DIR)"; \ + echo "=========================================="; \ + if test $$failed -gt 0; then \ + echo ""; \ + echo "Failed tests: $$failed_tests"; \ + echo "Run 'cat $(TEST_LOG_DIR)/.log' to see details"; \ + exit 1; \ + fi