CC ?= gcc
CFLAGS = -Wall -Wextra -std=c99 -O2 -g
LDFLAGS =
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
LIB_EXT = dylib
LIB_PATH_VAR = DYLD_LIBRARY_PATH
else ifeq ($(UNAME_S),Linux)
LIB_EXT = so
LIB_PATH_VAR = LD_LIBRARY_PATH
else
$(error Unsupported platform: $(UNAME_S))
endif
SYNTA_ROOT = ../..
INCLUDE_DIR = $(SYNTA_ROOT)/include
LIB_DIR = $(SYNTA_ROOT)/target/release
LIBS = -lcsynta -lpthread -ldl -lm
INCLUDES = -I$(INCLUDE_DIR)
TESTS = test_roundtrip test_errors test_memory
TEST_BINS = $(TESTS)
all: check-lib $(TEST_BINS)
check-lib:
@if [ ! -f "$(LIB_DIR)/libcsynta.$(LIB_EXT)" ]; then \
echo "Error: Synta FFI library not found. Build it first with:"; \
echo " cd $(SYNTA_ROOT) && cargo build --release -p synta-ffi"; \
exit 1; \
fi
@cd $(LIB_DIR) && ln -sf libcsynta.$(LIB_EXT) libcsynta.$(LIB_EXT).0 2>/dev/null || true
test_roundtrip: test_roundtrip.c $(INCLUDE_DIR)/synta.h
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< -L$(LIB_DIR) $(LIBS)
test_errors: test_errors.c $(INCLUDE_DIR)/synta.h
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< -L$(LIB_DIR) $(LIBS)
test_memory: test_memory.c $(INCLUDE_DIR)/synta.h
$(CC) $(CFLAGS) $(INCLUDES) -o $@ $< -L$(LIB_DIR) $(LIBS)
test: all
@echo "=== Running test_roundtrip ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_roundtrip || exit 1
@echo ""
@echo "=== Running test_errors ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_errors || exit 1
@echo ""
@echo "=== Running test_memory ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_memory || exit 1
@echo ""
@echo "=== All tests passed! ==="
valgrind: all
@echo "=== Valgrind: test_roundtrip ==="
$(LIB_PATH_VAR)=$(LIB_DIR) valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./test_roundtrip
@echo ""
@echo "=== Valgrind: test_errors ==="
$(LIB_PATH_VAR)=$(LIB_DIR) valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./test_errors
@echo ""
@echo "=== Valgrind: test_memory ==="
$(LIB_PATH_VAR)=$(LIB_DIR) valgrind --leak-check=full --show-leak-kinds=all --error-exitcode=1 ./test_memory
@echo ""
@echo "=== Valgrind: All tests passed with no leaks! ==="
asan: CFLAGS += -fsanitize=address -fno-omit-frame-pointer
asan: LDFLAGS += -fsanitize=address
asan: clean all
@echo "=== ASAN: test_roundtrip ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_roundtrip || exit 1
@echo ""
@echo "=== ASAN: test_errors ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_errors || exit 1
@echo ""
@echo "=== ASAN: test_memory ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_memory || exit 1
@echo ""
@echo "=== ASAN: All tests passed! ==="
ubsan: CFLAGS += -fsanitize=undefined -fno-omit-frame-pointer
ubsan: LDFLAGS += -fsanitize=undefined
ubsan: clean all
@echo "=== UBSAN: test_roundtrip ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_roundtrip || exit 1
@echo ""
@echo "=== UBSAN: test_errors ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_errors || exit 1
@echo ""
@echo "=== UBSAN: test_memory ==="
$(LIB_PATH_VAR)=$(LIB_DIR) ./test_memory || exit 1
@echo ""
@echo "=== UBSAN: All tests passed! ==="
clean:
rm -f $(TEST_BINS)
.PHONY: all check-lib test valgrind asan ubsan clean