kit

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

commit 5716bb7b4a506bdee79e1670ba42fe9f6b8fd763
parent 99709d87da2bf980f84076321e793e5908c060b6
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Mon,  1 Jun 2026 09:36:54 -0700

make: cut Makefile-load overhead from ~507 to ~25 child processes

Two parse-time fixes that make every `make` invocation (any target) pay a
fraction of what it did before — ~2.45s down to ~0.20s of pure parse work:

- mk/config.mk: parse all CFREE_*_ENABLED flags from include/cfree/config.h
  in a single awk pass + foreach/eval, instead of one `awk` per flag (38 -> 1
  process). The header stays the single source of truth.

- Makefile: give the `$(shell find ...)` source-list variables `:=` (simple)
  flavor instead of `=` (recursive). As recursive vars they were re-expanded
  ~20x apiece through the LIB_SRCS aggregation chain, re-spawning `find` each
  time (462 finds per parse). With `:=` each find runs exactly once (21 total).

Computed LIB_SRCS / LIB_OBJS / DRIVER_SRCS / LANG_OBJS and all flag values are
byte-identical before and after, so the build output is unchanged.

Diffstat:
MMakefile | 44++++++++++++++++++++++++--------------------
Mmk/config.mk | 58++++++++--------------------------------------------------
2 files changed, 32 insertions(+), 70 deletions(-)

