Skip to content

Commit

Permalink
CMake: Reconfigure faster by not looking for missing packages
Browse files Browse the repository at this point in the history
Instead of constantly trying to find packages by calling
qt_find_package on each reconfiguration, record which packages were
found during initial configuration. Then on a second reconfiguration,
skip looking for packages that were not found on the initial
configuration.

This speeds up reconfiguration on certain platforms and repos.

Here are some stats for my macOS qtbase build.

not skip 3.69s user 4.96s system 98% cpu 8.750 total
skip     2.69s user 1.00s system 97% cpu 3.792 total

Top-level build with -submodules=qtquick3d

not skip 15.03s user 10.58s system 97% cpu 26.334 total
skip     13.87s user 5.16s system 96% cpu 19.724 total

Note this is a behavior change from how find_package is used in most
CMake projects, where if a package was previously missing, the
developer can just install the package and reconfigure to pick it up.

With this change, they will first have to remove their CMakeCache.txt
file and configure from scratch, or remove the
QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES cache variable and reconfigure.

For this reason, we enable this behavior by default only in
-developer-builds.
Builders can also opt in or out by setting the
QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES variable to either ON or
OFF.

Note this behavior does not apply to user projects, or direct
find_package calls (as opposed to qt_find_package).

Fixes: QTBUG-107251
Change-Id: Iee9c5d120eb09e2a94eebb059a2174ef6b241e03
Reviewed-by: Kai Köhne <[email protected]>
Reviewed-by: Amir Masoud Abdol <[email protected]>
Reviewed-by: Alexey Edelev <[email protected]>
  • Loading branch information
alcroito committed Nov 29, 2022
1 parent 7f4aa1a commit 6847a19
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cmake/QtBuildInformation.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ from the build directory \n")
endif()

set(QT_INTERNAL_BUILD_INSTRUCTIONS_SHOWN "TRUE" CACHE STRING "" FORCE)

if(QT_SUPERBUILD)
qt_internal_save_previously_found_packages()
endif()
endfunction()

function(qt_configure_print_summary_helper summary_reports force_show)
Expand Down
4 changes: 4 additions & 0 deletions cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,10 @@ macro(qt_build_repo_end)
"List of the synced modules. Prevents running syncqt.cpp after the first configuring.")
endif()

if(NOT QT_SUPERBUILD)
qt_internal_save_previously_found_packages()
endif()

list(POP_BACK CMAKE_MESSAGE_CONTEXT)
endmacro()

Expand Down
46 changes: 46 additions & 0 deletions cmake/QtFindPackageHelpers.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,17 @@ macro(qt_find_package)
# qt_find_package(PNG PROVIDED_TARGET PNG::PNG) still needs to succeed and register the provided
# targets. To enable the debugging behavior, set QT_DEBUG_QT_FIND_PACKAGE to 1.
set(_qt_find_package_skip_find_package FALSE)

# Skip looking for packages that were not found on initial configuration, because they likely
# won't be found again, and only waste configuration time.
# Speeds up reconfiguration configuration for certain platforms and repos.
# Due to this behavior being different from what general CMake projects expect, it is only
# done for -developer-builds.
if(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES AND
NOT "${ARGV0}" IN_LIST QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES)
set(_qt_find_package_skip_find_package TRUE)
endif()

if(QT_DEBUG_QT_FIND_PACKAGE AND ${ARGV0}_FOUND AND arg_PROVIDED_TARGETS)
set(_qt_find_package_skip_find_package TRUE)
foreach(qt_find_package_target_name ${arg_PROVIDED_TARGETS})
Expand Down Expand Up @@ -141,6 +152,11 @@ macro(qt_find_package)
endif()
endif()

if(${ARGV0}_FOUND)
# Record that the package was found, so that future reconfigurations can be sped up.
set_property(GLOBAL APPEND PROPERTY _qt_previously_found_packages "${ARGV0}")
endif()

if(${ARGV0}_FOUND AND arg_PROVIDED_TARGETS AND NOT _qt_find_package_skip_find_package)
# If package was found, associate each target with its package name. This will be used
# later when creating Config files for Qt libraries, to generate correct find_dependency()
Expand Down Expand Up @@ -200,6 +216,36 @@ macro(qt_find_package)
endif()
endmacro()

# Save found packages in the cache. They will be read on next reconfiguration to skip looking
# for packages that were not previously found.
# Only applies to -developer-builds by default.
# Can also be opted in or opted out via QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES.
# Opting out will need two reconfigurations to take effect.
function(qt_internal_save_previously_found_packages)
if(DEFINED QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES)
set(should_save "${QT_INTERNAL_SAVE_PREVIOUSLY_FOUND_PACKAGES}")
else()
if(FEATURE_developer_build OR QT_FEATURE_developer_build)
set(should_save ON)
else()
set(should_save OFF)
endif()
endif()

if(NOT should_save)
# When the value is flipped to OFF, remove any previously saved packages.
unset(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES CACHE)
return()
endif()

get_property(_qt_previously_found_packages GLOBAL PROPERTY _qt_previously_found_packages)
if(_qt_previously_found_packages)
list(REMOVE_DUPLICATES _qt_previously_found_packages)
set(QT_INTERNAL_PREVIOUSLY_FOUND_PACKAGES "${_qt_previously_found_packages}" CACHE INTERNAL
"List of CMake packages found during configuration using qt_find_package.")
endif()
endfunction()

# Return qmake library name for the given target, e.g. return "vulkan" for "Vulkan::Vulkan".
function(qt_internal_map_target_to_qmake_lib target out_var)
set(${out_var} "${QT_QMAKE_LIB_OF_TARGET_${target}}" PARENT_SCOPE)
Expand Down

0 comments on commit 6847a19

Please sign in to comment.