CC = gcc CFLAGS = -Wall -Wextra -O3 -Isrc/include -Iinclude LDFLAGS = # Directories SRC_DIR = src BUILD_DIR = build BIN_DIR = $(BUILD_DIR)/bin LIB_DIR = $(BUILD_DIR)/lib INC_DIR = $(BUILD_DIR)/include OBJ_DIR = $(BUILD_DIR)/obj # Output names EXECUTABLE = $(BIN_DIR)/ground SHARED_LIB = $(LIB_DIR)/libgroundvm.so HEADER = $(INC_DIR)/groundvm.h # Source files LIB_SOURCES = $(filter-out $(SRC_DIR)/main.c, $(wildcard $(SRC_DIR)/*.c)) EXE_SOURCES = $(wildcard $(SRC_DIR)/*.c) # Object files LIB_OBJECTS = $(LIB_SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/lib_%.o) EXE_OBJECTS = $(EXE_SOURCES:$(SRC_DIR)/%.c=$(OBJ_DIR)/exe_%.o) # Default target: build standalone executable .PHONY: all all: executable # Build standalone executable .PHONY: executable executable: $(EXECUTABLE) # Build shared library .PHONY: library library: $(SHARED_LIB) $(HEADER) # Build both .PHONY: both both: executable library # Link executable $(EXECUTABLE): $(EXE_OBJECTS) | $(BIN_DIR) $(CC) $(EXE_OBJECTS) -o $@ $(LDFLAGS) # Build shared library $(SHARED_LIB): $(LIB_OBJECTS) | $(LIB_DIR) $(CC) -shared $(LIB_OBJECTS) -o $@ $(LDFLAGS) # Copy header for library distribution $(HEADER): include/groundvm.h | $(INC_DIR) cp $< $@ # Compile object files for executable $(OBJ_DIR)/exe_%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) $(CC) $(CFLAGS) -c $< -o $@ # Compile object files for shared library (with -fPIC) $(OBJ_DIR)/lib_%.o: $(SRC_DIR)/%.c | $(OBJ_DIR) $(CC) $(CFLAGS) -fPIC -c $< -o $@ # Create directories $(BUILD_DIR) $(BIN_DIR) $(LIB_DIR) $(INC_DIR) $(OBJ_DIR): mkdir -p $@ # Clean build artifacts .PHONY: clean clean: rm -rf $(BUILD_DIR) # Debug: print variables .PHONY: debug debug: @echo "LIB_SOURCES: $(LIB_SOURCES)" @echo "EXE_SOURCES: $(EXE_SOURCES)" @echo "LIB_OBJECTS: $(LIB_OBJECTS)" @echo "EXE_OBJECTS: $(EXE_OBJECTS)"