Skip to content

Commit f1e70e9

Browse files
committed
makefile refactor
1 parent 71d4b8a commit f1e70e9

File tree

1 file changed

+134
-106
lines changed

1 file changed

+134
-106
lines changed

Makefile

Lines changed: 134 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,132 +1,160 @@
1-
# Makefile
1+
# Makefile for SQLite Sync Extension
2+
# Supports compilation for Linux, macOS, Windows, Android and iOS
23

3-
# Compiler and flags
4-
CC = gcc
5-
NO_COVERAGE_FLAGS = -Wall -Wextra -Wno-unused-parameter -I$(SRC_DIR) -I$(TEST_DIR) -I$(SQLITE_DIR) -I$(CURL_DIR)
6-
CFLAGS = $(NO_COVERAGE_FLAGS) -DCLOUDSYNC_OMIT_NETWORK=1 -DCLOUDSYNC_OMIT_PRINT_RESULT=1 -fprofile-arcs -ftest-coverage
7-
EXTENSION_FLAGS = $(NO_COVERAGE_FLAGS) -O3 -fPIC
8-
9-
ifeq ($(shell uname -s),Darwin)
10-
CONFIG_DARWIN=y
11-
else ifeq ($(OS),Windows_NT)
12-
CONFIG_WINDOWS=y
4+
# Set default platform if not specified
5+
ifeq ($(OS),Windows_NT)
6+
PLATFORM := windows
137
else
14-
CONFIG_LINUX=y
15-
endif
16-
17-
ifdef CONFIG_DARWIN
18-
LOADABLE_EXTENSION=dylib
19-
endif
20-
21-
ifdef CONFIG_LINUX
22-
LOADABLE_EXTENSION=so
23-
CFLAGS += -lm
24-
endif
25-
26-
ifdef CONFIG_WINDOWS
27-
LOADABLE_EXTENSION=dll
8+
UNAME_S := $(shell uname -s)
9+
ifeq ($(UNAME_S),Darwin)
10+
PLATFORM := macos
11+
else
12+
PLATFORM := linux
13+
endif
2814
endif
2915

16+
# Compiler and flags
17+
CC = gcc
18+
CFLAGS = -Wall -Wextra -Wno-unused-parameter -I$(SRC_DIR) -I$(SQLITE_DIR) -I$(CURL_DIR)
19+
TEST_FLAGS = $(CFLAGS) -DSQLITE_CORE -DCLOUDSYNC_UNITTEST -DCLOUDSYNC_OMIT_NETWORK -DCLOUDSYNC_OMIT_PRINT_RESULT -fprofile-arcs -ftest-coverage
20+
EXTENSION_FLAGS = $(CFLAGS) -O3 -fPIC
3021
LDFLAGS = -lcurl
22+
COVERAGE = false
3123

32-
# setting the -lgcov flag on macOS leads to a linker error
33-
ifeq ($(shell uname), Linux)
34-
LDFLAGS += -lgcov
35-
DYLIB_LDFLAGS =
36-
else
37-
LDFLAGS +=
38-
DYLIB_LDFLAGS = -dynamiclib
39-
endif
40-
41-
# Directories and files
24+
# Directories
4225
SRC_DIR = src
26+
DIST_DIR = dist
4327
TEST_DIR = test
4428
SQLITE_DIR = sqlite
45-
OBJ_DIR = obj
46-
CURL_DIR = network/curl/macos
29+
VPATH = $(SRC_DIR):$(SQLITE_DIR):$(TEST_DIR)
30+
BUILD_RELEASE = build/release
31+
BUILD_TEST = build/test
32+
BUILD_DIRS = $(BUILD_TEST) $(BUILD_RELEASE)
33+
CURL_DIR = network/curl/$(PLATFORM)
4734
COV_DIR = coverage
48-
CUSTOM_CSS = $(TEST_DIR)/sqlitecloud.css
49-
TARGET_PREFIX=dist
50-
51-
TARGET_NAME=cloudsync
52-
TARGET_LOADABLE=$(TARGET_PREFIX)/$(TARGET_NAME).$(LOADABLE_EXTENSION)
53-
TARGET_STATIC=$(TARGET_PREFIX)/libsqlite_$(TARGET_NAME)0.a
54-
TARGET_STATIC_H=$(TARGET_PREFIX)/sqlite-$(TARGET_NAME).h
55-
TARGET_CLI=$(TARGET_PREFIX)/sqlite3
35+
CUSTOM_CSS = $(TEST_DIR)/sqliteai.css
5636

