kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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