From 8675a65a58345810e519c312d7349873586802a0 Mon Sep 17 00:00:00 2001 From: Thomas Walker Lynch Date: Mon, 27 Oct 2025 07:30:33 +0000 Subject: [PATCH] . --- developer/make/target_kmod.mk | 131 ++++++++++++++++----------- developer/make/target_library_CLI.mk | 49 +++++----- 2 files changed, 99 insertions(+), 81 deletions(-) diff --git a/developer/make/target_kmod.mk b/developer/make/target_kmod.mk index 7ca2fc8..03928f7 100644 --- a/developer/make/target_kmod.mk +++ b/developer/make/target_kmod.mk @@ -3,35 +3,57 @@ # version 1.4 .SUFFIXES: -.EXPORT_ALL_VARIABLES: .DELETE_ON_ERROR: -# allow overrides -KMOD_SOURCE_DIR ?= cc +#-------------------------------------------------------------------------------- +# defaults for environment variables (override from outer make/env as needed) + +# Kernel build tree, which is part of the Linux system, use running kernel if unset +KMOD_BUILD_DIR ?= -# allow cross-compile override via KDIR; else default to running kernel -KDIR ?= -BUILD_DIR ?= $(if $(KDIR),$(KDIR),/lib/modules/$(shell uname -r)/build) +# Authored source directory (single dir) +KMOD_SOURCE_DIR ?= cc -# default, then canonicalize to absolute regardless of source -OUTPUT_DIR ?= scratchpad/kmod -OUTPUT_DIR := $(abspath $(OUTPUT_DIR)) +# Extra compiler flags passed to Kbuild (e.g., -I $(KMOD_SOURCE_DIR)) +# RT uses unified header/source files +KMOD_CCFLAGS ?= -# authored basenames (without suffix) -BASE_LIST := $(patsubst %.kmod.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.kmod.c))) +# Staging/output directory for Kbuild +KMOD_OUTPUT_DIR ?= scratchpad/kmod -# optional library sources (without suffix) to include inside modules -# set KMOD_INCLUDE_LIB=0 to disable +# Include *.lib.c into modules (1=yes, 0=no) KMOD_INCLUDE_LIB ?= 1 + + + + +#-------------------------------------------------------------------------------- +# derived variables (computed from the above) + +# Canonicalize output dir +kmod_output_dir := $(abspath $(KMOD_OUTPUT_DIR)) + +# Select kernel build dir (cross or running kernel) +kmod_build_dir := $(if $(KMOD_BUILD_DIR),$(KMOD_BUILD_DIR),/lib/modules/$(shell uname -r)/build) + +# Authored basenames (without suffix) +base_list := $(patsubst %.kmod.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.kmod.c))) + +# Optional library sources (without suffix) to include inside modules ifeq ($(KMOD_INCLUDE_LIB),1) -LIB_BASE := $(patsubst %.lib.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.lib.c))) +lib_base := $(patsubst %.lib.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.lib.c))) else -LIB_BASE := +lib_base := endif -# staged sources (kept namespaced to prevent .o collisions) -ALL_KMOD_C := $(addsuffix .kmod.c,$(addprefix $(OUTPUT_DIR)/,$(BASE_LIST))) -ALL_LIB_C := $(addsuffix .lib.c,$(addprefix $(OUTPUT_DIR)/,$(LIB_BASE))) +# Staged sources (kept namespaced to prevent .o collisions) +all_kmod_c := $(addsuffix .kmod.c,$(addprefix $(kmod_output_dir)/,$(base_list))) +all_lib_c := $(addsuffix .lib.c,$(addprefix $(kmod_output_dir)/,$(lib_base))) + + + +#-------------------------------------------------------------------------------- +# targets .PHONY: usage usage: @@ -44,52 +66,53 @@ version: .PHONY: information information: @echo "KMOD_SOURCE_DIR: " $(KMOD_SOURCE_DIR) - @echo "BUILD_DIR: " $(BUILD_DIR) - @echo "OUTPUT_DIR: " $(OUTPUT_DIR) - @echo "BASE_LIST: " $(BASE_LIST) - @echo "LIB_BASE: " $(LIB_BASE) - @echo "ALL_KMOD_C: " $(ALL_KMOD_C) - @echo "ALL_LIB_C: " $(ALL_LIB_C) + @echo "kmod_build_dir: " $(kmod_build_dir) + @echo "KMOD_OUTPUT_DIR: " $(KMOD_OUTPUT_DIR) + @echo "kmod_output_dir: " $(kmod_output_dir) + @echo "base_list: " $(base_list) + @echo "lib_base: " $(lib_base) + @echo "all_kmod_c: " $(all_kmod_c) + @echo "all_lib_c: " $(all_lib_c) @echo "KMOD_INCLUDE_LIB=" $(KMOD_INCLUDE_LIB) -ifndef BASE_LIST -$(warning No *.kmod.c found under $(KMOD_SOURCE_DIR); nothing to build) + +ifeq ($(strip $(base_list)),) + $(warning No *.kmod.c found under $(KMOD_SOURCE_DIR); nothing to build) endif # --- Parallel-safe preparation as real targets --- # ensure the staging dir exists (order-only prereq) -$(OUTPUT_DIR): - @mkdir -p "$(OUTPUT_DIR)" +$(kmod_output_dir): + @mkdir -p "$(kmod_output_dir)" # generate the Kbuild control Makefile -# generate the Kbuild control Makefile -$(OUTPUT_DIR)/Makefile: | $(OUTPUT_DIR) +$(kmod_output_dir)/Makefile: | $(kmod_output_dir) @{ \ printf "ccflags-y += %s\n" "$(KMOD_CCFLAGS)"; \ - printf "obj-m := %s\n" "$(foreach m,$(BASE_LIST),$(m).o)"; \ - for m in $(BASE_LIST); do \ + printf "obj-m := %s\n" "$(foreach m,$(base_list),$(m).o)"; \ + for m in $(base_list); do \ printf "%s-objs := %s.kmod.o" "$$m" "$$m"; \ - for lb in $(LIB_BASE); do printf " %s.lib.o" "$$lb"; done; \ + for lb in $(lib_base); do printf " %s.lib.o" "$$lb"; done; \ printf "\n"; \ done; \ } > "$@" # stage kmod sources (one rule per file; parallelizable) -$(OUTPUT_DIR)/%.kmod.c: $(KMOD_SOURCE_DIR)/%.kmod.c | $(OUTPUT_DIR) +$(kmod_output_dir)/%.kmod.c: $(KMOD_SOURCE_DIR)/%.kmod.c | $(kmod_output_dir) @echo "--- Stage: $@ ---" @ln -sf "$<" "$@" 2>/dev/null || { rm -f "$@"; cp "$<" "$@"; } # stage library sources (optional; also parallelizable) -$(OUTPUT_DIR)/%.lib.c: $(KMOD_SOURCE_DIR)/%.lib.c | $(OUTPUT_DIR) +$(kmod_output_dir)/%.lib.c: $(KMOD_SOURCE_DIR)/%.lib.c | $(kmod_output_dir) @echo "--- Stage: $@ ---" @ln -sf "$<" "$@" 2>/dev/null || { rm -f "$@"; cp "$<" "$@"; } # rebuild inputs for 'modules' .PHONY: modules -modules: $(OUTPUT_DIR)/Makefile $(ALL_KMOD_C) $(ALL_LIB_C) - @echo "--- Invoking Kbuild for Modules: $(BASE_LIST) ---" - $(MAKE) -C "$(BUILD_DIR)" M="$(OUTPUT_DIR)" modules +modules: $(kmod_output_dir)/Makefile $(all_kmod_c) $(all_lib_c) + @echo "--- Invoking Kbuild for Modules: $(base_list) ---" + $(MAKE) -C "$(kmod_build_dir)" M="$(kmod_output_dir)" modules # top-level convenience target .PHONY: kmod @@ -97,26 +120,26 @@ kmod: modules # quality-of-life: allow 'make scratchpad/kmod/foo.ko' after batch build -$(OUTPUT_DIR)/%.ko: modules +$(kmod_output_dir)/%.ko: modules @true .PHONY: clean clean: - @if [ -d "$(OUTPUT_DIR)" ]; then \ - echo "--- Cleaning Kbuild Artifacts in $(OUTPUT_DIR) ---"; \ - $(MAKE) -C "$(BUILD_DIR)" M="$(OUTPUT_DIR)" clean; \ + @if [ -d "$(kmod_output_dir)" ]; then \ + echo "--- Cleaning Kbuild Artifacts in $(kmod_output_dir) ---"; \ + $(MAKE) -C "$(kmod_build_dir)" M="$(kmod_output_dir)" clean; \ # belt & suspenders: nuke common leftovers regardless of Kbuild's behavior - rm -f "$(OUTPUT_DIR)"/*.o \ - "$(OUTPUT_DIR)"/*.ko \ - "$(OUTPUT_DIR)"/*.mod \ - "$(OUTPUT_DIR)"/*.mod.c \ - "$(OUTPUT_DIR)"/modules.order \ - "$(OUTPUT_DIR)"/Module.symvers \ - "$(OUTPUT_DIR)"/.*.cmd 2>/dev/null || true; \ - rm -rf "$(OUTPUT_DIR)"/.tmp_versions 2>/dev/null || true; \ + rm -f "$(kmod_output_dir)"/*.o \ + "$(kmod_output_dir)"/*.ko \ + "$(kmod_output_dir)"/*.mod \ + "$(kmod_output_dir)"/*.mod.c \ + "$(kmod_output_dir)"/modules.order \ + "$(kmod_output_dir)"/Module.symvers \ + "$(kmod_output_dir)"/.*.cmd 2>/dev/null || true; \ + rm -rf "$(kmod_output_dir)"/.tmp_versions 2>/dev/null || true; \ # remove staged sources we created (symlinks or copies) - find "$(OUTPUT_DIR)" -maxdepth 1 -type l -name '*.kmod.c' -delete 2>/dev/null || true; \ - find "$(OUTPUT_DIR)" -maxdepth 1 -type l -name '*.lib.c' -delete 2>/dev/null || true; \ - find "$(OUTPUT_DIR)" -maxdepth 1 -type f -name '*.kmod.c' -delete 2>/dev/null || true; \ - find "$(OUTPUT_DIR)" -maxdepth 1 -type f -name '*.lib.c' -delete 2>/dev/null || true; \ + find "$(kmod_output_dir)" -maxdepth 1 -type l -name '*.kmod.c' -delete 2>/dev/null || true; \ + find "$(kmod_output_dir)" -maxdepth 1 -type l -name '*.lib.c' -delete 2>/dev/null || true; \ + find "$(kmod_output_dir)" -maxdepth 1 -type f -name '*.kmod.c' -delete 2>/dev/null || true; \ + find "$(kmod_output_dir)" -maxdepth 1 -type f -name '*.lib.c' -delete 2>/dev/null || true; \ fi diff --git a/developer/make/target_library_CLI.mk b/developer/make/target_library_CLI.mk index 0b52842..798ebef 100644 --- a/developer/make/target_library_CLI.mk +++ b/developer/make/target_library_CLI.mk @@ -3,7 +3,6 @@ # files have two suffixes by convention, e.g.: X.lib.c or Y.CLI.c .SUFFIXES: -.EXPORT_ALL_VARIABLES: .DELETE_ON_ERROR: #-------------------------------------------------------------------------------- @@ -16,32 +15,28 @@ LIBRARY_FILE ?= MACHINE_DIR ?= scratchpad LN_FLAGS ?= -ifeq ($(strip $(C)),) - $(error target_lib_CLI.mk: no C compiler specified) -endif - #-------------------------------------------------------------------------------- # derived variables # source discovery (single dir) -C_SOURCE_LIB := $(wildcard $(C_SOURCE_DIR)/*.lib.c) -C_SOURCE_EXEC := $(wildcard $(C_SOURCE_DIR)/*.CLI.c) +c_source_lib := $(wildcard $(C_SOURCE_DIR)/*.lib.c) +c_source_exec := $(wildcard $(C_SOURCE_DIR)/*.CLI.c) # remove suffix to get base name -C_BASE_LIB := $(sort $(patsubst %.lib.c,%, $(notdir $(C_SOURCE_LIB)))) -C_BASE_EXEC := $(sort $(patsubst %.CLI.c,%, $(notdir $(C_SOURCE_EXEC)))) +c_base_lib := $(sort $(patsubst %.lib.c,%, $(notdir $(c_source_lib)))) +c_base_exec := $(sort $(patsubst %.CLI.c,%, $(notdir $(c_source_exec)))) # two sets of object files, one for the lib, and one for the CLI programs -OBJECT_LIB := $(patsubst %, scratchpad/%.lib.o, $(C_BASE_LIB)) -OBJECT_EXEC := $(patsubst %, scratchpad/%.CLI.o, $(C_BASE_EXEC)) +object_lib := $(patsubst %, scratchpad/%.lib.o, $(c_base_lib)) +object_exec := $(patsubst %, scratchpad/%.CLI.o, $(c_base_exec)) -# executables are made from EXEC sources -EXEC := $(patsubst %, $(MACHINE_DIR)/%, $(C_BASE_EXEC)) +# executables are made from exec_ sources +exec_ := $(patsubst %, $(MACHINE_DIR)/%, $(c_base_exec)) #-------------------------------------------------------------------------------- # pull in dependencies --include $(OBJECT_LIB:.o=.d) $(OBJECT_EXEC:.o=.d) +-include $(object_lib:.o=.d) $(object_exec:.o=.d) #-------------------------------------------------------------------------------- @@ -65,19 +60,19 @@ version: information: @printf "· → Unicode middle dot — visible: [%b]\n" "·" @echo "C_SOURCE_DIR: " $(C_SOURCE_DIR) - @echo "C_SOURCE_LIB: " $(C_SOURCE_LIB) - @echo "C_SOURCE_EXEC: " $(C_SOURCE_EXEC) - @echo "C_BASE_LIB: " $(C_BASE_LIB) - @echo "C_BASE_EXEC: " $(C_BASE_EXEC) - @echo "OBJECT_LIB: " $(OBJECT_LIB) - @echo "OBJECT_EXEC: " $(OBJECT_EXEC) - @echo "EXEC: " $(EXEC) + @echo "c_source_lib: " $(c_source_lib) + @echo "c_source_exec: " $(c_source_exec) + @echo "c_base_lib: " $(c_base_lib) + @echo "c_base_exec: " $(c_base_exec) + @echo "object_lib: " $(object_lib) + @echo "object_exec: " $(object_exec) + @echo "exec_: " $(exec_) .PHONY: library library: $(LIBRARY_FILE) -$(LIBRARY_FILE): $(OBJECT_LIB) - @if [ -s "$@" ] || [ -n "$(OBJECT_LIB)" ]; then \ +$(LIBRARY_FILE): $(object_lib) + @if [ -s "$@" ] || [ -n "$(object_lib)" ]; then \ echo "ar rcs $@ $^"; \ ar rcs $@ $^; \ else \ @@ -85,10 +80,10 @@ $(LIBRARY_FILE): $(OBJECT_LIB) fi #.PHONY: CLI -#CLI: $(LIBRARY_FILE) $(EXEC) +#CLI: $(LIBRARY_FILE) $(exec_) .PHONY: CLI -CLI: library $(EXEC) +CLI: library $(exec_) # generally better to use the project local clean scripts, but this will make it so that the make targets can be run again @@ -96,8 +91,8 @@ CLI: library $(EXEC) .PHONY: clean clean: rm -f $(LIBRARY_FILE) - for obj in $(OBJECT_LIB) $(OBJECT_EXEC); do rm -f $$obj $${obj%.o}.d || true; done - for i in $(EXEC); do [ -e $$i ] && rm $$i || true; done + for obj in $(object_lib) $(object_exec); do rm -f $$obj $${obj%.o}.d || true; done + for i in $(exec_); do [ -e $$i ] && rm $$i || true; done # recipes -- 2.20.1