build: Fix stale FFmpeg libs not restaged after decoder config change - #1388
Open
bernie-laberge wants to merge 1 commit into
Open
build: Fix stale FFmpeg libs not restaged after decoder config change#1388bernie-laberge wants to merge 1 commit into
bernie-laberge wants to merge 1 commit into
Conversation
bernie-laberge
requested review from
cedrik-fuoco-adsk and
eloisebrosseau
as code owners
August 21, 2026 20:57
eloisebrosseau
approved these changes
Aug 21, 2026
bernie-laberge
force-pushed
the
fix/ffmpeg-stage-rebuild
branch
2 times, most recently
from
August 22, 2026 10:10
eb47025 to
ca3329b
Compare
RV_STAGE_DEPENDENCY_LIBS only depended on the FFmpeg ExternalProject's
target name, which CMake treats as an order-only dependency for
non-executable/library targets. So after e.g.
`rvcfg -DRV_FFMPEG_NON_FREE_DECODERS_TO_ENABLE="aac"` and a rebuild,
FFmpeg itself was correctly reconfigured and rebuilt with AAC enabled,
but the freshly rebuilt libavcodec/libavformat were never copied into
the stage directory, since the staged output filenames didn't change
and Ninja considered the copy already up to date.
Add the resolved source library paths (the same paths registered as
BUILD_BYPRODUCTS on the ExternalProject) to the staging custom
command's DEPENDS, giving it a real file-level dependency. This is a
shared macro used by 14 dependencies besides FFmpeg, so all of them
now correctly restage when rebuilt from source.
Also touch the staged outputs at the end of the staging command:
copy_if_different skips the copy when a rebuilt dependency produced
byte-identical output, which would leave the staged files older than
the sources they now depend on and keep the command dirty on every
build. macOS happens to avoid this because install_name_tool and
codesign always rewrite the staged file, but Linux and Windows do not.
Finally, remove the dead _force_rebuild / BUILD_ALWAYS mechanism from
ffmpeg.cmake. `SET(${_force_rebuild} ...)` dereferenced an undefined
variable, so BUILD_ALWAYS was silently never set. Actually enabling it
is harmful: BUILD_ALWAYS marks the build and install stamps SYMBOLIC,
so FFmpeg's make/make install re-run on every single build and dirty
every downstream link edge. It is also unnecessary, since
ExternalProject already writes the resolved CONFIGURE_COMMAND to
<target>-cfgcmd.txt and makes it a file dependency of the configure
stamp, which is what actually triggers the rebuild when the decoder
options change.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Bernard Laberge <bernard.laberge@autodesk.com>
bernie-laberge
force-pushed
the
fix/ffmpeg-stage-rebuild
branch
from
August 22, 2026 10:18
ca3329b to
d35565f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Linked issues
Related to #689 (may also need a docs fix for the
prores_ksvsproresdecoder name).Summarize your change.
When a developer reconfigures with a changed
RV_FFMPEG_NON_FREE_DECODERS_TO_ENABLE(e.g.
rvcfg -DRV_FFMPEG_NON_FREE_DECODERS_TO_ENABLE="aac") and rebuilds, the freshlyrebuilt FFmpeg libraries were never copied into the stage directory, so the running app
kept using the old binaries with the decoder still disabled.
Describe the reason for the change.
1. Staging never re-ran (the reported bug).
RV_STAGE_DEPENDENCY_LIBS(incmake/macros/rv_stage_dependency_libs.cmake) stagedFFmpeg's libraries via a custom command whose
DEPENDSonly referenced theRV_DEPS_FFMPEGExternalProjecttarget name. CMake only creates an order-onlydependency for a target like this (not an executable/library), so once the staged
output filenames already existed from a prior build, Ninja considered the copy command
up to date and skipped it — even though FFmpeg itself was correctly reconfigured and
rebuilt with the new decoder enabled.
The fix adds the resolved source library paths (the same paths already registered as
BUILD_BYPRODUCTSon the FFmpegExternalProject) to the staging custom command'sDEPENDS, giving it a real file-level dependency. This macro is shared by 14 otherdependencies (boost, openssl, zlib, etc.), so they all benefit from the same
correctness fix, not just FFmpeg.
2. Staged outputs are now touched.
copy_if_differentskips the copy when a rebuilt dependency produced byte-identicaloutput, which would leave the staged files older than the sources they now depend on
and keep the staging command dirty on every build. macOS happens to avoid this because
install_name_tool+codesignalways rewrite the staged file, but Linux and Windowsdo not (
rv_create_soname_symlink.cmakeonly creates a symlink). A finalcmake -E touch_nocreateon the staged outputs makes the graph converge on allplatforms.
3. Removed the dead
_force_rebuild/BUILD_ALWAYSmechanism inffmpeg.cmake.SET(${_force_rebuild} ...)dereferenced an undefined variable, soBUILD_ALWAYSwassilently never set. Actually enabling it turns out to be actively harmful:
BUILD_ALWAYSmakes CMake mark the ExternalProject build/install stamps
SYMBOLIC(dropping theircmake -E touch), so FFmpeg'smake/make installre-run on every build and dirtyevery downstream link edge — a perpetual rebuild loop. It is also unnecessary:
ExternalProject already writes the resolved
CONFIGURE_COMMANDto<target>-cfgcmd.txtand makes it a file dependency of the configure stamp, and that is what actually
triggers the reconfigure+rebuild when the decoder options change. So the whole mechanism
(including the now-unused
RV_FFMPEG_CONFIG_OPTIONS_CACHE) is removed, with a commentto stop it being reintroduced.
Describe what you have tested and on which operating system.
Tested on macOS (arm64, Ninja, FFmpeg 8):
pre-commit run cmake-formaton both changed files.cmake -E touch <stamp>(i.e.BUILD_ALWAYSis gone), matching the DAV1D/OpenSSL edges.0 edges to an up-to-date build (previously
make install+ staging + ~77 relinksevery single time). The residual edges in an idle build come from the pre-existing
RV_DEPS_IMGUIgit-update cascade, which is unrelated to this PR.RV_DEPS_FFMPEG/install/lib/libavcodec.62.dylibandconfirmed the staging command re-ran and the staged
stage/app/RV.app/Contents/lib/libavcodec.62.dylibwas actually refreshed, then thatthe build converged again on the next run.
Not tested: Windows and Linux. In particular the Windows import-lib branch and the
touch_nocreateconvergence path (which only matters on Linux/Windows) were notexercised locally — worth confirming in CI.
Add a list of changes, and note any that might need special attention during the review.
cmake/macros/rv_stage_dependency_libs.cmakeTARGET_LIBSsource paths to the stagingADD_CUSTOM_COMMAND'sDEPENDStouch_nocreatethe staged outputs so the graph converges whencopy_if_differentskipscmake/dependencies/ffmpeg.cmake_force_rebuild/BUILD_ALWAYS/RV_FFMPEG_CONFIG_OPTIONS_CACHEmechanismPlease pay attention to the Linux/Windows behaviour of the two staging changes, since
both were only verified on macOS.
If possible, provide screenshots.
N/A (build-system change).