From: Thomas Walker Lynch Date: Wed, 22 Oct 2025 08:15:47 +0000 (+0000) Subject: . X-Git-Url: https://git.reasoningtechnology.com/fossil/timeline.rss?a=commitdiff_plain;h=4ab5df72c65f41e4b27a033ab5e2c8989fc34645;p=RT-project-share . --- diff --git a/developer/make/environment_RT_1.mk b/developer/make/environment_RT_1.mk index 84eb5db..af850d4 100644 --- a/developer/make/environment_RT_1.mk +++ b/developer/make/environment_RT_1.mk @@ -1,21 +1,30 @@ # makefile environment variable defaults. -# cc is the name of the C compiler, a file called .c is C source code. +# cc is the name of the C compiler, a file called .c is C source code. +# RT uses header integrated C source files, i.e. the source and the header are the same file SHELL=/bin/bash -#ECHO= echo -e -#ECHO= echo +# environment_RT_1.mk + ECHO := printf "%b\n" +C_SOURCE_DIR := cc +KMOD_SOURCE_DIR := cc + +C := gcc +CFLAGS := -std=gnu11 -Wall -Wextra -Wpedantic -finput-charset=UTF-8 +CFLAGS += -MMD -MP +CFLAGS += -I $(C_SOURCE_DIR) + +KMOD_CCFLAGS := -I $(KMOD_SOURCE_DIR) + +LIBNAME := $(PROJECT) +LIBNAME := $(subst -,_,$(LIBNAME)) + +LIBDIR := scratchpad +LIBFILE := $(LIBDIR)/lib$(LIBNAME).a + +LINKFLAGS := -L$(LIBDIR) -L/lib64 -L/lib -# sources found in these subdirectories: -SRCDIR_LIST=cc -LIBDIR := scratchpad -LIBFILE := $(LIBDIR)/lib.a -LINKFLAGS := -L$(LIBDIR) -L/lib64 -L/lib -EXECDIR := scratchpad +EXECDIR := scratchpad -C=gcc -CFLAGS=-std=gnu11 -Wall -Wextra -Wpedantic -finput-charset=UTF-8 -CFLAGS += -MMD -MP -LINKFLAGS=-L$(LIBDIR) -L/lib64 -L/lib diff --git a/developer/make/target_kmod.mk b/developer/make/target_kmod.mk index d24269d..6fc30e3 100644 --- a/developer/make/target_kmod.mk +++ b/developer/make/target_kmod.mk @@ -4,19 +4,27 @@ .SUFFIXES: .EXPORT_ALL_VARIABLES: +.DELETE_ON_ERROR: -SOURCE_DIR := cc -BUILD_DIR := /lib/modules/$(shell uname -r)/build -OUTPUT_DIR := $(abspath scratchpad/kmod) # dedicated kmod staging/build dir +# allow overrides +KMOD_SOURCE_DIR ?= cc + +# allow cross-compile override via KDIR; else default to running kernel +KDIR ?= +BUILD_DIR ?= $(if $(KDIR),$(KDIR),/lib/modules/$(shell uname -r)/build) + +# default, then canonicalize to absolute regardless of source +OUTPUT_DIR ?= scratchpad/kmod +OUTPUT_DIR := $(abspath $(OUTPUT_DIR)) # authored basenames (without suffix) -BASE_LIST := $(patsubst %.kmod.c,%,$(notdir $(wildcard $(SOURCE_DIR)/*.kmod.c))) +BASE_LIST := $(patsubst %.kmod.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.kmod.c))) # optional library sources (without suffix) to include inside modules # set KMOD_INCLUDE_LIB=0 to disable KMOD_INCLUDE_LIB ?= 1 ifeq ($(KMOD_INCLUDE_LIB),1) -LIB_BASE := $(patsubst %.lib.c,%,$(notdir $(wildcard $(SOURCE_DIR)/*.lib.c))) +LIB_BASE := $(patsubst %.lib.c,%,$(notdir $(wildcard $(KMOD_SOURCE_DIR)/*.lib.c))) else LIB_BASE := endif @@ -35,7 +43,7 @@ version: .PHONY: information information: - @echo "SOURCE_DIR: " $(SOURCE_DIR) + @echo "KMOD_SOURCE_DIR: " $(KMOD_SOURCE_DIR) @echo "BUILD_DIR: " $(BUILD_DIR) @echo "OUTPUT_DIR: " $(OUTPUT_DIR) @echo "BASE_LIST: " $(BASE_LIST) @@ -45,16 +53,17 @@ information: @echo "KMOD_INCLUDE_LIB=" $(KMOD_INCLUDE_LIB) ifndef BASE_LIST -$(warning No *.kmod.c found under $(SOURCE_DIR); nothing to build) +$(warning No *.kmod.c found under $(KMOD_SOURCE_DIR); nothing to build) endif -.PHONY: kmod -kmod: _prepare modules +# --- Parallel-safe preparation as real targets --- -.PHONY: _prepare -_prepare: +# ensure the staging dir exists (order-only prereq) +$(OUTPUT_DIR): @mkdir -p "$(OUTPUT_DIR)" - # fresh Kbuild control file — one obj per module; each module also links lib objs (if any) + +# generate the Kbuild control Makefile +$(OUTPUT_DIR)/Makefile: | $(OUTPUT_DIR) @{ \ printf "obj-m := %s\n" "$(foreach m,$(BASE_LIST),$(m).o)"; \ for m in $(BASE_LIST); do \ @@ -62,23 +71,29 @@ _prepare: for lb in $(LIB_BASE); do printf " %s.lib.o" "$$lb"; done; \ printf "\n"; \ done; \ - } > "$(OUTPUT_DIR)/Makefile" - # stage kmod sources (read-only authored dir, write only to OUTPUT_DIR) - @for b in $(BASE_LIST); do \ - src="$(SOURCE_DIR)/$$b.kmod.c"; dst="$(OUTPUT_DIR)/$$b.kmod.c"; \ - echo "--- Stage: $$dst ---"; ln -sf "$$src" "$$dst" 2>/dev/null || cp "$$src" "$$dst"; \ - done - # stage library sources (optional) - @for b in $(LIB_BASE); do \ - src="$(SOURCE_DIR)/$$b.lib.c"; dst="$(OUTPUT_DIR)/$$b.lib.c"; \ - echo "--- Stage: $$dst ---"; ln -sf "$$src" "$$dst" 2>/dev/null || cp "$$src" "$$dst"; \ - done + } > "$@" + +# stage kmod sources (one rule per file; parallelizable) +$(OUTPUT_DIR)/%.kmod.c: $(KMOD_SOURCE_DIR)/%.kmod.c | $(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) + @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 +# top-level convenience target +.PHONY: kmod +kmod: modules + + # quality-of-life: allow 'make scratchpad/kmod/foo.ko' after batch build $(OUTPUT_DIR)/%.ko: modules @true @@ -88,8 +103,18 @@ clean: @if [ -d "$(OUTPUT_DIR)" ]; then \ echo "--- Cleaning Kbuild Artifacts in $(OUTPUT_DIR) ---"; \ $(MAKE) -C "$(BUILD_DIR)" M="$(OUTPUT_DIR)" clean; \ - 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; \ + # 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; \ + # 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; \ fi diff --git a/developer/make/target_library_cli.mk b/developer/make/target_library_cli.mk index dd17117..5ef8770 100644 --- a/developer/make/target_library_cli.mk +++ b/developer/make/target_library_cli.mk @@ -3,6 +3,7 @@ .SUFFIXES: .EXPORT_ALL_VARIABLES: +.DELETE_ON_ERROR: #-------------------------------------------------------------------------------- # files have two suffixes by convention, e.g.: X.lib.c or Y.cli.c @@ -12,35 +13,35 @@ ifeq ($(strip $(C)),) $(error target_lib_cli.mk: no C compiler specified) endif -# keep only the source directories that are in the file system -SRCDIR_LIST := $(wildcard $(SRCDIR_LIST)) +# single source directory +C_SOURCE_DIR ?= cc +C_SOURCE_DIR_OK := $(wildcard $(C_SOURCE_DIR)) -ifeq ($(strip $(SRCDIR_LIST)),) - $(warning target_lib_cli.mk: empty SRCDIR_LIST) +ifeq ($(strip $(C_SOURCE_DIR_OK)),) + $(warning target_lib_cli.mk: C_SOURCE_DIR '$(C_SOURCE_DIR)' not found or empty) endif -# duplicate source file names in different directories will cause -# problems with this makefile +# RT uses header integrated C source files +CFLAGS ?= -I $(C_SOURCE_DIR) -C_SOURCE_LIB := $(foreach dir, $(SRCDIR_LIST), $(wildcard $(dir)/*.lib.c)) -C_SOURCE_EXEC := $(foreach dir, $(SRCDIR_LIST), $(wildcard $(dir)/*.cli.c)) +# source discovery (single dir) +C_SOURCE_LIB := $(wildcard $(C_SOURCE_DIR)/*.lib.c) +C_SOURCE_EXEC := $(wildcard $(C_SOURCE_DIR)/*.cli.c) -#remove the 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)))) +# 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)))) -# two sets of object files, one for the lib, and one for the command line interface progs -OBJECT_LIB= $(patsubst %, scratchpad/%.lib.o, $(C_BASE_LIB)) -OBJECT_EXEC= $(patsubst %, scratchpad/%.cli.o, $(C_BASE_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)) -include $(OBJECT_LIB:.o=.d) $(OBJECT_EXEC:.o=.d) # executables are made from EXEC sources -EXEC= $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC)) +EXEC := $(patsubst %, $(EXECDIR)/%, $(C_BASE_EXEC)) -# the new C programming style gated sections in source instead of header filesheader -INCFLAG_List := $(foreach dir, $(SRCDIR_LIST), -I $(dir)) -CFLAGS += $(INCFLAG_List) #-------------------------------------------------------------------------------- # targets @@ -62,7 +63,7 @@ version: .PHONY: information information: @printf "· → Unicode middle dot — visible: [%b]\n" "·" - @echo "SRCDIR_LIST: " $(SRCDIR_LIST) + @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) @@ -72,43 +73,16 @@ information: @echo "EXEC: " $(EXEC) @echo "INCFLAG_List: " $(INCFLAG_List) -#.PHONY: library -#library: $(LIBFILE) - -NEED_LIB := $(strip $(OBJECT_LIB)) -LIB_ARG := $(if $(NEED_LIB),$(LIBFILE),) # expands to lib path only when needed - .PHONY: library -library: $(if $(NEED_LIB),$(LIBFILE),.remove_lib_if_exists) - -.PHONY: .remove_lib_if_exists -.remove_lib_if_exists: - @rm -f $(LIBFILE) - -ifneq ($(NEED_LIB),) -$(LIBFILE): $(OBJECT_LIB) - @echo "ar rcs $@ $^" - ar rcs $@ $^ -endif - -ifeq ($(NEED_LIB),) -$(LIBFILE): - @rm -f $(LIBFILE) -endif - +library: $(LIBFILE) -#$(LIBFILE): $(OBJECT_LIB) $(DEPFILE) $(LIBFILE): $(OBJECT_LIB) - ar rcs $(LIBFILE) $(OBJECT_LIB) - - -#.PHONY: cli -#cli: $(LIBFILE) $(DEPFILE) -#cli: $(LIBFILE) -# make sub_cli - -#.PHONY: sub_cli -#sub_cli: $(EXEC) + @if [ -s "$@" ] || [ -n "$(OBJECT_LIB)" ]; then \ + echo "ar rcs $@ $^"; \ + ar rcs $@ $^; \ + else \ + rm -f "$@"; \ + fi #.PHONY: cli #cli: $(LIBFILE) $(EXEC) @@ -117,7 +91,6 @@ $(LIBFILE): $(OBJECT_LIB) 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 .PHONY: clean @@ -128,13 +101,9 @@ clean: # recipes -vpath %.c $(SRCDIR_LIST) -scratchpad/%.o: %.c +scratchpad/%.o: $(C_SOURCE_DIR)/%.c $(C) $(CFLAGS) -o $@ -c $< -#$(EXECDIR)/%: scratchpad/%.cli.o $(LIBFILE) -# $(C) -o $@ $< $(LIBFILE) $(LINKFLAGS) - $(EXECDIR)/%: scratchpad/%.cli.o $(C) -o $@ $< $(LIB_ARG) $(LINKFLAGS)