5737
# Files and objects
58-
LIB_HEADERS = $(wildcard $(SRC_DIR)/*.h) $(wildcard $(SQLITE_DIR)/*.h)
59-
SRC_FILES = $(filter-out $(SQLITE_DIR)/sqlite3.c $(TEST_DIR)/unittest.c $(SRC_DIR)/lz4.c, $(wildcard $(SRC_DIR)/*.c) $(wildcard $(TEST_DIR)/*.c) $(wildcard $(SQLITE_DIR)/*.c))
60-
LIB_OBJ_FILES = $(patsubst %.c, $(TARGET_PREFIX)/$(OBJ_DIR)/%.o, $(notdir $(SRC_FILES)))
61-
LIB_SQLITE_OBJ = $(TARGET_PREFIX)/$(OBJ_DIR)/sqlite3.o
38+
ifeq ($(PLATFORM),windows)
39+
TEST_TARGET := $(DIST_DIR)/test.exe
40+
else
41+
TEST_TARGET := $(DIST_DIR)/test
42+
endif
43+
SRC_FILES = $(wildcard $(SRC_DIR)/*.c)
44+
TEST_FILES = $(SRC_FILES) $(wildcard $(TEST_DIR)/*.c) $(wildcard $(SQLITE_DIR)/*.c)
45+
RELEASE_OBJ = $(patsubst %.c, $(BUILD_RELEASE)/%.o, $(notdir $(SRC_FILES)))
46+
TEST_OBJ = $(patsubst %.c, $(BUILD_TEST)/%.o, $(notdir $(TEST_FILES)))
47+
COV_FILES = $(filter-out $(SRC_DIR)/lz4.c $(SRC_DIR)/network.c, $(SRC_FILES))
48+
49+
# Platform-specific settings
50+
ifeq ($(PLATFORM),windows)
51+
TARGET := $(DIST_DIR)/cloudsync.dll
52+
LDFLAGS += -shared
53+
# Create .def file for Windows
54+
DEF_FILE := $(BUILD_RELEASE)/cloudsync.def
55+
else ifeq ($(PLATFORM),macos)
56+
TARGET := $(DIST_DIR)/cloudsync.dylib
57+
LDFLAGS += -dynamiclib -undefined dynamic_lookup
58+
# macOS-specific flags
59+
CFLAGS += -arch x86_64 -arch arm64
60+
else ifeq ($(PLATFORM),android)
61+
# Use Android NDK's Clang compiler, the user should set the CC
62+
# example CC=$ANDROID_NDK/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang
63+
ifeq ($(filter %-clang,$(CC)),)
64+
$(error "CC must be set to the Android NDK's Clang compiler")
65+
endif
66+
TARGET := $(DIST_DIR)/cloudsync.so
67+
LDFLAGS += -shared -lm
68+
# Android-specific flags
69+
CFLAGS += -D__ANDROID__
70+
else ifeq ($(PLATFORM),ios)
71+
TARGET := $(DIST_DIR)/cloudsync.dylib
72+
SDK := -isysroot $(shell xcrun --sdk iphoneos --show-sdk-path) -miphoneos-version-min=11.0
73+
LDFLAGS += -dynamiclib $(SDK)
74+
# iOS-specific flags
75+
CFLAGS += -arch arm64 $(SDK)
76+
else ifeq ($(PLATFORM),isim)
77+
TARGET := $(DIST_DIR)/cloudsync.dylib
78+
SDK := -isysroot $(shell xcrun --sdk iphonesimulator --show-sdk-path) -miphonesimulator-version-min=11.0
79+
LDFLAGS += -dynamiclib $(SDK)
80+
# iphonesimulator-specific flags
81+
CFLAGS += -arch x86_64 -arch arm64 $(SDK)
82+
else # linux
83+
TARGET := $(DIST_DIR)/cloudsync.so
84+
LDFLAGS += -shared
85+
CFLAGS += -lm
86+
TEST_FLAGS += -lgcov
87+
endif
88+
89+
# Windows .def file generation
90+
$(DEF_FILE):
91+
ifeq ($(PLATFORM),windows)
92+
@echo "LIBRARY js.dll" > $@
93+
@echo "EXPORTS" >> $@
94+
@echo " sqlite3_js_init" >> $@
95+
@echo " sqlitejs_version" >> $@
96+
@echo " quickjs_version" >> $@
97+
endif
6298

63-
SRC_FILES = $(filter-out $(SQLITE_DIR)/sqlite3.c $(TEST_DIR)/unittest.c $(SRC_DIR)/lz4.c, $(wildcard $(SRC_DIR)/*.c) $(wildcard $(TEST_DIR)/*.c) $(wildcard $(SQLITE_DIR)/*.c))
64-
OBJ_FILES = $(patsubst %.c, $(OBJ_DIR)/%.o, $(notdir $(SRC_FILES)))
65-
LZ4_OBJ = $(OBJ_DIR)/lz4.o
66-
SQLITE_OBJ = $(OBJ_DIR)/sqlite3.o
67-
UNIT_TEST_OBJ = $(OBJ_DIR)/unittest.o
68-
HEADERS = $(wildcard $(SRC_DIR)/*.h) $(wildcard $(TEST_DIR)/*.h) $(wildcard $(SQLITE_DIR)/*.h)
99+
# Make sure the build and dist directories exist
100+
$(shell mkdir -p $(BUILD_DIRS) $(DIST_DIR))
69101

70102
# Default target
71-
extension: $(TARGET_LOADABLE)
72-
all: $(TARGET_LOADABLE)
103+
extension: $(TARGET)
104+
all: $(TARGET)
73105

74106
# Loadable library
75-
$(TARGET_LOADABLE): $(LIB_OBJ_FILES) $(LIB_SQLITE_OBJ) $(LZ4_OBJ) $(TARGET_PREFIX)
76-
$(CC) $(LIB_OBJ_FILES) $(LZ4_OBJ) $(LIB_SQLITE_OBJ) -o $@ $(LDFLAGS) $(DYLIB_LDFLAGS)
77-
78-
# Object files for the lib (with coverage flags)
79-
$(TARGET_PREFIX)/$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(LIB_HEADERS) | $(TARGET_PREFIX)/$(OBJ_DIR)
80-
$(CC) $(EXTENSION_FLAGS) -c $< -o $@
81-
$(LIB_SQLITE_OBJ): $(SQLITE_DIR)/sqlite3.c $(LIB_HEADERS) | $(TARGET_PREFIX)/$(OBJ_DIR)
82-
$(CC) $(EXTENSION_FLAGS) -c $< -o $@
83-
84-
# Object files (with coverage flags)
85-
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(HEADERS) | $(OBJ_DIR)
86-
$(CC) $(CFLAGS) -c $< -o $@
87-
88-
$(OBJ_DIR)/%.o: $(TEST_DIR)/%.c $(HEADERS) | $(OBJ_DIR)
89-
$(CC) $(CFLAGS) -c $< -o $@
90-
91-
$(OBJ_DIR)/%.o: $(SQLITE_DIR)/%.c $(HEADERS) | $(OBJ_DIR)
92-
$(CC) $(CFLAGS) -c $< -o $@
93-
94-
# Compile lz4.c without coverage flags
95-
$(LZ4_OBJ): $(SRC_DIR)/lz4.c $(HEADERS) | $(OBJ_DIR)
96-
$(CC) $(NO_COVERAGE_FLAGS) -c $< -o $@
97-
98-
# Compile sqlite3.c without coverage flags
99-
$(SQLITE_OBJ): $(SQLITE_DIR)/sqlite3.c $(HEADERS) | $(OBJ_DIR)
100-
$(CC) $(NO_COVERAGE_FLAGS) -DSQLITE_CORE=1 -c $< -o $@
101-
102-
# Compile unittest.c without coverage flags
103-
$(UNIT_TEST_OBJ): $(TEST_DIR)/unittest.c $(HEADERS) | $(OBJ_DIR)
104-
$(CC) $(CFLAGS) -c $< -o $@
105-
106-
# Create object directory if not exists
107-
$(OBJ_DIR):
108-
mkdir -p $(OBJ_DIR)
109-
$(TARGET_PREFIX)/$(OBJ_DIR):
110-
mkdir -p $(TARGET_PREFIX)/$(OBJ_DIR)
107+
$(TARGET): $(RELEASE_OBJ) $(DEF_FILE)
108+
$(CC) $(LDFLAGS) $? -o $@
109+
ifeq ($(PLATFORM),windows)
110+
# Generate import library for Windows
111+
dlltool -D $@ -d $(DEF_FILE) -l $(DIST_DIR)/js.lib
112+
endif
111113

112-
$(TARGET_PREFIX):
113-
mkdir -p $(TARGET_PREFIX)
114+
# Test executable
115+
$(TEST_TARGET): $(TEST_OBJ)
116+
$(CC) $(TEST_FLAGS) $? -o $@
114117

115-
# Build unit test executable
116-
UNIT_TEST = unittest
117-
$(UNIT_TEST): CFLAGS += -DSQLITE_CORE=1 -DCLOUDSYNC_UNITTEST=1
118-
$(UNIT_TEST): $(OBJ_FILES) $(SQLITE_OBJ) $(LZ4_OBJ) $(UNIT_TEST_OBJ)
119-
$(CC) $(CFLAGS) $(OBJ_FILES) $(LZ4_OBJ) $(SQLITE_OBJ) $(UNIT_TEST_OBJ) -o $@ $(LDFLAGS)
118+
# Object files
119+
$(BUILD_RELEASE)/%.o: %.c
120+
$(CC) $(EXTENSION_FLAGS) -c $< -o $@
121+
$(BUILD_TEST)/sqlite3.o: $(SQLITE_DIR)/sqlite3.c
122+
$(CC) $(CFLAGS) -DSQLITE_CORE=1 -c $< -o $@
123+
$(BUILD_TEST)/%.o: %.c
124+
$(CC) $(TEST_FLAGS) -c $< -o $@
120125

121126
# Run code coverage (--css-file $(CUSTOM_CSS))
122-
coverage: $(UNIT_TEST)
123-
./$(UNIT_TEST)
127+
test: $(TARGET) $(TEST_TARGET)
128+
sqlite3 ":memory:" -cmd ".bail on" ".load ./$<" "SELECT cloudsync_version();"
129+
./$(TEST_TARGET)
130+
ifneq ($(COVERAGE),false)
124131
mkdir -p $(COV_DIR)
125-
lcov --capture --directory . --output-file $(COV_DIR)/coverage.info
132+
lcov --capture --directory . --output-file $(COV_DIR)/coverage.info $(subst src, --include src,${COV_FILES})
126133
genhtml $(COV_DIR)/coverage.info --output-directory $(COV_DIR)
134+
endif
127135

128136
# Clean up generated files
129137
clean:
130-
rm -rf $(OBJ_DIR) $(UNIT_TEST) $(COV_DIR) *.gcda *.gcno *.gcov dist/*
131-
132-
.PHONY: all clean coverage extension $(DEPS)
138+
rm -rf $(BUILD_DIRS) $(DIST_DIR)/* $(COV_DIR) *.gcda *.gcno *.gcov
139+
140+
# Help message
141+
help:
142+
@echo "SQLite Sync Extension Makefile"
143+
@echo "Usage:"
144+
@echo " make [PLATFORM=platform] [target]"
145+
@echo ""
146+
@echo "Platforms:"
147+
@echo " linux (default on Linux)"
148+
@echo " macos (default on macOS)"
149+
@echo " windows (default on Windows)"
150+
@echo " android (needs CC to be set to Android NDK's Clang compiler)"
151+
@echo " ios (only on macOS)"
152+
@echo " isim (only on macOS)"
153+
@echo ""
154+
@echo "Targets:"
155+
@echo " all - Build the extension (default)"
156+
@echo " clean - Remove built files"
157+
@echo " test [COVERAGE=true] - Test the extension with optional coverage output"
158+
@echo " help - Display this help message"
159+
160+
.PHONY: all clean test extension help

0 commit comments

Comments
 (0)