build: VPATH-enable shared make machinery (out-of-tree)

With the autoconf layer relocatable, teach the shared make
files to read sources from the source tree and write objects into the
build tree.  The ~26 "standard" and "near-standard" module Makefiles now
build out-of-tree with no per-module edits.

scripts/defs.mak.in:
* Add MAGICSRC = @abs_top_srcdir@ (absolute source top) and derive each
  module's srcdir/VPATH from CURDIR relative to the build top:
      BUILD_TOP      := $(abspath $(MAGICDIR))
      MODULE_SUBPATH := $(subst $(BUILD_TOP),,$(CURDIR))
      srcdir         := $(MAGICSRC)$(MODULE_SUBPATH)
      VPATH          := $(srcdir)
  (MAGICDIR keeps meaning the *build* top; in-tree the trees coincide.)
* CPPFLAGS: add -I${MAGICSRC} (source top, for "<module>/<hdr>.h") and
  -I${srcdir} (same-dir headers), keeping -I${MAGICDIR} for the generated
  database/database.h in the build top.
* MAGIC_VERSION/REVISION read ${MAGICSRC}/VERSION; MAGIC_COMMIT uses
  `git -C ${MAGICSRC}` so it works from a build dir outside the work-tree.

rules.mak:
* Compile rule: `-c $*.c` -> `-c $< -o $@` so the source is found via
  VPATH in srcdir and the object is written to the build cwd.
* Depend and tags rules: prefix sources with $(srcdir)/ (they are passed
  to the compiler/ctags directly, which do not honor VPATH).

scripts/configure.in: AC_CONFIG_FILES([rules.mak:rules.mak]) copies the
VPATH-aware rules.mak into the build top, so a single ${MAGICDIR}
resolves both `include`s in every subdir Makefile.  Regenerated configure.

Known limitation (v1): the Depend post-processing sed strips
absolute-path headers, so with an absolute srcdir most header deps are
dropped; out-of-tree incremental header-change rebuilds are weaker.
Depend is already "optimistic/optional"; relativizing is a follow-up.

Verified out-of-tree: `tiles` and `drc` (the latter #includes the
generated database/database.h) build to completion; all objects land in
the build tree; the source tree stays clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Darryl L. Miles 2026-07-22 12:33:37 +00:00 committed by R. Timothy Edwards
parent a4e6289035
commit b522f31d87
4 changed files with 38 additions and 7 deletions

View File

@ -16,7 +16,7 @@ depend: ${DEPEND_FILE}
# corrupting the output, the final MV is transactional. If that is needed
# it indicates a missing dependency somewhere in a upstream/parent Makefile.
${DEPEND_FILE}: ${DEPSRCS}
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${DEPEND_FLAG} ${DEPSRCS} > ${DEPEND_FILE}$$PPID.tmp
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} ${DEPEND_FLAG} $(addprefix $(srcdir)/,${DEPSRCS}) > ${DEPEND_FILE}$$PPID.tmp
${SED} -e "/#/D" -e "/ \//s/ \/.*\.h//" -e "/ \\\/D" -i ${DEPEND_FILE}$$PPID.tmp
${MV} -f ${DEPEND_FILE}$$PPID.tmp ${DEPEND_FILE}
@ -26,7 +26,7 @@ ${DEPEND_FILE}: ${DEPSRCS}
%.o: %.c
@echo --- compiling ${MODULE}/$*.o
${RM} $*.o
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} -c $*.c
${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} -c $< -o $@
lib${MODULE}.o: ${OBJS}
@echo --- linking lib${MODULE}.o
@ -55,7 +55,7 @@ clean:
${RM} ${CLEANS}
tags: ${SRCS} ${LIB_SRCS}
ctags ${SRCS} ${LIB_SRCS}
ctags $(addprefix $(srcdir)/,${SRCS} ${LIB_SRCS})
# Depends are a somewhat optional part of the build process that are only useful when incremental
# building. If the file is here it's here, if not continue with build optimistically

3
scripts/configure vendored
View File

@ -9300,6 +9300,8 @@ ac_config_files="$ac_config_files defs.mak:scripts/defs.mak.in"
ac_config_files="$ac_config_files scripts/makedbh:scripts/makedbh.in"
ac_config_files="$ac_config_files rules.mak:rules.mak"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@ -10009,6 +10011,7 @@ do
case $ac_config_target in
"defs.mak") CONFIG_FILES="$CONFIG_FILES defs.mak:scripts/defs.mak.in" ;;
"scripts/makedbh") CONFIG_FILES="$CONFIG_FILES scripts/makedbh:scripts/makedbh.in" ;;
"rules.mak") CONFIG_FILES="$CONFIG_FILES rules.mak:rules.mak" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac

View File

@ -1982,6 +1982,10 @@ dnl build directory (config.status' CWD): defs.mak at the build top, makedbh
dnl under build/scripts/ (matching ${SCRIPTS}/makedbh = ${MAGICDIR}/scripts).
AC_CONFIG_FILES([defs.mak:scripts/defs.mak.in])
AC_CONFIG_FILES([scripts/makedbh:scripts/makedbh.in], [chmod +x scripts/makedbh])
dnl Copy rules.mak into the build top (it has no @...@ substitutions; this just
dnl places it next to the generated defs.mak so a single ${MAGICDIR} resolves
dnl both `include`s in every subdir Makefile out-of-tree).
AC_CONFIG_FILES([rules.mak:rules.mak])
AC_OUTPUT
dnl

View File

@ -8,6 +8,27 @@
SHELL = @SHELL@
# --- out-of-tree (VPATH) support ------------------------------------------
# MAGICDIR is set by each subdir Makefile to the relative path back to the
# *build* top (that is where the generated defs.mak / rules.mak live, and where
# the generated database/database.h is written). MAGICSRC is the absolute path
# to the *source* top. For an in-tree build the two trees coincide.
MAGICSRC = @abs_top_srcdir@
# Derive this module's source directory (and VPATH) from where make is running
# (CURDIR, a build directory) relative to the build top (abspath of MAGICDIR):
# build top = $(abspath $(MAGICDIR))
# subpath = "/tiles", or "" at the top
# srcdir = $(MAGICSRC)$(subpath)
BUILD_TOP := $(abspath $(MAGICDIR))
# 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.
MODULE_SUBPATH := $(patsubst $(BUILD_TOP)%,%,$(CURDIR))
srcdir := $(MAGICSRC)$(MODULE_SUBPATH)
VPATH := $(srcdir)
# --------------------------------------------------------------------------
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
@ -79,9 +100,9 @@ LIB_SPECS_GRNULL = @LIB_SPECS_GRNULL@
WISH_EXE = @WISH_EXE@
TCL_LIB_DIR = @TCL_LIB_DIR@
MAGIC_VERSION ?= $(shell cat ${MAGICDIR}/VERSION | cut -d. -f1-2)
MAGIC_REVISION ?= $(shell cat ${MAGICDIR}/VERSION | cut -d. -f3)
MAGIC_COMMIT ?= $(shell git rev-parse HEAD)
MAGIC_VERSION ?= $(shell cat ${MAGICSRC}/VERSION | cut -d. -f1-2)
MAGIC_REVISION ?= $(shell cat ${MAGICSRC}/VERSION | cut -d. -f3)
MAGIC_COMMIT ?= $(shell git -C ${MAGICSRC} rev-parse HEAD)
MAGIC_BUILDDATE ?= $(shell date | tr -d '\r\n')
# This allow inheritence of the values from toplevel Makefile
@ -111,7 +132,10 @@ CXX = @CXX@
### Status: NOT-STABILITY-AFFECTING (if your binary links you are good to continue)
#FEATURE_FLAGS += -DSUPPORT_REMOVE_MALLOC_LEGACY
CPPFLAGS = -I${MAGICDIR} @CPPFLAGS@
# -I${MAGICDIR}: build top, for the generated database/database.h
# -I${MAGICSRC}: source top, for "<module>/<header>.h" includes
# -I${srcdir}: this module's source dir, for same-directory headers
CPPFLAGS = -I${MAGICDIR} -I${MAGICSRC} -I${srcdir} @CPPFLAGS@
CXXFLAGS = @CXXFLAGS@
DFLAGS_MAGICVERSION = -DMAGIC_VERSION=\"${MAGIC_VERSION}\" -DMAGIC_REVISION=\"${MAGIC_REVISION}\" -DMAGIC_COMMIT=\"${MAGIC_COMMIT}\" "-DMAGIC_BUILDDATE=\"${MAGIC_BUILDDATE}\""
DFLAGS = @extra_defs@ @stub_defs@ @DEFS@ ${DFLAGS_MAGICVERSION} -DGCORE=\"@GCORE@\"