Skip to content

FetchContent: Invoke steps directly and avoid a separate sub-build

Craig Scott requested to merge craig.scott/cmake:fetchcontent-performance into master

The main motivation for this set of changes is to significantly improve the performance of FetchContent, especially for the case where the content is already populated and up-to-date. The effect will be most noticeable for platforms or generators that are known to be slow when configuring a build (Visual Studio and Xcode), but all generators and platforms should show substantial benefit.

Significant refactoring of the ExternalProject module was needed to be able to avoid requiring a sub-build. Previously, all information was stored on the main target, but there is no target when FetchContent doesn't create a sub-build. The refactoring split out the logic to operate on variables that follow the same naming convention instead, allowing the scripts to be defined without needing a target.

To improve robustness and simplify the implementation, the ExternalProject argument parsing was also updated. Previously, it scanned the module's documentation at runtime to extract the list of supported keywords. It did this every time the ExternalProject module was included and it required that inclusion to be done in the current scope or one of its parents. A one-time local change was made to print out the set of keywords that was being extracted and these were converted to hard-coded lists. The argument parsing now follows a more conventional pattern and doesn't rely on scanning the documentation at runtime. It also allowed the module to make itself able to be included once globally and short-circuit subsequent inclusions, since no there are no longer any assumptions about scope visibility. The module doesn't save any variables in the local scope, it only defines commands and global properties upon inclusion.

The refactoring also made the way each of the steps was implemented more consistent. This had the nice side effect of fixing #21748 (closed) because we record more information in the repository info file now and we always create that file for every download method.

The implementation of the configure, build, install and test steps has been largely left alone. They could be refactored in the future to follow a similar pattern to the mkdir, download, update and patch steps, but there is already a lot of change here. Furthermore, these steps may refer to the special token $(MAKE), which complicates their handling somewhat. A brief forum discussion concluded that we can probably remove much of that complication associated with how some cygwin-specific aspects are currently implemented, but are probably no longer needed. That logic hasn't been carried over to the download, update and patch steps, based on that discussion.

Merge request reports