From 64614da7a09168a96e138bbebb8b3715646aad87 Mon Sep 17 00:00:00 2001 From: "Darryl L. Miles" Date: Thu, 23 Jul 2026 14:27:18 +0000 Subject: [PATCH] build: --enable-ccache-prefix-map for cross-tree ccache sharing The out-of-tree build puts absolute source-root paths on the command line (-I${MAGICSRC}, -I${srcdir}, the source file itself), which are part of ccache's key -- so same-tree rebuilds hit (proven) but different checkouts / build dirs do not share cache. New opt-in configure --enable-ccache-prefix-map adds -ffile-prefix-map=${MAGICSRC}=. to CFLAGS (requires ccache; the flag is probed for GCC-8+/clang support and skipped with a warning otherwise). This relativizes the source paths embedded in the compiled output (__FILE__, debug info) so a cached object is valid regardless of which tree produced it. Off by default: it makes debug paths relative, so gdb then needs `set substitute-path . `. It is only for cross-tree *correctness* and must be paired with CCACHE_BASEDIR= in the environment for cross-tree *hits* (that half normalizes the command-line paths in the hash; this half keeps the cached output tree-neutral). Same-tree caching needs neither. Verified: default/--disable-ccache carry no -ffile-prefix-map; --enable-ccache-prefix-map (probe "yes") adds it, and with --disable-ccache it warns and is ignored. Full build rc=0 (375 files); the installed tclmagic.so contains zero absolute /work/magic paths. Co-Authored-By: Claude Opus 4.8 (1M context) --- scripts/configure | 42 ++++++++++++++++++++++++++++++++++++++++++ scripts/configure.in | 26 ++++++++++++++++++++++++++ scripts/defs.mak.in | 9 +++++++++ 3 files changed, 77 insertions(+) diff --git a/scripts/configure b/scripts/configure index 80019f26..80f4988b 100755 --- a/scripts/configure +++ b/scripts/configure @@ -691,6 +691,7 @@ ALLOCA EGREP GREP PERL +CCACHE_PREFIX_MAP_FLAG CCACHE SED RANLIB @@ -762,6 +763,7 @@ ac_subst_files='' ac_user_opts=' enable_option_checking enable_ccache +enable_ccache_prefix_map with_gnu_ld enable_assertions enable_debug @@ -1428,6 +1430,7 @@ Optional Features: --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] --disable-ccache do not use ccache even if it is installed + --enable-ccache-prefix-map relativize embedded source paths for cross-tree ccache (needs ccache; makes debug paths relative) --enable-assertions build with fatal assertions enabled --enable-debug build with fatal debug enabled --disable-compression disable file compression @@ -4289,6 +4292,45 @@ $as_echo "$as_me: using ccache: CC=\"$CC\"" >&6;} fi fi +CCACHE_PREFIX_MAP_FLAG="" +# Check whether --enable-ccache-prefix-map was given. +if test "${enable_ccache_prefix_map+set}" = set; then : + enableval=$enable_ccache_prefix_map; + if test "x$CCACHE" = "x"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-ccache-prefix-map ignored: ccache is not in use" >&5 +$as_echo "$as_me: WARNING: --enable-ccache-prefix-map ignored: ccache is not in use" >&2;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -ffile-prefix-map" >&5 +$as_echo_n "checking whether $CC accepts -ffile-prefix-map... " >&6; } + magic_save_cflags="$CFLAGS" + CFLAGS="$CFLAGS -ffile-prefix-map=/nonexistent=." + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; }; CCACHE_PREFIX_MAP_FLAG="-ffile-prefix-map" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; }; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: compiler lacks -ffile-prefix-map; not relativizing paths" >&5 +$as_echo "$as_me: WARNING: compiler lacks -ffile-prefix-map; not relativizing paths" >&2;} +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$magic_save_cflags" + fi + +fi + + + # Extract the first word of "perl", so it can be a program name with args. set dummy perl; ac_word=$2 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 diff --git a/scripts/configure.in b/scripts/configure.in index ec655c83..95fe8038 100644 --- a/scripts/configure.in +++ b/scripts/configure.in @@ -49,6 +49,32 @@ if test "x$enable_ccache" = "xyes"; then fi fi +dnl Optional: normalize the absolute source-root prefix embedded in compiled +dnl output (__FILE__, debug info) so a cached object is valid regardless of which +dnl checkout / build dir produced it -- needed for *correct* cross-tree ccache +dnl sharing (which also wants CCACHE_BASEDIR= in the environment at +dnl build time; see the README). Off by default: it relativizes debug paths, so +dnl gdb then needs `set substitute-path . `. Requires GCC 8+/clang, so +dnl the flag is probed before use. Same-tree cache hits do NOT need this (the +dnl command-line paths already match); it is purely for cross-tree correctness. +CCACHE_PREFIX_MAP_FLAG="" +AC_ARG_ENABLE(ccache-prefix-map, +[ --enable-ccache-prefix-map relativize embedded source paths for cross-tree ccache (needs ccache; makes debug paths relative)], +[ + if test "x$CCACHE" = "x"; then + AC_MSG_WARN([--enable-ccache-prefix-map ignored: ccache is not in use]) + else + AC_MSG_CHECKING([whether $CC accepts -ffile-prefix-map]) + magic_save_cflags="$CFLAGS" + CFLAGS="$CFLAGS -ffile-prefix-map=/nonexistent=." + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])], + [AC_MSG_RESULT([yes]); CCACHE_PREFIX_MAP_FLAG="-ffile-prefix-map"], + [AC_MSG_RESULT([no]); AC_MSG_WARN([compiler lacks -ffile-prefix-map; not relativizing paths])]) + CFLAGS="$magic_save_cflags" + fi +]) +AC_SUBST(CCACHE_PREFIX_MAP_FLAG) + AC_PATH_PROG(PERL, perl, no) AC_SUBST(PERL) diff --git a/scripts/defs.mak.in b/scripts/defs.mak.in index 48047db6..8f22f385 100755 --- a/scripts/defs.mak.in +++ b/scripts/defs.mak.in @@ -186,6 +186,15 @@ DFLAGS_NOSTUB = @extra_defs@ @DEFS@ -DGCORE=\"@GCORE@\" DFLAGS_NOSTUB += -DSHDLIB_EXT=\"@SHDLIB_EXT@\" @NDEBUG_defs@ @DEBUG_defs@ ${FEATURE_FLAGS} CFLAGS = @CFLAGS@ @SHLIB_CFLAGS@ @INC_SPECS@ +# Set only by configure --enable-ccache-prefix-map (empty otherwise). Maps the +# absolute source root to "." in the compiled output so a cached object carries +# no tree-specific paths -- required for correct cross-tree ccache sharing (pair +# with CCACHE_BASEDIR= in the environment for cross-tree *hits*). +CCACHE_PREFIX_MAP_FLAG = @CCACHE_PREFIX_MAP_FLAG@ +ifneq (${CCACHE_PREFIX_MAP_FLAG},) +CFLAGS += ${CCACHE_PREFIX_MAP_FLAG}=${MAGICSRC}=. +endif + LDFLAGS = @LDFLAGS@ READLINE_DEFS = @rl_defs@