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,<dir>,<goal>)
  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 "<dir>/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) <noreply@anthropic.com>
This commit is contained in:
Darryl L. Miles 2026-07-22 16:48:24 +00:00 committed by R. Timothy Edwards
parent 64d2ad8df7
commit 242d415788
3 changed files with 39 additions and 13 deletions

7
.gitignore vendored
View File

@ -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
# "<dir>/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

View File

@ -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 <builddir> -f ${MAGICSRC}/<dir>/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,<dir>,<goal>) -- 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:

View File

@ -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}: