CC ?= cc CFLAGS ?= -std=c99 -Wall -Wextra -O2 LDLIBS := -lm BUILD_DIR := build OBJ_DIR := $(BUILD_DIR)/obj DIST_DIR := dist DIST_IMG_DIR := $(DIST_DIR)/img DIST_I18N_DIR := $(DIST_DIR)/i18n # ---- engine ---- ENGINE_SRC_DIR := engine/src ENGINE_THIRD_PARTY := engine/third_party/astronomy/astronomy.c ENGINE_TEST_DIR := engine/tests ENGINE_I18N_DIR := engine/i18n ENGINE_SCRIPTS_DIR := engine/scripts RES_IMG_DIR := res/img # Durable copy of the user's real birth data, outside dist/ (which is # disposable - `make clean`, or just deleting the directory, wipes it). # Gitignored: see .gitignore. USER_PROPS_BACKUP := $(ENGINE_SCRIPTS_DIR)/user.properties.local # Engine logic shared by the CLI and the test binary (no main()). ENGINE_SRCS := $(ENGINE_SRC_DIR)/rng.c $(ENGINE_SRC_DIR)/tarot.c $(ENGINE_SRC_DIR)/tarot_data.c \ $(ENGINE_SRC_DIR)/astro.c $(ENGINE_SRC_DIR)/reading.c $(ENGINE_SRC_DIR)/i18n.c \ $(ENGINE_THIRD_PARTY) ENGINE_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(ENGINE_SRCS)) ENGINE_MAIN_OBJ := $(OBJ_DIR)/$(ENGINE_SRC_DIR)/main.o ENGINE_TEST_OBJ := $(OBJ_DIR)/$(ENGINE_TEST_DIR)/smoke_test.o ENGINE_BINARY := $(DIST_DIR)/deck-engine ENGINE_TEST_BINARY := $(BUILD_DIR)/smoke_test # ---- interpreter ---- # Only ever compiles this module's own sources - significance.h/ # reading_io.h reach into engine/src/ for struct/enum *definitions* # (plain #includes), but no engine/src/*.c (or the vendored Astronomy # Engine) is compiled or linked here. That's what keeps this module (and # its tests) independent of the engine's actual ephemeris/tarot-draw # implementation - see significance.c's and reading_io.c's own comments # for why each duplicates a small table instead of linking astro.c. INTERP_SRC_DIR := interpreter/src INTERP_TEST_DIR := interpreter/tests INTERP_LIB_SRCS := $(INTERP_SRC_DIR)/significance.c $(INTERP_SRC_DIR)/json.c \ $(INTERP_SRC_DIR)/reading_io.c $(INTERP_SRC_DIR)/narrative.c INTERP_LIB_OBJS := $(patsubst %.c,$(OBJ_DIR)/%.o,$(INTERP_LIB_SRCS)) INTERP_MAIN_OBJ := $(OBJ_DIR)/$(INTERP_SRC_DIR)/main.o INTERP_BINARY := $(DIST_DIR)/interpreter-cli SIGNIFICANCE_TEST_OBJ := $(OBJ_DIR)/$(INTERP_TEST_DIR)/significance_test.o JSON_TEST_OBJ := $(OBJ_DIR)/$(INTERP_TEST_DIR)/json_test.o NARRATIVE_TEST_OBJ := $(OBJ_DIR)/$(INTERP_TEST_DIR)/narrative_test.o SIGNIFICANCE_TEST_BIN := $(BUILD_DIR)/significance_test JSON_TEST_BIN := $(BUILD_DIR)/json_test NARRATIVE_TEST_BIN := $(BUILD_DIR)/narrative_test .PHONY: all test clean images i18n scripts all: $(ENGINE_BINARY) $(INTERP_BINARY) images i18n scripts $(ENGINE_BINARY): $(ENGINE_OBJS) $(ENGINE_MAIN_OBJ) @mkdir -p $(DIST_DIR) $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS) $(INTERP_BINARY): $(INTERP_LIB_OBJS) $(INTERP_MAIN_OBJ) @mkdir -p $(DIST_DIR) $(CC) $(CFLAGS) -o $@ $^ # The HTML report expects card art at img/ next to deck-engine, so # every build refreshes a copy alongside it (cheap: 22 small JPEGs). images: @mkdir -p $(DIST_IMG_DIR) cp $(RES_IMG_DIR)/*.jpeg $(DIST_IMG_DIR)/ # deck-engine expects translation files at i18n/.lang next to it # (default --i18n-dir), so every build refreshes a copy alongside it, # same as images/. Add a new language by dropping another .lang # file into engine/i18n/ - no code or Makefile change needed. i18n: @mkdir -p $(DIST_I18N_DIR) cp $(ENGINE_I18N_DIR)/*.lang $(DIST_I18N_DIR)/ # run-engine.sh/run-interpreter.sh are refreshed every build. # # user.properties is backed up/restored across dist/ wipes rather than # just "seeded once": if dist/user.properties exists and looks filled in # (no leftover YOUR_... placeholder), it's copied out to # USER_PROPS_BACKUP; otherwise, if that backup exists (e.g. dist/ was # just deleted), it's copied back in; otherwise (genuinely first run) # dist/user.properties is seeded from the placeholder template, same as # before. scripts: @mkdir -p $(DIST_DIR) cp $(ENGINE_SCRIPTS_DIR)/run-engine.sh $(DIST_DIR)/run-engine.sh chmod +x $(DIST_DIR)/run-engine.sh cp $(ENGINE_SCRIPTS_DIR)/run-interpreter.sh $(DIST_DIR)/run-interpreter.sh chmod +x $(DIST_DIR)/run-interpreter.sh @if [ -f $(DIST_DIR)/user.properties ] && ! grep -q 'YOUR_' $(DIST_DIR)/user.properties; then \ cp $(DIST_DIR)/user.properties $(USER_PROPS_BACKUP); \ elif [ -f $(USER_PROPS_BACKUP) ]; then \ cp $(USER_PROPS_BACKUP) $(DIST_DIR)/user.properties; \ elif [ ! -f $(DIST_DIR)/user.properties ]; then \ cp $(ENGINE_SCRIPTS_DIR)/user.properties.template $(DIST_DIR)/user.properties; \ fi test: $(ENGINE_TEST_BINARY) $(SIGNIFICANCE_TEST_BIN) $(JSON_TEST_BIN) $(NARRATIVE_TEST_BIN) ./$(ENGINE_TEST_BINARY) ./$(SIGNIFICANCE_TEST_BIN) ./$(JSON_TEST_BIN) ./$(NARRATIVE_TEST_BIN) $(ENGINE_TEST_BINARY): $(ENGINE_OBJS) $(ENGINE_TEST_OBJ) $(CC) $(CFLAGS) -o $@ $^ $(LDLIBS) $(SIGNIFICANCE_TEST_BIN): $(OBJ_DIR)/$(INTERP_SRC_DIR)/significance.o $(SIGNIFICANCE_TEST_OBJ) $(CC) $(CFLAGS) -o $@ $^ $(JSON_TEST_BIN): $(OBJ_DIR)/$(INTERP_SRC_DIR)/json.o $(OBJ_DIR)/$(INTERP_SRC_DIR)/reading_io.o $(JSON_TEST_OBJ) $(CC) $(CFLAGS) -o $@ $^ $(NARRATIVE_TEST_BIN): $(OBJ_DIR)/$(INTERP_SRC_DIR)/narrative.o $(NARRATIVE_TEST_OBJ) $(CC) $(CFLAGS) -o $@ $^ $(OBJ_DIR)/%.o: %.c @mkdir -p $(dir $@) $(CC) $(CFLAGS) -c -o $@ $< clean: rm -rf $(BUILD_DIR) $(ENGINE_BINARY) $(INTERP_BINARY) $(DIST_IMG_DIR) $(DIST_I18N_DIR) \ $(DIST_DIR)/run-engine.sh $(DIST_DIR)/run-interpreter.sh # user.properties holds the user's own data - never removed by clean.