Makefile (12098B)
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 # Parallelize the library/binary/runtime build by default: appending -j to 13 # MAKEFLAGS at the top level turns plain `make`, `make lib`, `make bin`, etc. 14 # into parallel builds without the caller passing -j. Two guards keep it 15 # scoped: 16 # - MAKELEVEL 0 only, so a recursive $(MAKE) (bootstrap/dist/rt) inherits the 17 # parent jobserver instead of re-forcing -j (which would disable the 18 # jobserver and oversubscribe cores). 19 # - skip when any requested goal is a test target: the suites are heavy and 20 # their output interleaves badly under -j, so `make test-*` stays serial. 21 # A caller's explicit `-j`/`-jN` still wins; override with `make NCPU=1 ...`. 22 NCPU ?= $(shell getconf _NPROCESSORS_ONLN 2>/dev/null || echo 4) 23 ifeq ($(MAKELEVEL),0) 24 ifeq ($(filter test%,$(MAKECMDGOALS)),) 25 MAKEFLAGS += -j$(NCPU) 26 endif 27 endif 28 29 # Build setup, in dependency order. Each include owns one concern and only 30 # reads the variables produced by the ones before it: 31 # env.mk host detection, driver/env source selection, SDK sysroot 32 # config.mk KIT_*_ENABLED component flags (mirrored from config.h) 33 # flags.mk compiler/linker flag derivation + the .build-config stamp 34 # lib_srcs.mk libkit source selection -> LIB_OBJS / LIB_DEPS 35 # driver_srcs.mk driver source selection -> DRIVER_OBJS / DRIVER_DEPS 36 # rt.mk runtime variant/source selection -> RT_OBJS_<variant> 37 include mk/env.mk 38 include mk/config.mk 39 include mk/flags.mk 40 include mk/lib_srcs.mk 41 include mk/driver_srcs.mk 42 include mk/rt.mk 43 44 LIB_AR = $(BUILD_DIR)/libkit.a 45 BIN = $(BUILD_DIR)/kit 46 KIT_DRIVER_CUSTOM_BIN ?= $(BUILD_DIR)/kit-custom 47 48 # =========================================================================== 49 # Main build sequence: objects -> archive -> binary. 50 # =========================================================================== 51 52 .PHONY: all lib bin custom-bin 53 54 all: lib bin rt 55 56 lib: $(LIB_AR) 57 58 bin: $(BIN) $(BUILD_DIR)/support/rt 59 60 custom-bin: $(KIT_DRIVER_CUSTOM_BIN) $(dir $(KIT_DRIVER_CUSTOM_BIN))support/rt 61 62 # A kit binary resolves its runtime support from <bindir>/support/rt (an 63 # `rt` symlink in a `support` dir beside the executable). This pattern rule 64 # installs that symlink for ANY directory ending in /support/rt, so an 65 # alternative build dir — or a snapshot binary copied next to its own 66 # support/ (see `perf-golden` in mk/maint.mk) — is self-contained and finds 67 # its runtime from any cwd, no in-checkout requirement. 68 %/support/rt: 69 @mkdir -p $(@D) 70 ln -sfn $(abspath rt) $@ 71 72 # Rebuild the archive from scratch (rm first): `ar rcs` only adds/updates, so 73 # recreating it ensures a removed .c file also drops its .o from the archive. 74 $(LIB_AR): $(LIB_OBJS) $(BUILD_CONFIG) 75 @mkdir -p $(dir $@) 76 @rm -f $@ 77 $(AR) rcs $@ $(LIB_OBJS) 78 79 $(BIN): $(DRIVER_OBJS) $(LIB_AR) $(BUILD_CONFIG) 80 $(CC) $(HOST_LDFLAGS) -o $@ $(DRIVER_OBJS) $(LIB_AR) $(HOST_LDLIBS) 81 82 CUSTOM_DRIVER_OBJS = $(patsubst $(BUILD_DIR)/driver/%.o,$(BUILD_DIR)/custom-driver/%.o,$(DRIVER_OBJS)) 83 CUSTOM_DRIVER_EXT_CFLAGS = $(if $(KIT_DRIVER_EXT_REGISTER),-DKIT_DRIVER_EXT_REGISTER=$(KIT_DRIVER_EXT_REGISTER)) 84 85 $(KIT_DRIVER_CUSTOM_BIN): $(CUSTOM_DRIVER_OBJS) $(LIB_AR) $(KIT_DRIVER_EXT_OBJS) $(BUILD_CONFIG) 86 @mkdir -p $(dir $@) 87 $(CC) $(HOST_LDFLAGS) -o $@ $(CUSTOM_DRIVER_OBJS) $(KIT_DRIVER_EXT_OBJS) $(LIB_AR) $(HOST_LDLIBS) 88 89 # --------------------------------------------------------------------------- 90 # Compile rules, grouped by source tree: src/ (libkit) -> lang/ (frontends) -> 91 # vendor/ -> driver/. Each tree gets its own include scope; see mk/flags.mk for 92 # the *_CFLAGS definitions and the rationale behind each tree's include set. 93 # 94 # The libkit (src/, vendor/, lang/) objects use path-flattened basenames so the 95 # `ar` member names in libkit.a are unique (see `flatobjs` in mk/lib_srcs.mk); 96 # the basename no longer matches the source, so these are generated explicit 97 # rules rather than `%`-pattern rules. The per-group compile flags are attached 98 # as a target-specific RULE_CFLAGS, not threaded through $(call) — the flag 99 # strings can contain commas (e.g. -fsanitize=address,undefined). The driver/ 100 # objects are NOT archived (they link directly), so they keep simple patterns. 101 # --------------------------------------------------------------------------- 102 103 # $(1)=source $(2)=tree root to strip $(3)=dest subdir under BUILD_DIR 104 define libkit_obj_rule 105 $(call flatobjs,$(1),$(2),$(3)): $(1) Makefile $$(BUILD_CONFIG) 106 @mkdir -p $$(@D) 107 $$(CC) $$(RULE_CFLAGS) $$(DEPFLAGS) -c $$< -o $$@ 108 endef 109 110 # --- src/: libkit core (C + asm), freestanding, hidden visibility ----------- 111 $(foreach s,$(LIB_SRCS_C_GENERAL) $(LIB_ASMS),$(eval $(call libkit_obj_rule,$(s),src,lib))) 112 $(call flatobjs,$(LIB_SRCS_C_GENERAL) $(LIB_ASMS),src,lib): RULE_CFLAGS = $(LIB_CFLAGS) 113 114 # lang_registry.c is the one libkit source that crosses into lang/*; it 115 # uses -Ilang so the frontend headers can be reached as "c/c.h" etc. 116 ifneq ($(LIB_SRCS_LANGREG),) 117 $(foreach s,$(LIB_SRCS_LANGREG),$(eval $(call libkit_obj_rule,$(s),src,lib))) 118 $(call flatobjs,$(LIB_SRCS_LANGREG),src,lib): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang -Isrc 119 endif 120 121 # --- lang/: frontends, each with its own include set ------------------------ 122 ifeq ($(KIT_LANG_CPP_ENABLED),1) 123 $(foreach s,$(LANG_CPP_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 124 $(call flatobjs,$(LANG_CPP_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/cpp 125 endif 126 127 # The C frontend includes the lexer and preprocessor headers (pp/pp.h, 128 # lex/lex.h) which now live under lang/cpp/, and cpp_support.h is the 129 # shared substrate. So lang/c objects build with -Ilang/cpp -Ilang/c. 130 ifeq ($(KIT_LANG_C_ENABLED),1) 131 $(foreach s,$(LANG_C_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 132 $(call flatobjs,$(LANG_C_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/cpp -Ilang/c 133 endif 134 135 # The Wasm frontend is the one lang/* tree that reaches internal headers: it 136 # includes "wasm/wasm.h" to share src/wasm/ (the module/encode/decode library) 137 # with the Wasm backend, so it gets -Isrc. lang/c and lang/cpp deliberately do 138 # not — they see only the public include/ surface. 139 ifeq ($(KIT_LANG_WASM_ENABLED),1) 140 $(foreach s,$(LANG_WASM_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 141 $(call flatobjs,$(LANG_WASM_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Isrc -Ilang/wasm 142 endif 143 144 ifeq ($(KIT_LANG_TOY_ENABLED),1) 145 $(foreach s,$(LANG_TOY_SRCS),$(eval $(call libkit_obj_rule,$(s),lang,lang))) 146 $(call flatobjs,$(LANG_TOY_SRCS),lang,lang): RULE_CFLAGS = $(FREESTANDING_CFLAGS) $(LIB_VISIBILITY_CFLAGS) -Iinclude -Ilang/toy 147 endif 148 149 # --- vendor/: third-party sources compiled into libkit ---------------------- 150 # Vendored third-party sources (monocypher) compiled into libkit. Same 151 # freestanding flags as the rest of the library; symbols stay hidden. 152 ifneq ($(LIB_SRCS_VENDOR),) 153 $(foreach s,$(LIB_SRCS_VENDOR),$(eval $(call libkit_obj_rule,$(s),vendor,vendor))) 154 $(call flatobjs,$(LIB_SRCS_VENDOR),vendor,vendor): RULE_CFLAGS = $(LIB_CFLAGS) 155 endif 156 157 # --- driver/: hosted CLI; env/ is the OS/libc adapter sub-tree -------------- 158 $(BUILD_DIR)/driver/%.o: driver/%.c Makefile $(BUILD_CONFIG) 159 @mkdir -p $(dir $@) 160 $(CC) $(DRIVER_CFLAGS) $(DEPFLAGS) -c $< -o $@ 161 162 # version.o carries the injected VERSION / build-id / host-triple. It depends on 163 # the dedicated version sentinel (not BUILD_CONFIG) so only this one TU rebuilds 164 # when those change. The defines append to DRIVER_CFLAGS for this target only 165 # (the pattern rule above uses $(DRIVER_CFLAGS) directly). See mk/flags.mk. 166 $(BUILD_DIR)/driver/version.o $(BUILD_DIR)/custom-driver/version.o: $(VERSION_CONFIG) 167 $(BUILD_DIR)/driver/version.o $(BUILD_DIR)/custom-driver/version.o: \ 168 DRIVER_CFLAGS += $(KIT_VERSION_DEFS) 169 170 # Generated update-channel URL + trust-anchor set. Keep it out of the public 171 # headers and attach its include path only to the one driver translation unit. 172 $(RELEASE_CONFIG_HEADER): FORCE scripts/gen_release_config.sh $(KIT_RELEASE_PUBKEYS_EFFECTIVE) 173 @sh scripts/gen_release_config.sh "$@" "$(KIT_UPDATE_INDEX_URL)" $(KIT_RELEASE_PUBKEYS_EFFECTIVE) 174 175 $(BUILD_DIR)/driver/release_key.o $(BUILD_DIR)/custom-driver/release_key.o: $(RELEASE_CONFIG_HEADER) 176 $(BUILD_DIR)/driver/release_key.o $(BUILD_DIR)/custom-driver/release_key.o: \ 177 DRIVER_CFLAGS += -I$(BUILD_DIR)/generated 178 179 $(BUILD_DIR)/driver/env/%.o: driver/env/%.c Makefile $(BUILD_CONFIG) 180 @mkdir -p $(dir $@) 181 $(CC) $(DRIVER_ENV_CFLAGS) $(DRIVER_ENV_OS_CFLAGS) $(DEPFLAGS) -c $< -o $@ 182 183 $(BUILD_DIR)/custom-driver/%.o: driver/%.c Makefile $(BUILD_CONFIG) 184 @mkdir -p $(dir $@) 185 $(CC) $(DRIVER_CFLAGS) $(CUSTOM_DRIVER_EXT_CFLAGS) $(DEPFLAGS) -c $< -o $@ 186 187 $(BUILD_DIR)/custom-driver/env/%.o: driver/env/%.c Makefile $(BUILD_CONFIG) 188 @mkdir -p $(dir $@) 189 $(CC) $(DRIVER_ENV_CFLAGS) $(DRIVER_ENV_OS_CFLAGS) $(CUSTOM_DRIVER_EXT_CFLAGS) $(DEPFLAGS) -c $< -o $@ 190 191 # =========================================================================== 192 # Runtime (libkit_rt.a): kit compiles and archives its own runtime, one 193 # variant per target. The variant table and per-variant source/flag lists come 194 # from mk/rt.mk; this section is the per-variant build rules expanded over it. 195 # =========================================================================== 196 197 RT_CC ?= $(BIN) cc 198 RT_AR ?= $(if $(filter 1,$(KIT_TOOL_AR_ENABLED)),$(BIN) ar,$(AR)) 199 RT_AS ?= $(BIN) as 200 RT_AS_COMPILE_FLAGS ?= 201 202 .PHONY: rt rt-all-targets rt-no-native-target $(addprefix rt-,$(RT_VARIANTS)) 203 204 rt: $(if $(RT_DEFAULT_VARIANTS),$(addprefix rt-,$(RT_DEFAULT_VARIANTS)),rt-no-native-target) 205 rt-all-targets: $(addprefix rt-,$(RT_VARIANTS)) 206 207 rt-no-native-target: 208 $(error unsupported native runtime target: HOST_UNAME=$(HOST_UNAME) RT_HOST_MACHINE=$(RT_HOST_MACHINE)) 209 210 define RT_VARIANT_rules 211 rt-$(1): $$(RT_BUILD_DIR)/$(1)/libkit_rt.a 212 213 # Regular (not order-only) dep on $(BIN): kit compiles and archives its own 214 # runtime, so a codegen or `ar` change in the compiler must rebuild the rt. 215 # The archive lists $(RT_OBJS) explicitly rather than $^ so the kit binary 216 # (now a regular prereq) is not itself archived. 217 # 218 # Depend on mk/rt.mk + this Makefile too: the member list (RT_*_SRCS) lives in 219 # mk/rt.mk and `ar rcs` only adds/updates members. When the list grows, an 220 # existing archive whose objects happen to be newer would otherwise never 221 # regenerate and would silently drop the new members (e.g. a missing 222 # __clear_cache breaking links). With the makefiles as prereqs, any list edit 223 # re-fires the `rm -f` + full re-archive below so the archive always matches 224 # RT_OBJS. 225 $$(RT_BUILD_DIR)/$(1)/libkit_rt.a: $$(RT_OBJS_$(1)) mk/rt.mk Makefile $$(BIN) 226 @mkdir -p $$(dir $$@) 227 @rm -f $$@ 228 $$(RT_AR) rcs $$@ $$(RT_OBJS_$(1)) 229 230 $$(RT_BUILD_DIR)/$(1)/%.s.o: rt/lib/%.s $$(BIN) 231 @mkdir -p $$(dir $$@) 232 $$(RT_AS) $$(RT_ASFLAGS_$(1)) $$(RT_AS_COMPILE_FLAGS) $$< -o $$@ 233 234 $$(RT_BUILD_DIR)/$(1)/%.S.o: rt/lib/%.S $$(BIN) 235 @mkdir -p $$(dir $$@) 236 $$(RT_AS) $$(RT_ASFLAGS_$(1)) $$(RT_AS_COMPILE_FLAGS) $$< -o $$@ 237 238 $$(RT_BUILD_DIR)/$(1)/%.o: rt/lib/% $$(BIN) 239 @mkdir -p $$(dir $$@) 240 $$(RT_CC) $$(RT_CFLAGS_$(1)) -c $$< -o $$@ 241 242 $$(RT_BUILD_DIR)/$(1)/atomic/atomic_freestanding.c.o: rt/lib/atomic/atomic_common.inc 243 endef 244 245 $(foreach variant,$(RT_VARIANTS),$(eval $(call RT_VARIANT_rules,$(variant)))) 246 247 # =========================================================================== 248 # Bootstrap, dist, and maintenance targets live in their own includes. 249 # =========================================================================== 250 include mk/bootstrap.mk 251 include mk/dist.mk 252 include mk/maint.mk 253 254 -include $(LIB_DEPS) 255 -include $(DRIVER_DEPS) 256 257 include mk/test.mk 258 # Optional: the portability test-orchestration targets (test-cross/test-selfhost/ 259 # provision). -include so a tracked-files-only ship (e.g. the freebsd/linux 260 # self-host bootstrap) that omits an as-yet-uncommitted port.mk still builds kit. 261 -include mk/port.mk