Preserve timestamps for unchanged installed files

Avoid rewriting identical installed files during Tcl, Tk, and general
bext installs. Remove the unconditional build stamp so no-op builds do
not trigger a dependent BRL-CAD reconfigure.
This commit is contained in:
Clifford Yapp
2026-09-16 18:39:14 +00:00
parent fe3b288e65
commit 1c7c8af7d0
7 changed files with 170 additions and 32 deletions
+47 -18
View File
@@ -47,6 +47,21 @@ function(bext_write_file_list outvar filename values)
set(${outvar} "${filename}" PARENT_SCOPE)
endfunction()
function(bext_content_fingerprints outvar root label file_list_var)
set(records "")
foreach(relative IN LISTS ${file_list_var})
set(path "${root}/${relative}")
if (IS_SYMLINK "${path}")
file(READ_SYMLINK "${path}" value)
string(APPEND records "L ${label}/${relative} ${value}\n")
else ()
file(SHA256 "${path}" value)
string(APPEND records "F ${label}/${relative} ${value}\n")
endif ()
endforeach()
set(${outvar} "${records}" PARENT_SCOPE)
endfunction()
function(bext_relative_path outvar path)
file(RELATIVE_PATH relative "${BEXT_INSTALL_ROOT}" "${path}")
string(REPLACE "\\" "/" relative "${relative}")
@@ -355,15 +370,6 @@ list(SORT plain_text_files)
# install prefix intact: downstream projects replace this canonical prefix
# with their own staging prefix after copying the finalized tree.
set(text_paths ${text_files})
foreach(path ${text_paths})
set(text_path "${BEXT_INSTALL_ROOT}/${path}")
if (UNIX)
file(CHMOD "${text_path}"
PERMISSIONS OWNER_READ OWNER_WRITE
GROUP_READ GROUP_WRITE
WORLD_READ)
endif ()
endforeach()
foreach(clear_target
"${BEXT_SOURCE_ROOT}"
"${BEXT_BINARY_ROOT}"
@@ -392,13 +398,6 @@ if ("${BEXT_SYSTEM_NAME}" STREQUAL "Darwin" AND
list(APPEND binary_cleanup_paths "${BEXT_INSTALL_ROOT}/${relative}")
endforeach()
endif ()
foreach(path ${binary_paths})
if (UNIX)
file(CHMOD "${path}"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)
endif ()
endforeach()
bext_run_binary_clear("${binary_cleanup_paths}")
bext_run_rpath_update("${rpath_paths}")
@@ -408,6 +407,8 @@ bext_json_escape(platform "${BEXT_SYSTEM_NAME}")
file(APPEND "${BEXT_MANIFEST}.tmp" " \"platform\": \"${platform}\",\n")
file(APPEND "${BEXT_MANIFEST}.tmp" " \"install_root\": \"install\",\n")
file(APPEND "${BEXT_MANIFEST}.tmp" " \"generated_by\": \"bext\",\n")
bext_write_json_array("${BEXT_MANIFEST}.tmp" "files" installed_files)
file(APPEND "${BEXT_MANIFEST}.tmp" ",\n")
bext_write_json_array("${BEXT_MANIFEST}.tmp" "rpath" rpath_files)
file(APPEND "${BEXT_MANIFEST}.tmp" ",\n")
bext_write_json_array("${BEXT_MANIFEST}.tmp" "binary" binary_files)
@@ -416,7 +417,35 @@ bext_write_json_array("${BEXT_MANIFEST}.tmp" "cmake" cmake_files)
file(APPEND "${BEXT_MANIFEST}.tmp" ",\n")
bext_write_json_array("${BEXT_MANIFEST}.tmp" "text" plain_text_files)
file(APPEND "${BEXT_MANIFEST}.tmp" "\n}\n")
file(RENAME "${BEXT_MANIFEST}.tmp" "${BEXT_MANIFEST}")
file(COPY_FILE "${BEXT_MANIFEST}.tmp" "${BEXT_MANIFEST}" ONLY_IF_DIFFERENT)
file(REMOVE "${BEXT_MANIFEST}.tmp")
file(TOUCH "${BEXT_MANIFEST}")
# Existing files are watched by downstream builds. This list also detects
# additions and removals without changing its timestamp on a no-op build.
file(GLOB_RECURSE noinstall_files
LIST_DIRECTORIES false
RELATIVE "${BEXT_NOINSTALL_ROOT}"
"${BEXT_NOINSTALL_ROOT}/*"
)
list(REMOVE_ITEM noinstall_files "build-stamp")
list(SORT noinstall_files)
set(noinstall_inventory "${BEXT_BINARY_ROOT}/CMakeFiles/bext-noinstall-files.txt")
bext_write_file_list(noinstall_inventory "${noinstall_inventory}" noinstall_files)
file(COPY_FILE "${noinstall_inventory}" "${BEXT_NOINSTALL_ROOT}/build-stamp"
ONLY_IF_DIFFERENT)
# Finalized binaries and config files may be rewritten on every install even
# when their resulting bytes are unchanged. Publish one stable dependency for
# downstream builds instead of making them watch every output timestamp.
bext_content_fingerprints(installed_content "${BEXT_INSTALL_ROOT}" "install"
installed_files)
bext_content_fingerprints(noinstall_content "${BEXT_NOINSTALL_ROOT}" "noinstall"
noinstall_files)
file(SHA256 "${BEXT_MANIFEST}" manifest_digest)
string(SHA256 content_digest
"${installed_content}${noinstall_content}M ${manifest_digest}\n")
set(content_stamp "${BEXT_BINARY_ROOT}/bext-content-stamp")
file(WRITE "${content_stamp}.tmp" "${content_digest}\n")
file(COPY_FILE "${content_stamp}.tmp" "${content_stamp}" ONLY_IF_DIFFERENT)
file(REMOVE "${content_stamp}.tmp")
message(STATUS "Generated bext install manifest: ${BEXT_MANIFEST}")
-9
View File
@@ -313,14 +313,6 @@ if(MSVC)
endif(MSVC)
# Add a target that will run every time we build and touch a file in
# noinstall to allow interested parent CMake builds to be aware of potential
# changes, even if all that happens is to add files - otherwise, add-only
# operations won't trigger a CMake reconfigure even if the client build is
# watching the install files.
file(MAKE_DIRECTORY ${CMAKE_NOBUNDLE_INSTALL_PREFIX})
add_custom_target(BuildStamp ALL COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_NOBUNDLE_INSTALL_PREFIX}/build-stamp)
# If configurations change after a build has been performed, we don't
# automatically scrub a pre-existing output directory to remove the files from
# the newly disabled components. This variable records whether we need to warn
@@ -771,7 +763,6 @@ endif ()
if (TARGET PLIEF_BLD-install)
add_dependencies(bext_finalize PLIEF_BLD-install)
endif ()
add_dependencies(BuildStamp bext_finalize)
###############################################################################
+1 -1
View File
@@ -71,7 +71,7 @@ if (ENABLE_ITK)
COMMAND ${CMAKE_COMMAND} -E copy ${BEXT_ITCL_BUNDLED_SOURCE_DIR}/tclconfig/install-sh <SOURCE_DIR>/tclconfig/install-sh
CONFIGURE_COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/itk_configure.cmake
BUILD_COMMAND ${BEXT_MAKE_COMMAND} -j${pcnt}
INSTALL_COMMAND ${BEXT_MAKE_COMMAND} -j1 install
INSTALL_COMMAND ${BEXT_MAKE_COMMAND} -j1 INSTALL_OPTIONS=-C install
LOG_CONFIGURE ${EXT_BUILD_QUIET}
LOG_BUILD ${EXT_BUILD_QUIET}
LOG_INSTALL ${EXT_BUILD_QUIET}
+4 -3
View File
@@ -135,7 +135,8 @@ if (ENABLE_TCL)
"${CMAKE_CURRENT_SOURCE_DIR}/tcl_relocatable_config.patch")
if (NOT MSVC)
list(APPEND TCL_PATCH_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/tcl_unix_build.patch")
"${CMAKE_CURRENT_SOURCE_DIR}/tcl_unix_build.patch"
"${CMAKE_CURRENT_SOURCE_DIR}/tcl_incremental_install.patch")
endif ()
if (WIN32)
list(APPEND TCL_PATCH_FILES
@@ -303,12 +304,12 @@ if (ENABLE_TCL)
# we must provide it ourselves
if (MSVC)
add_custom_target(tclsh_cpy ALL
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${CMAKE_EXECUTABLE_SUFFIX} ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${CMAKE_EXECUTABLE_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${TCL_MAJOR_VERSION}${TCL_MINOR_VERSION}${CMAKE_EXECUTABLE_SUFFIX} ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${CMAKE_EXECUTABLE_SUFFIX}
DEPENDS TCL_BLD-install
)
else (MSVC)
add_custom_target(tclsh_cpy ALL
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${TCL_VERSION}${CMAKE_EXECUTABLE_SUFFIX} ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${CMAKE_EXECUTABLE_SUFFIX}
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${TCL_VERSION}${CMAKE_EXECUTABLE_SUFFIX} ${CMAKE_BUNDLE_INSTALL_PREFIX}/${BIN_DIR}/tclsh${CMAKE_EXECUTABLE_SUFFIX}
DEPENDS TCL_BLD-install
)
endif (MSVC)
+60
View File
@@ -0,0 +1,60 @@
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -153,9 +153,9 @@
INSTALL_STRIP_PROGRAM = strip
INSTALL_STRIP_LIBRARY = strip -x
-INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c
+INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c -C
INSTALL_PROGRAM = ${INSTALL}
-INSTALL_LIBRARY = ${INSTALL}
+INSTALL_LIBRARY = ${INSTALL} -m 644
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_DATA_DIR = ${INSTALL} -d -m 755
@@ -812,7 +812,6 @@
done
@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
@@INSTALL_LIB@
- @chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
@echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
@$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
@echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
@@ -1762,7 +1761,7 @@
if [ -f $(PKG_DIR)/$$pkg/Makefile ] ; then \
echo "Installing package '$$pkg'"; \
( cd $(PKG_DIR)/$$pkg; $(MAKE) install \
- "DESTDIR=$(INSTALL_ROOT)"; ) || exit $$?; \
+ "DESTDIR=$(INSTALL_ROOT)" "INSTALL_OPTIONS=-C"; ) || exit $$?; \
fi; \
fi; \
done
--- a/tools/genStubs.tcl
+++ b/tools/genStubs.tcl
@@ -280,6 +280,16 @@
puts -nonewline $out [read $in]
close $in
close $out
+
+ set old [open $file rb]
+ set new [open ${file}.new rb]
+ set unchanged [string equal [read $old] [read $new]]
+ close $old
+ close $new
+ if {$unchanged} {
+ file delete ${file}.new
+ return
+ }
file rename -force ${file}.new ${file}
return
}
--- a/pkgs/sqlite3.53.0/Makefile.in
+++ b/pkgs/sqlite3.53.0/Makefile.in
@@ -242,7 +242,6 @@
@echo "Installing documentation in $(DESTDIR)$(mandir)"
@list='$(srcdir)/doc/*.n'; for i in $$list; do \
echo "Installing $$i"; \
- rm -f "$(DESTDIR)$(mandir)/mann/`basename $$i`"; \
$(INSTALL_DATA) $$i "$(DESTDIR)$(mandir)/mann" ; \
done
+2 -1
View File
@@ -87,7 +87,8 @@ if (TK_DO_BUILD)
set(TK_PATCH_FILES "${CMAKE_CURRENT_SOURCE_DIR}/tk_manifest.patch")
if (NOT MSVC)
list(APPEND TK_PATCH_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/tk_unix_build.patch")
"${CMAKE_CURRENT_SOURCE_DIR}/tk_unix_build.patch"
"${CMAKE_CURRENT_SOURCE_DIR}/tk_incremental_install.patch")
endif ()
if (WIN32)
list(APPEND TK_PATCH_FILES
+56
View File
@@ -0,0 +1,56 @@
--- a/unix/Makefile.in
+++ b/unix/Makefile.in
@@ -222,9 +222,9 @@
INSTALL_STRIP_PROGRAM = strip
INSTALL_STRIP_LIBRARY = strip -x
-INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c
+INSTALL = $(SHELL) $(UNIX_DIR)/install-sh -c -C
INSTALL_PROGRAM = ${INSTALL}
-INSTALL_LIBRARY = ${INSTALL}
+INSTALL_LIBRARY = ${INSTALL} -m 644
INSTALL_DATA = ${INSTALL} -m 644
INSTALL_DATA_DIR = ${INSTALL} -d -m 755
@@ -727,7 +727,6 @@
done;
@if test "x$(TK_SHARED_BUILD)" = "x1"; then \
echo "Creating package index $(PKG_INDEX)"; \
- rm -f "$(PKG_INDEX)"; \
(\
echo "if {![package vsatisfies [package provide Tcl] 8.6.0]} return";\
relative=`echo | awk '{ORS=" "; split("$(TK_PKG_DIR)",a,"/"); for (f in a) {print ".."}}'`;\
@@ -741,11 +740,15 @@
echo " package ifneeded Tk $(MAJOR_VERSION).$(MINOR_VERSION)$(PATCH_LEVEL) [list load [file normalize [file join \$$dir $${relative}.. bin tk${MAJOR_VERSION}${MINOR_VERSION}.dll]]]";\
echo "}";\
fi \
- ) > "$(PKG_INDEX)"; \
+ ) > "$(PKG_INDEX).new"; \
+ if cmp "$(PKG_INDEX)" "$(PKG_INDEX).new" >/dev/null 2>&1; then \
+ rm -f "$(PKG_INDEX).new"; \
+ else \
+ mv -f "$(PKG_INDEX).new" "$(PKG_INDEX)"; \
+ fi; \
fi
@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
@@INSTALL_LIB@
- @chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
@if test -f "tk${MAJOR_VERSION}${MINOR_VERSION}.dll"; then \
$(INSTALL_LIBRARY) "tk${MAJOR_VERSION}${MINOR_VERSION}.dll" "$(DLL_INSTALL_DIR)";\
chmod 555 "$(DLL_INSTALL_DIR)/tk${MAJOR_VERSION}${MINOR_VERSION}.dll";\
@@ -814,8 +817,14 @@
@for i in $(TOP_DIR)/library/demos/*; \
do \
if [ -f $$i ] ; then \
+ dest="$(DEMO_INSTALL_DIR)/`basename $$i`"; \
sed -e '3 s|exec wish|exec wish$(VERSION)|' \
- $$i > "$(DEMO_INSTALL_DIR)"/`basename $$i`; \
+ $$i > "$$dest.new"; \
+ if cmp "$$dest" "$$dest.new" >/dev/null 2>&1; then \
+ rm -f "$$dest.new"; \
+ else \
+ mv -f "$$dest.new" "$$dest"; \
+ fi; \
fi; \
done;
@for i in $(DEMOPROGS); \