diff --git a/Makefile b/Makefile @@ -109,11 +109,15 @@ LIB_SRCS_NONARCH = $(LIB_SRCS_ABI_CORE) \ $(LIB_SRCS_CORE) \ $(LIB_SRCS_OBJ_CORE) -LIB_SRCS_ARCH_AA64 = $(shell find src/arch/aa64 -name '*.c' 2>/dev/null) -LIB_SRCS_ARCH_X64 = $(shell find src/arch/x64 -name '*.c' 2>/dev/null) -LIB_SRCS_ARCH_RV64 = $(shell find src/arch/rv64 -name '*.c' 2>/dev/null) -LIB_SRCS_ARCH_WASM = $(shell find src/arch/wasm -name '*.c' 2>/dev/null) -LIB_SRCS_ARCH_C_TARGET = $(shell find src/arch/c_target -name '*.c' 2>/dev/null) +# These source lists use `:=` (not `=`) so each `find` runs exactly once at +# parse time. With recursive `=`, every reference below (LIB_SRCS is rebuilt +# and re-expanded many times) would re-spawn the `find`, turning ~20 finds into +# hundreds on every `make` invocation. +LIB_SRCS_ARCH_AA64 := $(shell find src/arch/aa64 -name '*.c' 2>/dev/null) +LIB_SRCS_ARCH_X64 := $(shell find src/arch/x64 -name '*.c' 2>/dev/null) +LIB_SRCS_ARCH_RV64 := $(shell find src/arch/rv64 -name '*.c' 2>/dev/null) +LIB_SRCS_ARCH_WASM := $(shell find src/arch/wasm -name '*.c' 2>/dev/null) +LIB_SRCS_ARCH_C_TARGET := $(shell find src/arch/c_target -name '*.c' 2>/dev/null) ifneq ($(CFREE_OPT_ENABLED),1) LIB_SRCS_ARCH_AA64 := $(filter-out %/opt_coord.c,$(LIB_SRCS_ARCH_AA64)) LIB_SRCS_ARCH_X64 := $(filter-out %/opt_coord.c,$(LIB_SRCS_ARCH_X64)) @@ -145,10 +149,10 @@ ifneq ($(CFREE_INTERP_ENABLED),1) LIB_SRCS_NONARCH += src/interp/interp_stubs.c endif -LIB_SRCS_OBJ_ELF = $(shell find src/obj/elf -name '*.c' 2>/dev/null) -LIB_SRCS_OBJ_MACHO = $(shell find src/obj/macho -name '*.c' 2>/dev/null) -LIB_SRCS_OBJ_COFF = $(shell find src/obj/coff -name '*.c' 2>/dev/null) -LIB_SRCS_OBJ_WASM = $(shell find src/obj/wasm -name '*.c' 2>/dev/null) +LIB_SRCS_OBJ_ELF := $(shell find src/obj/elf -name '*.c' 2>/dev/null) +LIB_SRCS_OBJ_MACHO := $(shell find src/obj/macho -name '*.c' 2>/dev/null) +LIB_SRCS_OBJ_COFF := $(shell find src/obj/coff -name '*.c' 2>/dev/null) +LIB_SRCS_OBJ_WASM := $(shell find src/obj/wasm -name '*.c' 2>/dev/null) ifneq ($(CFREE_LINK_ENABLED),1) LIB_SRCS_OBJ_ELF := $(filter-out %/link.c %/link_dyn.c,$(LIB_SRCS_OBJ_ELF)) LIB_SRCS_OBJ_MACHO := $(filter-out %/link.c,$(LIB_SRCS_OBJ_MACHO)) @@ -164,21 +168,21 @@ LIB_SRCS_OBJ_COFF := $(filter-out %/archive.c,$(LIB_SRCS_OBJ_COFF)) LIB_SRCS_NONARCH += src/obj/archive_stubs.c endif -LIB_SRCS_OPT = $(filter-out src/opt/pass_o2.c,$(shell find src/opt -name '*.c' 2>/dev/null)) -LIB_SRCS_INTERP = $(filter-out %/interp_stubs.c,$(shell find src/interp -name '*.c' 2>/dev/null)) -LIB_SRCS_WASM_CORE = $(shell find src/wasm -name '*.c' 2>/dev/null) +LIB_SRCS_OPT := $(filter-out src/opt/pass_o2.c,$(shell find src/opt -name '*.c' 2>/dev/null)) +LIB_SRCS_INTERP := $(filter-out %/interp_stubs.c,$(shell find src/interp -name '*.c' 2>/dev/null)) +LIB_SRCS_WASM_CORE := $(shell find src/wasm -name '*.c' 2>/dev/null) LIB_SRCS_API_AR = src/api/archive.c LIB_SRCS_API_DISASM = src/api/disasm.c LIB_SRCS_API_LINK = src/api/link.c -LIB_SRCS_DEBUG = $(shell find src/debug -name '*.c' 2>/dev/null) -LIB_SRCS_DBG = $(shell find src/dbg -name '*.c' 2>/dev/null) -LIB_SRCS_EMU = $(shell find src/emu -name '*.c' 2>/dev/null) \ +LIB_SRCS_DEBUG := $(shell find src/debug -name '*.c' 2>/dev/null) +LIB_SRCS_DBG := $(shell find src/dbg -name '*.c' 2>/dev/null) +LIB_SRCS_EMU := $(shell find src/emu -name '*.c' 2>/dev/null) \ $(shell find src/os -name '*.c' 2>/dev/null) -LIB_SRCS_LINK = $(shell find src/link -name '*.c' 2>/dev/null) +LIB_SRCS_LINK := $(shell find src/link -name '*.c' 2>/dev/null) ifneq ($(CFREE_JIT_ENABLED),1) LIB_SRCS_LINK := $(filter-out %/link_jit.c,$(LIB_SRCS_LINK)) endif -LIB_SRCS_JIT_ASM = $(shell find src/jit -name '*.S' 2>/dev/null) +LIB_SRCS_JIT_ASM := $(shell find src/jit -name '*.S' 2>/dev/null) LIB_SRC_ABI_AAPCS64 = src/abi/abi_aapcs64.c LIB_SRC_ABI_APPLE_ARM64 = src/abi/abi_apple_arm64.c @@ -272,9 +276,9 @@ endif # Per-frontend source sets. Each is gated by its CFREE_LANG_*_ENABLED flag # from mk/config.mk so the matching `#if` in src/api/lang_registry.c and # the build agree on which frontends are compiled in. -LANG_CPP_SRCS = $(shell find lang/cpp -name '*.c' 2>/dev/null) -LANG_C_SRCS = $(shell find lang/c -name '*.c' 2>/dev/null) -LANG_WASM_SRCS = $(shell find lang/wasm -name '*.c' 2>/dev/null) +LANG_CPP_SRCS := $(shell find lang/cpp -name '*.c' 2>/dev/null) +LANG_C_SRCS := $(shell find lang/c -name '*.c' 2>/dev/null) +LANG_WASM_SRCS := $(shell find lang/wasm -name '*.c' 2>/dev/null) LANG_TOY_SRCS = $(wildcard lang/toy/*.c) LANG_OBJS = diff --git a/mk/config.mk b/mk/config.mk @@ -2,53 +2,11 @@ # Makefile drops the same sources that #if drops from the compile. # # Single source of truth is the header; this file just parses it. -CFG_HDR := include/cfree/config.h -cfg_flag = $(shell awk '/^\#define $(1)[ \t]/{print $$3; exit}' $(CFG_HDR)) - -CFREE_ARCH_AA64_ENABLED := $(call cfg_flag,CFREE_ARCH_AA64_ENABLED) -CFREE_ARCH_X64_ENABLED := $(call cfg_flag,CFREE_ARCH_X64_ENABLED) -CFREE_ARCH_RV64_ENABLED := $(call cfg_flag,CFREE_ARCH_RV64_ENABLED) -CFREE_ARCH_WASM_ENABLED := $(call cfg_flag,CFREE_ARCH_WASM_ENABLED) -CFREE_ARCH_C_TARGET_ENABLED := $(call cfg_flag,CFREE_ARCH_C_TARGET_ENABLED) - -CFREE_OBJ_ELF_ENABLED := $(call cfg_flag,CFREE_OBJ_ELF_ENABLED) -CFREE_OBJ_MACHO_ENABLED := $(call cfg_flag,CFREE_OBJ_MACHO_ENABLED) -CFREE_OBJ_COFF_ENABLED := $(call cfg_flag,CFREE_OBJ_COFF_ENABLED) -CFREE_OBJ_WASM_ENABLED := $(call cfg_flag,CFREE_OBJ_WASM_ENABLED) - -CFREE_LANG_ASM_ENABLED := $(call cfg_flag,CFREE_LANG_ASM_ENABLED) -CFREE_LANG_CPP_ENABLED := $(call cfg_flag,CFREE_LANG_CPP_ENABLED) -CFREE_LANG_C_ENABLED := $(call cfg_flag,CFREE_LANG_C_ENABLED) -CFREE_LANG_TOY_ENABLED := $(call cfg_flag,CFREE_LANG_TOY_ENABLED) -CFREE_LANG_WASM_ENABLED := $(call cfg_flag,CFREE_LANG_WASM_ENABLED) - -CFREE_OPT_ENABLED := $(call cfg_flag,CFREE_OPT_ENABLED) - -CFREE_AR_ENABLED := $(call cfg_flag,CFREE_AR_ENABLED) -CFREE_DISASM_ENABLED := $(call cfg_flag,CFREE_DISASM_ENABLED) -CFREE_DWARF_ENABLED := $(call cfg_flag,CFREE_DWARF_ENABLED) -CFREE_LINK_ENABLED := $(call cfg_flag,CFREE_LINK_ENABLED) -CFREE_JIT_ENABLED := $(call cfg_flag,CFREE_JIT_ENABLED) -CFREE_DBG_ENABLED := $(call cfg_flag,CFREE_DBG_ENABLED) -CFREE_EMU_ENABLED := $(call cfg_flag,CFREE_EMU_ENABLED) -CFREE_INTERP_ENABLED := $(call cfg_flag,CFREE_INTERP_ENABLED) - -CFREE_TOOL_CC_ENABLED := $(call cfg_flag,CFREE_TOOL_CC_ENABLED) -CFREE_TOOL_CHECK_ENABLED := $(call cfg_flag,CFREE_TOOL_CHECK_ENABLED) -CFREE_TOOL_CPP_ENABLED := $(call cfg_flag,CFREE_TOOL_CPP_ENABLED) -CFREE_TOOL_AS_ENABLED := $(call cfg_flag,CFREE_TOOL_AS_ENABLED) -CFREE_TOOL_LD_ENABLED := $(call cfg_flag,CFREE_TOOL_LD_ENABLED) -CFREE_TOOL_AR_ENABLED := $(call cfg_flag,CFREE_TOOL_AR_ENABLED) -CFREE_TOOL_RANLIB_ENABLED := $(call cfg_flag,CFREE_TOOL_RANLIB_ENABLED) -CFREE_TOOL_STRIP_ENABLED := $(call cfg_flag,CFREE_TOOL_STRIP_ENABLED) -CFREE_TOOL_OBJCOPY_ENABLED := $(call cfg_flag,CFREE_TOOL_OBJCOPY_ENABLED) -CFREE_TOOL_OBJDUMP_ENABLED := $(call cfg_flag,CFREE_TOOL_OBJDUMP_ENABLED) -CFREE_TOOL_DBG_ENABLED := $(call cfg_flag,CFREE_TOOL_DBG_ENABLED) -CFREE_TOOL_RUN_ENABLED := $(call cfg_flag,CFREE_TOOL_RUN_ENABLED) -CFREE_TOOL_EMU_ENABLED := $(call cfg_flag,CFREE_TOOL_EMU_ENABLED) -CFREE_TOOL_NM_ENABLED := $(call cfg_flag,CFREE_TOOL_NM_ENABLED) -CFREE_TOOL_SIZE_ENABLED := $(call cfg_flag,CFREE_TOOL_SIZE_ENABLED) -CFREE_TOOL_ADDR2LINE_ENABLED := $(call cfg_flag,CFREE_TOOL_ADDR2LINE_ENABLED) -CFREE_TOOL_STRINGS_ENABLED := $(call cfg_flag,CFREE_TOOL_STRINGS_ENABLED) -CFREE_TOOL_CAS_ENABLED := $(call cfg_flag,CFREE_TOOL_CAS_ENABLED) -CFREE_TOOL_PKG_ENABLED := $(call cfg_flag,CFREE_TOOL_PKG_ENABLED) +# +# Parse every `CFREE_*_ENABLED` flag from the header in a single awk pass — one +# process for the whole file rather than one `awk` per flag — then define each +# as an identically named make variable. An absent flag stays unset/empty, +# exactly as the old per-flag lookups behaved. +CFG_HDR := include/cfree/config.h +CFG_DEFS := $(shell awk '/^\#define CFREE_[A-Z0-9_]+_ENABLED[ \t]/{print $$2"="$$3}' $(CFG_HDR)) +$(foreach kv,$(CFG_DEFS),$(eval $(kv)))