From c81b0a38d684c91763aae71e9d5d3c43cbcc5695 Mon Sep 17 00:00:00 2001 From: Levon Gevorgyan Date: Sun, 26 Oct 2025 13:37:48 -0500 Subject: [PATCH] only rebuild when metadata is different --- README.md | 58 ++++++++++++++-------------- lib/build.sh | 104 +++++++++++++++++++++++++++++++++++++------------- lib/readme.sh | 2 +- lib/utils.sh | 17 +++++++-- main.sh | 10 +---- 5 files changed, 122 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index 3602e16..b2c559d 100644 --- a/README.md +++ b/README.md @@ -12,34 +12,36 @@ Tested on: ```bash ~~~ Usable Commands ~~~ -print_cmds: - print usable commands -do_build: - build a specific project -build: - build ffmpeg with desired configuration -docker_build_image: - build docker image with required dependencies pre-installed -docker_save_image: - save docker image into tar.zst -docker_load_image: - load docker image from tar.zst -docker_run_image: - run docker image with given flags -build_with_docker: - run docker image with given flags -docker_build_multiarch_image: - build multiarch docker image -efg: - estimate the film grain of a given file -encode: - encode a file using libsvtav1_psy and libopus -print_pkg_mgr: - print out evaluated package manager commands and required packages -install_deps: - install required dependencies -gen_readme: - generate project README.md +print_cmds: + print usable commands +do_build: + build a specific project +build: + build ffmpeg with desired configuration +docker_build_image: + build docker image with required dependencies pre-installed +docker_save_image: + save docker image into tar.zst +docker_load_image: + load docker image from tar.zst +docker_run_image: + run docker image with given flags +build_with_docker: + run docker image with given flags +docker_build_multiarch_image: + build multiarch docker image +efg: + estimate the film grain of a given file +encode: + encode a file using libsvtav1_psy and libopus +print_pkg_mgr: + print out evaluated package manager commands and required packages +install_deps: + install required dependencies +package: + package ffmpeg build +gen_readme: + generate project README.md ``` diff --git a/lib/build.sh b/lib/build.sh index f0d1aee..20fa165 100644 --- a/lib/build.sh +++ b/lib/build.sh @@ -3,13 +3,23 @@ set_compile_opts() { test "$FB_COMPILE_OPTS_SET" == 1 && return 0 - unset LDFLAGS C_FLAGS CXX_FLAGS CPP_FLAGS \ - CONFIGURE_FLAGS MESON_FLAGS \ - RUSTFLAGS CMAKE_FLAGS \ - FFMPEG_EXTRA_FLAGS \ + EXPORTED_ENV_NAMES=( + LDFLAGS + C_FLAGS + CXX_FLAGS + CPP_FLAGS + RUSTFLAGS + ) + BUILD_ENV_NAMES=( + "${EXPORTED_ENV_NAMES[@]}" + CONFIGURE_FLAGS + MESON_FLAGS + CMAKE_FLAGS + FFMPEG_EXTRA_FLAGS CARGO_CINSTALL_FLAGS - export LDFLAGS C_FLAGS CXX_FLAGS CPP_FLAGS \ - RUSTFLAGS PATH + ) + unset "${BUILD_ENV_NAMES[@]}" + export "${EXPORTED_ENV_NAMES[@]}" # set job count for all builds JOBS="$(nproc)" @@ -373,27 +383,64 @@ do_build() { get_build_conf "${build}" || return 1 download_release || return 1 - # start build - echo_info -n "building ${build} " + # save the metadata for a build to skip re-building identical builds + local oldMetadataFile="${TMP_DIR}/${build}-old-metadata" + local newMetadataFile="${TMP_DIR}/${build}-new-metadata" + + # add build function, version, url, and top-level env to metadata + type "build_${build}" >"${oldMetadataFile}" + echo "ver: ${ver}" >>"${oldMetadataFile}" + echo "url: ${url}" >>"${oldMetadataFile}" + for envName in "${BUILD_ENV_NAMES[@]}"; do + COLOR=OFF dump_arr "${envName}" >>"${oldMetadataFile}" + done + + # only ffmpeg cares about ENABLE and has special function + if [[ ${build} == 'ffmpeg' ]]; then + # shellcheck disable=SC2153 + echo "ENABLE=${ENABLE}" >>"${oldMetadataFile}" + type add_project_versioning_to_ffmpeg >>"${oldMetadataFile}" + fi + + # prepare build pushd "$extracted_dir" >/dev/null || return 1 # check for any patches for patch in "${PATCHES_DIR}/${build}"/*.patch; do test -f "${patch}" || continue echo_if_fail patch -p1 -i "${patch}" || return 1 + echo "patch:${patch}" >>"${oldMetadataFile}" done - export LOGNAME="${build}" - local timeBefore=${EPOCHSECONDS} - echo_if_fail build_"${build}" & - local buildPid=$! - spinner & - local spinPid=$! - wait ${buildPid} - retval=$? - kill ${spinPid} - spinner reset - popd >/dev/null || return 1 - test ${retval} -eq 0 || return ${retval} - echo_pass "built ${build} in $((EPOCHSECONDS - timeBefore)) seconds" + + # rebuild if metadata is different + local oldMetadata="$(<"${oldMetadataFile}")" + local newMetadata='' + test -f "${newMetadataFile}" && newMetadata="$(<"${newMetadataFile}")" + if [[ ${oldMetadata} != "${newMetadata}" ]]; then + echo_info -n "building ${build} " + # build in background + local timeBefore=${EPOCHSECONDS} + LOGNAME="${build}" echo_if_fail "build_${build}" & + local buildPid=$! + # start spinner + spinner & + local spinPid=$! + # get build return code + wait ${buildPid} + local retval=$? + # stop spinner + kill ${spinPid} + spinner reset + + popd >/dev/null || return 1 + test ${retval} -eq 0 || return ${retval} + echo_pass "built ${build} in $((EPOCHSECONDS - timeBefore)) seconds" + else + popd >/dev/null || return 1 + echo_info "re-using identical previous build for ${build}" + fi + + # update build metadata + cp "${oldMetadataFile}" "${newMetadataFile}" } FB_FUNC_NAMES+=('build') @@ -421,16 +468,17 @@ build() { for build in ${ENABLE}; do do_build "${build}" || return 1 done - do_build "ffmpeg" || return 1 + do_build ffmpeg || return 1 + local ffmpegBin="${PREFIX}/bin/ffmpeg" # run ffmpeg to show completion - "${PREFIX}/bin/ffmpeg" + "${ffmpegBin}" -version # suggestion for path hash -r local ffmpeg="$(command -v ffmpeg 2>/dev/null)" - if [[ ${ffmpeg} != "${PREFIX}/bin/ffmpeg" ]]; then + if [[ ${ffmpeg} != "${ffmpegBin}" ]]; then echo - echo_warn "ffmpeg in path (${ffmpeg}) is not the built one (${PREFIX}/bin/ffmpeg)" + echo_warn "ffmpeg in path (${ffmpeg}) is not the built one (${ffmpegBin})" echo_info "consider adding ${PREFIX}/bin to \$PATH" echo "echo 'export PATH=\"${PREFIX}/bin:\$PATH\"' >> ~/.bashrc" fi @@ -840,12 +888,13 @@ add_project_versioning_to_ffmpeg() { return 0 } build_ffmpeg() { + add_project_versioning_to_ffmpeg || return 1 + + # libsvtav1_psy real name is libsvtav1 for enable in ${ENABLE}; do test "${enable}" == 'libsvtav1_psy' && enable='libsvtav1' CONFIGURE_FLAGS+=("--enable-${enable}") done - add_project_versioning_to_ffmpeg || return 1 - # lto is broken on darwin for ffmpeg only # https://trac.ffmpeg.org/ticket/11479 local ffmpegFlags=() @@ -870,6 +919,7 @@ build_ffmpeg() { --disable-txtpages \ --disable-ffplay \ --disable-autodetect \ + --extra-version="${ver}" \ --enable-runtime-cpudetect || return 1 ccache make -j"${JOBS}" || return 1 ${SUDO_MODIFY} make -j"${JOBS}" install || return 1 diff --git a/lib/readme.sh b/lib/readme.sh index 5eece6d..865a047 100644 --- a/lib/readme.sh +++ b/lib/readme.sh @@ -14,7 +14,7 @@ $(printf ' - %s\n' "${VALID_DOCKER_IMAGES[@]}") - darwin aarch64 \`\`\`bash -$(print_cmds false) +$(COLOR=OFF print_cmds) \`\`\` " >"${readme}" diff --git a/lib/utils.sh b/lib/utils.sh index 7d5fa24..23e63f2 100644 --- a/lib/utils.sh +++ b/lib/utils.sh @@ -16,7 +16,16 @@ echo_wrapper() { args=("$1") shift fi - echo -e "${args[@]}" "${color}${word}${NC}" "$@" + # COLOR is override for using ${color} + # shellcheck disable=SC2153 + if [[ ${COLOR} == 'OFF' ]]; then + color='' + endColor='' + else + endColor="${NC}" + fi + + echo -e "${args[@]}" "${color}${word:-''}${endColor}" "$@" } echo_fail() { color="${RED}" word="FAIL" echo_wrapper "$@"; } echo_info() { color="${CYAN}" word="INFO" echo_wrapper "$@"; } @@ -31,11 +40,11 @@ void() { echo "$@" >/dev/null; } echo_if_fail() { local cmd=("$@") local logName="${LOGNAME:-${RANDOM}}-" - local out="${TMP_DIR}/.${logName}stdout" - local err="${TMP_DIR}/.${logName}stderr" + local out="${TMP_DIR}/${logName}stdout" + local err="${TMP_DIR}/${logName}stderr" # set trace to the cmdEvalTrace and open file descriptor - local cmdEvalTrace="${TMP_DIR}/.${logName}cmdEvalTrace" + local cmdEvalTrace="${TMP_DIR}/${logName}cmdEvalTrace" test -d "${TMP_DIR}" || mkdir -p "${TMP_DIR}" exec 5>"${cmdEvalTrace}" export BASH_XTRACEFD=5 diff --git a/main.sh b/main.sh index 8e96ea5..ba841e6 100755 --- a/main.sh +++ b/main.sh @@ -55,17 +55,9 @@ $cmd "$@"' >"${ENTRY_SCRIPT}" FB_FUNC_NAMES+=('print_cmds') FB_FUNC_DESCS['print_cmds']='print usable commands' print_cmds() { - local color="${1:-true}" - local uncolor='' - if [[ ${color} == true ]]; then - color="${CYAN}" - uncolor="${NC}" - else - color='' - fi echo -e "~~~ Usable Commands ~~~\n" for funcname in "${FB_FUNC_NAMES[@]}"; do - echo -e "${color}${funcname}${uncolor}:\n\t" "${FB_FUNC_DESCS[${funcname}]}" + color="${CYAN}" word="${funcname}:" echo_wrapper "\n\t${FB_FUNC_DESCS[${funcname}]}" if [[ $FB_RUNNING_AS_SCRIPT -eq 0 ]]; then (cd "$SCRIPT_DIR" && ln -sf entry.sh "${funcname}.sh") fi