The branch main has been updated by kevans: URL: https://cgit.FreeBSD.org/src/commit/?id=0090096e52738383d6bf48ed5d27dffc850c8a01
commit 0090096e52738383d6bf48ed5d27dffc850c8a01 Author: Kyle Evans <kev...@freebsd.org> AuthorDate: 2025-08-15 04:43:42 +0000 Commit: Kyle Evans <kev...@freebsd.org> CommitDate: 2025-08-15 04:43:42 +0000 build: introduce the notion of a build epoch Idea and file format shamelessly stolen from CheriBSD, but reimplemented in terms of the standard FreeBSD build system. We'll use this in some events that call for a deeper cleansing, typically reserved for situations where the dependencies are too complicated to unwind. This notably does not preclude us from doing separate cleansing of world for specific src.conf(5) knob changes that would require a rebuild. In the FreeBSD version, we either stamp the OBJTOP we're cleaning (bootstrap or the full OBJDIR) with the current epoch and bail out for unstamped objdirs, or we compare and either `rm -rf` or `cleandir` as necessary. Reviewed by: brooks, des Differential Revision: https://reviews.freebsd.org/D51848 --- .clean_build_epoch | 7 ++++ Makefile.inc1 | 5 ++- tools/build/depend-cleanup.sh | 85 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 4 deletions(-) diff --git a/.clean_build_epoch b/.clean_build_epoch new file mode 100644 index 000000000000..74cb650f0015 --- /dev/null +++ b/.clean_build_epoch @@ -0,0 +1,7 @@ +# Add a new line containing a larger number than the last (e.g. YYYYMMDD) for +# every change that breaks ABI or requires a full rebuild for some other reason. +# Only the last entry is required, but having the full list may be useful for +# looking at frequency of ABI breakage, etc. + +# 4757b351ea9: openssl: Import version 3.5.1 +20250807 # All OpenSSL-using bits need rebuilt diff --git a/Makefile.inc1 b/Makefile.inc1 index e67bc7f5d1b1..cf32248b6b9d 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1082,7 +1082,7 @@ _cleanobj_fast_depend_hack: .PHONY @echo ">>> Deleting stale dependencies..."; MACHINE=${MACHINE} MACHINE_ARCH=${MACHINE_ARCH} \ ALL_libcompats=${_ALL_libcompats:Q} \ - sh ${.CURDIR}/tools/build/depend-cleanup.sh ${OBJTOP} + sh ${.CURDIR}/tools/build/depend-cleanup.sh ${OBJTOP} ${SRCTOP} _cleanworldtmp: .PHONY .if ${MK_CLEAN} == "yes" @@ -1175,7 +1175,8 @@ _cleanobj: ${_+_}cd ${.CURDIR}; ${LIB${LIBCOMPAT}WMAKE} _NO_INCLUDE_COMPILERMK=t -f Makefile.inc1 ${CLEANDIR} .endfor .else - ${_+_}cd ${.CURDIR}; ${WMAKE} _NO_INCLUDE_COMPILERMK=t _cleanobj_fast_depend_hack + ${_+_}cd ${.CURDIR}; env CLEANMK="_NO_INCLUDE_COMPILERMK=t ${CLEANDIR}" \ + MAKE=${MAKE} ${WMAKE} _cleanobj_fast_depend_hack .endif # ${MK_CLEAN} == "yes" _obj: @echo diff --git a/tools/build/depend-cleanup.sh b/tools/build/depend-cleanup.sh index c2cb7877dd04..cd51c59ff0e1 100755 --- a/tools/build/depend-cleanup.sh +++ b/tools/build/depend-cleanup.sh @@ -63,6 +63,10 @@ # if [ "$MACHINE_ARCH" = "amd64" ]; then # clean_dep lib/libc bcmp c # fi +# +# We also have a big hammer at the top of the tree, .clean_build_epoch, to be +# used in severe cases where we can't surgically remove just the parts that +# need rebuilt. This should be used sparingly. set -e set -u @@ -80,7 +84,7 @@ err() usage() { - echo "usage: $(basename $0) [-v] [-n] objtop" >&2 + echo "usage: $(basename $0) [-v] [-n] objtop srctop" >&2 } VERBOSE= @@ -101,17 +105,31 @@ while getopts vn o; do done shift $((OPTIND-1)) -if [ $# -ne 1 ]; then +if [ $# -ne 2 ]; then usage exit 1 fi OBJTOP=$1 shift +SRCTOP=$1 +shift + if [ ! -d "$OBJTOP" ]; then err "$OBJTOP: Not a directory" fi +if [ ! -d "$SRCTOP" -o ! -f "$SRCTOP/Makefile.inc1" ]; then + err "$SRCTOP: Not the root of a src tree" +fi + +: ${CLEANMK=""} +if [ -n "$CLEANMK" ]; then + if [ -z "${MAKE+set}" ]; then + err "MAKE not set" + fi +fi + if [ -z "${MACHINE+set}" ]; then err "MACHINE not set" fi @@ -151,6 +169,69 @@ clean_dep() done } +extract_epoch() +{ + [ -s "$1" ] || return 0 + + awk 'int($1) > 0 { epoch = $1 } END { print epoch }' "$1" +} + +clean_world() +{ + local buildepoch="$1" + + # The caller may set CLEANMK in the environment to make target(s) that + # should be invoked instead of just destroying everything. This is + # generally used after legacy/bootstrap tools to avoid over-cleansing + # since we're generally in the temporary tree's ancestor. + if [ -n "$CLEANMK" ]; then + echo "Cleaning up the object tree" + run $MAKE -C "$SRCTOP" -f "$SRCTOP"/Makefile.inc1 $CLEANMK + else + echo "Cleaning up the temporary build tree" + run rm -rf "$OBJTOP" + fi + + # We don't assume that all callers will have grabbed the build epoch, so + # we'll do it here as needed. This will be useful if we add other + # non-epoch reasons to force clean. + if [ -z "$buildepoch" ]; then + buildepoch=$(extract_epoch "$SRCTOP"/.clean_build_epoch) + fi + + mkdir -p "$OBJTOP" + echo "$buildepoch" > "$OBJTOP"/.clean_build_epoch + + exit 0 +} + +check_epoch() +{ + local srcepoch objepoch + + srcepoch=$(extract_epoch "$SRCTOP"/.clean_build_epoch) + if [ -z "$srcepoch" ]; then + err "Malformed .clean_build_epoch; please validate the last line" + fi + + # We don't discriminate between the varying degrees of difference + # between epochs. If it went backwards we could be bisecting across + # epochs, in which case the original need to clean likely still stands. + objepoch=$(extract_epoch "$OBJTOP"/.clean_build_epoch) + if [ -z "$objepoch" ] || [ "$srcepoch" -ne "$objepoch" ]; then + if [ "$VERBOSE" ]; then + echo "Cleaning - src epoch: $srcepoch, objdir epoch: ${objepoch:-unknown}" + fi + + clean_world "$srcepoch" + # NORETURN + fi +} + +check_epoch + +#### Typical dependency cleanup begins here. + # Date Rev Description # 20220326 fbc002cb72d2 move from bcmp.c to bcmp.S