From 242d4157887cd5c2a4ad5ffd5f2976da0ce679b1 Mon Sep 17 00:00:00 2001 From: "Darryl L. Miles" Date: Wed, 22 Jul 2026 16:48:24 +0000 Subject: [PATCH] build: accept @srcdir@-substituted subdir Makefiles Enabler for the Makefile -> Makefile.in migration. No module is converted yet; behaviour is identical. * scripts/defs.mak.in: dual-mode. A module converted to Makefile.in will set `srcdir` (and VPATH) from @srcdir@ before including defs.mak; only derive them (the $(abspath)/$(patsubst) srcdir computation) when it did not -- `ifeq ($(origin srcdir),undefined)`. BUILD_TOP (needed by GENINC) is computed either way. * Makefile.in: route every subdir recursion through a single helper, $(call submake,,) which uses the generated build Makefile if config.status made one there (a converted Makefile.in) and otherwise falls back to the source Makefile with -f. Today nothing is converted, so out-of-tree always takes the -f path and in-tree uses the (identical) static Makefile natively. clean/ keeps its own no-mkdir variant. readline/ is intentionally never converted and always takes -f. * .gitignore: document the migration policy -- each converted module adds its generated "/Makefile" here in the same commit so an in-tree build can never commit a generated Makefile. (None converted yet.) Verified in-tree and out-of-tree: `configure && make && make install` each produce 376 files with the header in the right place (database/ database.h in-tree, include/database/database.h relocated), 27/28 docs, source tree clean. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 7 +++++++ Makefile.in | 39 ++++++++++++++++++++++++++------------- scripts/defs.mak.in | 6 ++++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index f1f12990..2810adfc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,13 @@ install.log make.log reconfigure.sh +# Generated per-directory Makefiles (Makefile.in migration). POLICY: whenever a +# module's Makefile becomes a configure-generated Makefile.in, add its +# "/Makefile" here in the *same commit*, so an in-tree build never lets a +# generated Makefile be committed. (Top-level /Makefile is handled above; +# readline/ is intentionally NOT converted and keeps its tracked static Makefile.) +# --- converted dirs below (none yet) --- + # Compiled objects / libraries *.o *.a diff --git a/Makefile.in b/Makefile.in index dc3300a7..8499cd03 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,9 +4,8 @@ MAGICDIR = . # Absolute path to the source tree (config.status substitutes @abs_top_srcdir@). -# For an in-tree build this is the same directory as the build top. Every -# recursion below drives a build subdirectory (created on demand) using the -# module Makefile from the source tree: -C -f ${MAGICSRC}//Makefile. +# For an in-tree build this is the same directory as the build top. Recursion +# into subdirectories goes through $(submake) (defined below). MAGICSRC = @abs_top_srcdir@ PROGRAMS = magic TECHS = scmos @@ -27,6 +26,16 @@ INSTALL_CAD_DIRS = windows doc ${TECHS} # the build tree), empty otherwise (the pre-built PostScript is installed as-is). DOCS_TARGET = @DOCS_TARGET@ +# $(call submake,,) -- recurse into a build subdirectory. +# Use the generated build Makefile if config.status created one there (a module +# converted to Makefile.in); otherwise fall back to the source Makefile +# with -f. The build subdir is created on demand. During the +# Makefile.in migration both kinds coexist; readline/ is intentionally never +# converted, so it always takes the -f path. +define submake +mkdir -p $(1) && if test -f $(1)/Makefile; then $(MAKE) -C $(1) $(2); else $(MAKE) -C $(1) -f $(MAGICSRC)/$(1)/Makefile $(2); fi +endef + all: $(ALL_TARGET) techs $(DOCS_TARGET) standard: mains @@ -47,12 +56,12 @@ config: tcllibrary: ${DATABASE_H} modules @echo --- making Tcl shared libraries for dir in ${PROGRAMS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile tcl-main || exit 1; done + $(call submake,$$dir,tcl-main) || exit 1; done mains: ${DATABASE_H} modules libs @echo --- making main programs for dir in ${PROGRAMS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile main || exit 1; done + $(call submake,$$dir,main) || exit 1; done # makedbh is the one generated helper script; it lives in the *build* tree. # ${DATABASE_H} is $(builddir)/database/database.h in-tree, or @@ -77,13 +86,13 @@ LIBS_SUBDIR := $(shell for i in ${MODULES}; do echo "$${i}/lib$${i}.a"; done) .PHONY: FORCE ${MODULES_SUBDIR}: FORCE - @d=$(dir $@); mkdir -p $$d && ${MAKE} -C $$d -f ${MAGICSRC}/$${d}Makefile module + @$(call submake,$(patsubst %/,%,$(dir $@)),module) .PHONY: modules modules: ${DATABASE_H} depend ${MODULES_SUBDIR} ${LIBS_SUBDIR}: FORCE - @d=$(dir $@); mkdir -p $$d && ${MAKE} -C $$d -f ${MAGICSRC}/$${d}Makefile lib + @$(call submake,$(patsubst %/,%,$(dir $@)),lib) # Force the tiles/utils modules to exist first for libdatabase.a .PHONY: libs @@ -106,7 +115,7 @@ SUBDIRS_DEPEND = $(addsuffix /Depend, ${SUBDIRS_FILTERED}) ${SUBDIRS_DEPEND}: ${DATABASE_H} @echo --- making dependencies - @d=$(dir $@); mkdir -p $$d && ${MAKE} -C $$d -f ${MAGICSRC}/$${d}Makefile depend + @$(call submake,$(patsubst %/,%,$(dir $@)),depend) .PHONY: depend depend: defs.mak ${SUBDIRS_DEPEND} @@ -115,7 +124,7 @@ depend: defs.mak ${SUBDIRS_DEPEND} techs: depend @echo --- making techs for dir in ${TECHS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile all || exit 1; done + $(call submake,$$dir,all) || exit 1; done # Regenerate the PostScript documentation from its .tex sources (only reached # from "all" when configure found latex+dvips; see DOCS_TARGET). @@ -135,9 +144,9 @@ install-magic: install-real: install-dirs for dir in ${INSTALL_CAD_DIRS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile install; done + $(call submake,$$dir,install); done for dir in ${PROGRAMS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile install; done + $(call submake,$$dir,install); done install-tcl-dirs: ${SCRIPTS}/mkdirs $(DESTDIR)${INSTALL_BINDIR} \ @@ -156,11 +165,15 @@ install-tcl: install-tcl-real: install-tcl-dirs for dir in ${INSTALL_CAD_DIRS} ${PROGRAMS}; do \ - mkdir -p $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile install-tcl; done + $(call submake,$$dir,install-tcl); done clean: + @# clean must not create dirs: skip absent ones, and use the generated build + @# Makefile if present else the source one (mirrors $(submake) without mkdir). for dir in ${SUBDIRS_FILTERED} ${TECHS} ${BUNDLED_MODULES}; do \ - test -d $$dir && ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile clean || true; done + test -d $$dir || continue; \ + if test -f $$dir/Makefile; then ${MAKE} -C $$dir clean; \ + else ${MAKE} -C $$dir -f ${MAGICSRC}/$$dir/Makefile clean; fi || true; done ${RM} *.tmp */*.tmp *.sav */*.sav *.log TAGS tags distclean: diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index 44bd6ab0..45d73f21 100755 --- a/scripts/defs.mak.in +++ b/scripts/defs.mak.in @@ -21,6 +21,11 @@ MAGICSRC = @abs_top_srcdir@ # subpath = "/tiles", or "" at the top # srcdir = $(MAGICSRC)$(subpath) BUILD_TOP := $(abspath $(MAGICDIR)) +# Dual mode: a module converted to Makefile.in sets `srcdir` (and VPATH) from +# @srcdir@ *before* including this file, so we only derive them when it did not. +# This lets the two kinds of Makefile coexist during the migration. BUILD_TOP +# (needed by GENINC below) is computed either way. +ifeq ($(origin srcdir),undefined) # Anchored prefix strip (patsubst matches the whole word, so BUILD_TOP must be a # leading prefix): "" at the build top, "/tiles" in a subdir. Unlike $(subst …) # this cannot mis-fire if BUILD_TOP happens to recur later in the path. @@ -32,6 +37,7 @@ srcdir := $(MAGICSRC)$(MODULE_SUBPATH) ifneq ($(MODULE_SUBPATH),) VPATH := $(srcdir) endif +endif # Generated headers (currently just database/database.h) are exposed through a # single include directory, ${GENINC}: