Makefile (8524B)
1 CC = clang 2 AR = ar 3 RELEASE ?= 0 4 ifeq ($(RELEASE),1) 5 BUILD_DIR ?= build/release 6 else 7 BUILD_DIR ?= build 8 endif 9 10 .DEFAULT_GOAL := all 11 12 # Build setup, in dependency order. Each include owns one concern and only 13 # reads the variables produced by the ones before it: 14 # env.mk host detection, driver/env source selection, SDK sysroot 15 # config.mk KIT_*_ENABLED component flags (mirrored from config.h) 16 # flags.mk compiler/linker flag derivation + the .build-config stamp 17 # lib_srcs.mk libkit source selection -> LIB_OBJS / LIB_DEPS 18 # driver_srcs.mk driver source selection -> DRIVER_OBJS / DRIVER_DEPS 19 # rt.mk runtime variant/source selection -> RT_OBJS_<variant> 20 include mk/env.mk 21 include mk/config.mk 22 include mk/flags.mk 23 include mk/lib_srcs.mk 24 include mk/driver_srcs.mk 25 include mk/rt.mk 26 27 LIB_AR = $(BUILD_DIR)/libkit.a 28 BIN = $(BUILD_DIR)/kit 29 30 # =========================================================================== 31 # Main build sequence: objects -> archive -> binary. 32 # =========================================================================== 33 34 .PHONY: all lib bin 35 36 all: lib bin rt 37 38 lib: $(LIB_AR) 39 40 bin: $(BIN) $(BUILD_DIR)/support/rt 41 42 $(BUILD_DIR)/support/rt: 43 @mkdir -p $(dir $@) 44 ln -sfn $(abspath rt) $@ 45 46 # Rebuild the archive from scratch (rm first): `ar rcs` only adds/updates, so 47 # recreating it ensures a removed .c file also drops its .o from the archive. 48 $(LIB_AR): $(LIB_OBJS) $(BUILD_CONFIG) 49 @mkdir -p $(dir $@) 50 @rm -f $@ 51 $(AR) rcs $@ $(LIB_OBJS) 52 53 $(BIN): $(DRIVER_OBJS) $(LIB_AR) $(BUILD_CONFIG) 54 $(CC) $(HOST_LDFLAGS) -o $@ $(DRIVER_OBJS) $(LIB_AR) $(HOST_LDLIBS) 55 56 # --------------------------------------------------------------------------- 57 # Compile rules, grouped by source tree: src/ (libkit) -> lang/ (frontends) -> 58 # vendor/ -> driver/. Each tree gets its own include scope; see mk/flags.mk for 59 # the *_CFLAGS definitions and the rationale behind each tree's include set. 60 # 61 # The libkit (src/, vendor/, lang/) objects use path-flattened basenames so the 62 # `ar` member names in libkit.a are unique (see `flatobjs` in mk/lib_srcs.mk); 63 # the basename no longer matches the source, so these are generated explicit 64 # rules rather than `%`-pattern rules. The per-group compile flags are attached 65 # as a target-specific RULE_CFLAGS, not threaded through $(call) — the flag 66 # strings can contain commas (e.g. -fsanitize=address,undefined). The driver/ 67 # objects are NOT archived (they link directly), so they keep simple patterns. 68 # --------------------------------------------------------------------------- 69 70 # $(1)=source $(2)=tree root to strip $(3)=dest subdir under BUILD_DIR 71 define libkit_obj_rule 72 $(call flatobjs,$(1),$(2),$(3)): $(1) Makefile $$(BUILD_CONFIG) 73 @mkdir -p $$(@D) 74 $$(CC) $$(RULE_CFLAGS) $$(DEPFLAGS) -c $$< -o $$@ 75 endef 76 77 # --- src/: libkit core (C + asm), freestanding, hidden visibility ----------- 78 $(foreach s,$(LIB_SRCS_C_GENERAL) $(LIB_ASMS),$(eval $(call libkit_obj_rule,$(s),src,lib))) 79 $(call flatobjs,$(LIB_SRCS_C_GENERAL) $(LIB_ASMS),src,lib): RULE_CFLAGS = $(LIB_CFLAGS) 80 81 # lang_registry.c is the one libkit source that crosses into lang/*; it 82 # uses -Ilang so the frontend headers can be reached as "c/c.h" etc. 83 ifneq ($(LIB_SRCS_LANGREG),) 84 $(foreach s,$(LIB_SRCS_LANGREG),$(eval $(call libkit_obj_rule,$(s),src,lib))) 85 $(call flatobjs,$(LIB_SRCS_LANGREG),src,lib): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang -Isrc 86 endif 87 88 # --- lang/: frontends, each with its own include set ------------------------ 89 ifeq ($(KIT_LANG_CPP_ENABLED),1) 90 $(foreach s,$(LANG_CPP_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 91 $(call flatobjs,$(LANG_CPP_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/cpp 92 endif 93 94 # The C frontend includes the lexer and preprocessor headers (pp/pp.h, 95 # lex/lex.h) which now live under lang/cpp/, and cpp_support.h is the 96 # shared substrate. So lang/c objects build with -Ilang/cpp -Ilang/c. 97 ifeq ($(KIT_LANG_C_ENABLED),1) 98 $(foreach s,$(LANG_C_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 99 $(call flatobjs,$(LANG_C_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/cpp -Ilang/c 100 endif 101 102 # The Wasm frontend is the one lang/* tree that reaches internal headers: it 103 # includes "wasm/wasm.h" to share src/wasm/ (the module/encode/decode library) 104 # with the Wasm backend, so it gets -Isrc. lang/c and lang/cpp deliberately do 105 # not — they see only the public include/ surface. 106 ifeq ($(KIT_LANG_WASM_ENABLED),1) 107 $(foreach s,$(LANG_WASM_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 108 $(call flatobjs,$(LANG_WASM_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Isrc -Ilang/wasm 109 endif 110 111 ifeq ($(KIT_LANG_TOY_ENABLED),1) 112 $(foreach s,$(LANG_TOY_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 113 $(call flatobjs,$(LANG_TOY_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/toy 114 endif 115 116 # --- vendor/: third-party sources compiled into libkit ---------------------- 117 # Vendored third-party sources (monocypher) compiled into libkit. Same 118 # freestanding flags as the rest of the library; symbols stay hidden. 119 ifneq ($(LIB_SRCS_VENDOR),) 120 $(foreach s,$(LIB_SRCS_VENDOR),$(eval $(call libkit_obj_rule,$(s),vendor,vendor))) 121 $(call flatobjs,$(LIB_SRCS_VENDOR),vendor,vendor): RULE_CFLAGS = $(LIB_CFLAGS) 122 endif 123 124 # --- driver/: hosted CLI; env/ is the OS/libc adapter sub-tree -------------- 125 $(BUILD_DIR)/driver/%.o: driver/%.c Makefile $(BUILD_CONFIG) 126 @mkdir -p $(dir $@) 127 $(CC) $(DRIVER_CFLAGS) $(DEPFLAGS) -c $< -o $@ 128 129 $(BUILD_DIR)/driver/env/%.o: driver/env/%.c Makefile $(BUILD_CONFIG) 130 @mkdir -p $(dir $@) 131 $(CC) $(DRIVER_ENV_CFLAGS) $(DRIVER_ENV_OS_CFLAGS) $(DEPFLAGS) -c $< -o $@ 132 133 # =========================================================================== 134 # Runtime (libkit_rt.a): kit compiles and archives its own runtime, one 135 # variant per target. The variant table and per-variant source/flag lists come 136 # from mk/rt.mk; this section is the per-variant build rules expanded over it. 137 # =========================================================================== 138 139 RT_CC ?= $(BIN) cc 140 RT_AR ?= $(BIN) ar 141 RT_AS ?= $(BIN) as 142 RT_AS_COMPILE_FLAGS ?= 143 144 .PHONY: rt rt-all-targets rt-no-native-target $(addprefix rt-,$(RT_VARIANTS)) 145 146 rt: $(if $(RT_DEFAULT_VARIANTS),$(addprefix rt-,$(RT_DEFAULT_VARIANTS)),rt-no-native-target) 147 rt-all-targets: $(addprefix rt-,$(RT_VARIANTS)) 148 149 rt-no-native-target: 150 $(error unsupported native runtime target: HOST_UNAME=$(HOST_UNAME) RT_HOST_MACHINE=$(RT_HOST_MACHINE)) 151 152 define RT_VARIANT_rules 153 rt-$(1): $$(RT_BUILD_DIR)/$(1)/libkit_rt.a 154 155 # Regular (not order-only) dep on $(BIN): kit compiles and archives its own 156 # runtime, so a codegen or `ar` change in the compiler must rebuild the rt. 157 # The archive lists $(RT_OBJS) explicitly rather than $^ so the kit binary 158 # (now a regular prereq) is not itself archived. 159 # 160 # Depend on mk/rt.mk + this Makefile too: the member list (RT_*_SRCS) lives in 161 # mk/rt.mk and `ar rcs` only adds/updates members. When the list grows, an 162 # existing archive whose objects happen to be newer would otherwise never 163 # regenerate and would silently drop the new members (e.g. a missing 164 # __clear_cache breaking links). With the makefiles as prereqs, any list edit 165 # re-fires the `rm -f` + full re-archive below so the archive always matches 166 # RT_OBJS. 167 $$(RT_BUILD_DIR)/$(1)/libkit_rt.a: $$(RT_OBJS_$(1)) mk/rt.mk Makefile $$(BIN) 168 @mkdir -p $$(dir $$@) 169 @rm -f $$@ 170 $$(RT_AR) rcs $$@ $$(RT_OBJS_$(1)) 171 172 $$(RT_BUILD_DIR)/$(1)/%.s.o: rt/lib/%.s $$(BIN) 173 @mkdir -p $$(dir $$@) 174 $$(RT_AS) $$(RT_ASFLAGS_$(1)) $$(RT_AS_COMPILE_FLAGS) $$< -o $$@ 175 176 $$(RT_BUILD_DIR)/$(1)/%.S.o: rt/lib/%.S $$(BIN) 177 @mkdir -p $$(dir $$@) 178 $$(RT_AS) $$(RT_ASFLAGS_$(1)) $$(RT_AS_COMPILE_FLAGS) $$< -o $$@ 179 180 $$(RT_BUILD_DIR)/$(1)/%.o: rt/lib/% $$(BIN) 181 @mkdir -p $$(dir $$@) 182 $$(RT_CC) $$(RT_CFLAGS_$(1)) -c $$< -o $$@ 183 184 $$(RT_BUILD_DIR)/$(1)/atomic/atomic_freestanding.c.o: rt/lib/atomic/atomic_common.inc 185 endef 186 187 $(foreach variant,$(RT_VARIANTS),$(eval $(call RT_VARIANT_rules,$(variant)))) 188 189 # =========================================================================== 190 # Bootstrap, dist, and maintenance targets live in their own includes. 191 # =========================================================================== 192 include mk/bootstrap.mk 193 include mk/dist.mk 194 include mk/maint.mk 195 196 -include $(LIB_DEPS) 197 -include $(DRIVER_DEPS) 198 199 include mk/test.mk