Browse Source

Build: Out-of-tree build system with separate build directory

- Build in build/ directory instead of source tree
- Main binary (utun) copied to project root
- Tests run from build/tests/ with config files copied there
- Test output redirected to build/tests/logs/*.log files
- Console shows only [PASS]/[FAIL]/[SKIP] status
- Incremental build works correctly
- make check runs all tests with summary

Changes:
- New root Makefile as wrapper for out-of-tree build
- Updated Makefile.am files for lib, src, tests
- Added tinycrypt-objects target for test dependencies
- Tests no longer clutter project root
nodeinfo-routing-update
Evgeny 2 months ago
parent
commit
15001487af
  1. 138
      Makefile
  2. 20
      Makefile.am
  3. 18
      lib/Makefile.am
  4. 88
      src/Makefile.am
  5. 160
      tests/Makefile.am

138
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

20
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)

18
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

88
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:

160
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)/<test>.log' to see details"; \
exit 1; \
fi

Loading…
Cancel
Save