summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2020-10-02 15:38:47 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2020-10-06 10:07:05 +0200
commit07b6d3367debd8f15974abf0f5cdf48f0fe3a536 (patch)
tree9785c58624928e0aab42c7f49b6dbc02e0bf9d69
parente6fd92816dcbddcd9c28676815cf134b31291ea9 (diff)
CMake: Refactor optimization flag handling and add optimize_full
Introduce a bunch of helper functions to manipulate compiler flags and linker flags for the CMAKE_<LANG>_FLAGS_<CONFIG> and CMAKE_<LINK_TYPE>_LINKER_FLAGS_<CONFIG> CMake variables. These variables can be assigned and modified either in the cache or for a specific subdirectory scope, which will apply the flags only to targets in that scope. Add qt_internal_add_optimize_full_flags() function which mimics qmake's CONFIG += optimize_full behavior. Calling it will force usage of the '-O3' optimization flag on supported platforms (falling back '-O2' where not supported). Use the function for the Core and Gui subdirectories, to enable full optimization for the respective Qt modules as it is done in the qmake projects. To ensure that the global qmake-like compiler flags are assigned eveywhere, qt_internal_set_up_config_optimizations_like_in_qmake() needs to be called after Qt global features like optimize_size and optimize_full are available. This means that qtbase and its standalone tests need some special handling in regards to when to call that function. Task-number: QTBUG-86866 Change-Id: Ic7ac23de0265561cb06a0ba55089b6c0d3347441 Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
-rw-r--r--CMakeLists.txt10
-rw-r--r--cmake/QtBuildInternals/QtBuildInternalsConfig.cmake5
-rw-r--r--cmake/QtFindPackageHelpers.cmake4
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake530
-rw-r--r--src/corelib/CMakeLists.txt5
-rw-r--r--src/gui/CMakeLists.txt5
-rw-r--r--src/winmain/CMakeLists.txt6
-rw-r--r--tests/CMakeLists.txt10
8 files changed, 514 insertions, 61 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b089814803..d0014b5363 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,6 +83,13 @@ if(NOT QT_BUILD_STANDALONE_TESTS)
# Needed when building qtbase for android.
include(src/corelib/Qt6AndroidMacros.cmake)
+ # Set up optimization flags like in qmake.
+ # This function must be called after the global QT_FEATURE_xxx variables have been set up,
+ # aka after QtBaseGlobalTargets is processed.
+ # It also has to be called /before/ adding add_subdirectory(src), so that per-directory
+ # modifications can still be applied if necessary (like in done in Core and Gui).
+ qt_internal_set_up_config_optimizations_like_in_qmake()
+
## Setup documentation
add_subdirectory(doc)
@@ -122,9 +129,6 @@ endif()
qt_build_repo_end()
-# This function must be called after the QT_FEATURE_xxx variables have been set up.
-qt_internal_set_up_config_optimizations_like_in_qmake()
-
if(NOT QT_BUILD_STANDALONE_TESTS AND BUILD_EXAMPLES)
add_subdirectory(examples)
if(QT_NO_MAKE_EXAMPLES)
diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
index 529b83ff73..84273b5e9e 100644
--- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
+++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake
@@ -201,6 +201,11 @@ macro(qt_enable_cmake_languages)
endif()
endforeach()
+ # The qtbase call is handled in qtbase/CMakeLists.txt.
+ # This call is used for projects other than qtbase, including for other project's standalone
+ # tests.
+ # Because the function uses QT_FEATURE_foo values, it's important that find_package(Qt6Core) is
+ # called before this function. but that's usually the case for Qt repos.
if(NOT PROJECT_NAME STREQUAL "QtBase")
qt_internal_set_up_config_optimizations_like_in_qmake()
endif()
diff --git a/cmake/QtFindPackageHelpers.cmake b/cmake/QtFindPackageHelpers.cmake
index c68ba4d14a..d2bacd48cc 100644
--- a/cmake/QtFindPackageHelpers.cmake
+++ b/cmake/QtFindPackageHelpers.cmake
@@ -57,6 +57,7 @@ macro(qt_find_package)
# Re-append components to forward them.
list(APPEND arg_UNPARSED_ARGUMENTS "COMPONENTS;${arg_COMPONENTS}")
endif()
+ # TODO: Handle REQUIRED_COMPONENTS.
# Don't look for packages in PATH if requested to.
if(QT_NO_USE_FIND_PACKAGE_SYSTEM_ENVIRONMENT_PATH)
@@ -97,6 +98,9 @@ macro(qt_find_package)
endif()
endforeach()
+ # TODO: Handle packages with components where a previous component is already found.
+ # E.g. find_package(Qt6 COMPONENTS BuildInternals) followed by
+ # qt_find_package(Qt6 COMPONENTS Core) doesn't end up calling find_package(Qt6Core).
if (NOT ${ARGV0}_FOUND AND NOT _qt_find_package_skip_find_package)
# Unset the NOTFOUND ${package}_DIR var that might have been set by the previous
# find_package call, to get rid of "not found" messagees in the feature summary
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index a2b498bf20..db2790171d 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -245,6 +245,9 @@ function(qt_enable_utf8_sources target)
endif()
endfunction()
+# Saves the list of known optimization flags for the current compiler in out_var.
+#
+# Mostly used for removing them before adding new ones.
function(qt_internal_get_all_possible_optimization_flag_values out_var)
set(flag_values "")
set(vars QT_CFLAGS_OPTIMIZE QT_CFLAGS_OPTIMIZE_FULL
@@ -265,7 +268,35 @@ function(qt_internal_get_all_possible_optimization_flag_values out_var)
set("${out_var}" "${flag_values}" PARENT_SCOPE)
endfunction()
-function(qt_internal_print_optimization_flags_values languages configs target_link_types)
+# Return's the current compiler's optimize_full flags if available.
+# Otherwise returns the regular optimization level flag.
+function(qt_internal_get_optimize_full_flags out_var)
+ set(optimize_full_flags "${QT_CFLAGS_OPTIMIZE_FULL}")
+ if(NOT optimize_full_flags)
+ set(optimize_full_flags "${QT_CFLAGS_OPTIMIZE}")
+ endif()
+ set(${out_var} "${optimize_full_flags}" PARENT_SCOPE)
+endfunction()
+
+# Prints the compiler and linker flags for each configuration, language and target type.
+#
+# Usually it would print the cache variables, but one may also override the variables
+# in a specific directory scope, so this is useful for debugging.
+#
+# Basically dumps either scoped or cached
+# CMAKE_<LANG>_FLAGS_CONFIG> and CMAKE_<TYPE>_LINKER_FLAGS_<CONFIG> variables.
+
+function(qt_internal_print_optimization_flags_values)
+ qt_internal_get_enabled_languages_for_flag_manipulation(languages)
+ qt_internal_get_configs_for_flag_manipulation(configs)
+ qt_internal_get_target_link_types_for_flag_manipulation(target_link_types)
+
+ qt_internal_print_optimization_flags_values_helper(
+ "${languages}" "${configs}" "${target_link_types}")
+endfunction()
+
+# Helper function for printing the optimization flags.
+function(qt_internal_print_optimization_flags_values_helper languages configs target_link_types)
foreach(lang ${languages})
set(flag_var_name "CMAKE_${lang}_FLAGS")
message(STATUS "${flag_var_name}: ${${flag_var_name}}")
@@ -287,17 +318,26 @@ function(qt_internal_print_optimization_flags_values languages configs target_li
endforeach()
endfunction()
-# This function finds the optimization flags set by the default CMake modules or toolchains, and
-# replaces them with ones that Qt qmake builds expect for all the default CMAKE_BUILD_TYPE
-# configurations.
-# This normalizes things like using -O2 for both Release and RelWithDebInfo, among other flags.
-# See QTBUG-85992 for details.
-function(qt_internal_set_up_config_optimizations_like_in_qmake)
- # Allow opt out.
- if(QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS)
- return()
+# Saves the list of configs for which flag manipulation will occur.
+function(qt_internal_get_configs_for_flag_manipulation out_var)
+ set(configs RELEASE RELWITHDEBINFO MINSIZEREL DEBUG)
+
+ # Opt into additional non-standard configs for flag removal only.
+ if(QT_ADDITIONAL_OPTIMIZATION_FLAG_CONFIGS)
+ list(APPEND configs ${QT_ADDITIONAL_OPTIMIZATION_FLAG_CONFIGS})
endif()
+ set(${out_var} "${configs}" PARENT_SCOPE)
+endfunction()
+
+# Saves the list of target link types for which flag manipulation will occur.
+function(qt_internal_get_target_link_types_for_flag_manipulation out_var)
+ set(target_link_types EXE SHARED MODULE STATIC)
+ set(${out_var} "${target_link_types}" PARENT_SCOPE)
+endfunction()
+
+# Saves list of enabled languages for which it is safe to manipulate compilation flags.
+function(qt_internal_get_enabled_languages_for_flag_manipulation out_var)
# Limit flag modification to c-like code. We don't want to accidentally add incompatible
# flags to MSVC's RC or Swift.
set(languages_to_process C CXX OBJC OBJCXX)
@@ -308,70 +348,458 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
list(APPEND enabled_languages "${lang}")
endif()
endforeach()
+ set(${out_var} "${enabled_languages}" PARENT_SCOPE)
+endfunction()
- set(configs RELEASE RELWITHDEBINFO MINSIZEREL DEBUG)
- set(target_link_types EXE SHARED MODULE STATIC)
-
- # Opt into additional non-standard configs for flag removal only.
- if(QT_ADDITIONAL_OPTIMIZATION_FLAG_CONFIGS)
- list(APPEND configs ${QT_ADDITIONAL_OPTIMIZATION_FLAG_CONFIGS})
+# Removes all known compiler optimization flags for the given CONFIGS, for all enabled 'safe'
+# languages.
+#
+# IN_CACHE - remove them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - remove them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
+# LANGUAGES - optional list of languages like 'C', 'CXX', for which to remove the flags
+# if not provided, defaults to the list of enabled C-like languages
+function(qt_internal_remove_known_optimization_flags)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_remove_known_optimization_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ ""
+ "CONFIGS;LANGUAGES"
+ ${ARGN})
+
+ if(NOT arg_CONFIGS)
+ message(FATAL_ERROR
+ "You must specify at least one configuration for which to add the flags.")
endif()
- # You can set QT_DEBUG_OPTIMIZATION_FLAGS to see the before and after results.
- if(QT_DEBUG_OPTIMIZATION_FLAGS)
- message(STATUS "")
- message(STATUS "DEBUG: Original CMake optimization flags.\n")
- qt_internal_print_optimization_flags_values("${enabled_languages}" "${configs}"
- "${target_link_types}")
+ if(arg_LANGUAGES)
+ set(enabled_languages "${arg_LANGUAGES}")
+ else()
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
endif()
- # Remove known optimization flags.
qt_internal_get_all_possible_optimization_flag_values(flag_values)
+ set(configs ${arg_CONFIGS})
+
foreach(lang ${enabled_languages})
foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
foreach(flag_value ${flag_values})
- # Remove any existing optimization flags, they will be re-added later on.
string(REPLACE "${flag_value}" "" "${flag_var_name}" "${${flag_var_name}}")
string(STRIP "${${flag_var_name}}" "${flag_var_name}")
endforeach()
+
+ if(arg_IN_CACHE)
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ elseif(arg_IN_CURRENT_SCOPE)
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ else()
+ message(
+ FATAL_ERROR
+ "qt_internal_remove_known_optimization_flags expects a scope argument.")
+ endif()
endforeach()
endforeach()
+endfunction()
+
+# Adds compiler flags for the given CONFIGS either in the current scope or globally in the
+# cache.
+#
+# FLAGS - should be a single string of flags separated by spaces.
+# IN_CACHE - add them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
+# LANGUAGES - optional list of languages like 'C', 'CXX', for which to add the flags
+# if not provided, defaults to the list of enabled C-like languages
+function(qt_internal_add_compiler_flags)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_add_compiler_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ "FLAGS"
+ "CONFIGS;LANGUAGES"
+ ${ARGN})
+
+ if(NOT arg_CONFIGS)
+ message(FATAL_ERROR
+ "You must specify at least one configuration for which to add the flags.")
+ endif()
+ if(NOT arg_FLAGS)
+ message(FATAL_ERROR "You must specify at least one flag to add.")
+ endif()
+
+ if(arg_LANGUAGES)
+ set(enabled_languages "${arg_LANGUAGES}")
+ else()
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ endif()
+
+ set(configs ${arg_CONFIGS})
+
+ foreach(lang ${enabled_languages})
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+ string(APPEND "${flag_var_name}" " ${arg_FLAGS}")
+
+ if(arg_IN_CACHE)
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ elseif(arg_IN_CURRENT_SCOPE)
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ else()
+ message(
+ FATAL_ERROR
+ "qt_internal_add_compiler_flags expects a scope argument.")
+ endif()
+ endforeach()
+ endforeach()
+endfunction()
+
+# Convenience function that adds compiler flags for all release configurations.
+#
+# FLAGS - should be a single string of flags separated by spaces.
+# IN_CACHE - add them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# LANGUAGES - optional list of languages like 'C', 'CXX', for which to add the flags
+# if not provided, defaults to the list of enabled C-like languages
+function(qt_internal_add_compiler_flags_for_release_configs)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_add_compiler_flags_for_release_configs"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ "FLAGS"
+ "LANGUAGES"
+ ${ARGN})
+
+ set(args "")
+
+ if(arg_LANGUAGES)
+ set(enabled_languages "${arg_LANGUAGES}")
+ else()
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ endif()
+
+ set(configs RELEASE RELWITHDEBINFO MINSIZEREL)
+
+ list(APPEND args CONFIGS ${configs})
+
+ if(arg_FLAGS)
+ list(APPEND args FLAGS "${arg_FLAGS}")
+ endif()
+
+ if(arg_IN_CACHE)
+ list(APPEND args IN_CACHE)
+ endif()
+ if(arg_IN_CURRENT_SCOPE)
+ list(APPEND args IN_CURRENT_SCOPE)
+ endif()
+ list(APPEND args LANGUAGES ${enabled_languages})
+
+ qt_internal_add_compiler_flags(${args})
+
+ if(arg_IN_CURRENT_SCOPE)
+ foreach(lang ${enabled_languages})
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ endforeach()
+ endforeach()
+ endif()
+endfunction()
+
+# Convenience function that replaces all optimization flags with the equivalent of '-O3'
+# (optimize_full) flag for all release configs.
+#
+# This is the equivalent of qmake's CONFIG += optimize_full.
+# It is meant to be called in a subdirectory scope to enable full optimizations for a particular
+# Qt module, like Core or Gui.
+function(qt_internal_add_optimize_full_flags)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_add_optimize_full_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ ""
+ ""
+ ${ARGN})
+
+ set(args "")
+ if(arg_IN_CACHE)
+ list(APPEND args IN_CACHE)
+ endif()
+ if(arg_IN_CURRENT_SCOPE)
+ list(APPEND args IN_CURRENT_SCOPE)
+ endif()
+
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ set(configs RELEASE RELWITHDEBINFO MINSIZEREL)
+
+ qt_internal_remove_known_optimization_flags(${args} CONFIGS ${configs})
+
+ # If the respective compiler doesn't have optimize_full flags, use regular optimization flags.
+ # Mainly MSVC.
+ qt_internal_get_optimize_full_flags(optimize_full_flags)
+ list(APPEND args FLAGS "${optimize_full_flags}")
+
+ qt_internal_add_compiler_flags_for_release_configs(${args})
+
+ if(arg_IN_CURRENT_SCOPE)
+ foreach(lang ${enabled_languages})
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ endforeach()
+ endforeach()
+ endif()
+endfunction()
+
+# Convenience function to replace a compiler flag with another one, for the given configurations
+# for all enabled 'safe' languages.
+# Essentially a glorified string(REPLACE).
+# Can be used to remove compiler flags.
+#
+# match_string - string to match
+# replace_string - replacement string
+# IN_CACHE - replace them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - replace them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
+# LANGUAGES - optional list of languages like 'C', 'CXX', for which to replace the flags
+# if not provided, defaults to the list of enabled C-like languages
+function(qt_internal_replace_compiler_flags match_string replace_string)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_replace_compiler_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ ""
+ "CONFIGS;LANGUAGES"
+ ${ARGN})
+
+ if(NOT arg_CONFIGS)
+ message(FATAL_ERROR
+ "You must specify at least one configuration for which to replace the flags.")
+ endif()
+
+ if(arg_LANGUAGES)
+ set(enabled_languages "${arg_LANGUAGES}")
+ else()
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ endif()
+ set(configs ${arg_CONFIGS})
+
+ foreach(lang ${enabled_languages})
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+
+ # Handle an empty input string and an empty match string as a set().
+ if(match_string STREQUAL "" AND "${${flag_var_name}}" STREQUAL "")
+ set(${flag_var_name} "${replace_string}")
+ else()
+ string(REPLACE
+ "${match_string}" "${replace_string}"
+ "${flag_var_name}" "${${flag_var_name}}")
+ endif()
+
+ if(arg_IN_CACHE)
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ elseif(arg_IN_CURRENT_SCOPE)
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ else()
+ message(
+ FATAL_ERROR
+ "qt_internal_replace_compiler_flags expects a scope argument.")
+ endif()
+ endforeach()
+ endforeach()
+endfunction()
+
+# Convenience function to add linker flags, for the given configurations and target link types.
+#
+# FLAGS - should be a single string of flags separated by spaces.
+# IN_CACHE - add them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
+# TYPES - should be a list of target link types as expected by CMake's
+# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
+# e.g EXE, MODULE, SHARED, STATIC.
+function(qt_internal_add_linker_flags)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_add_linker_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ "FLAGS"
+ "CONFIGS;TYPES"
+ ${ARGN})
+
+ if(NOT arg_TYPES)
+ message(FATAL_ERROR
+ "You must specify at least one linker target type for which to add the flags.")
+ endif()
+ if(NOT arg_CONFIGS)
+ message(FATAL_ERROR
+ "You must specify at least one configuration for which to add the flags.")
+ endif()
+ if(NOT arg_FLAGS)
+ message(FATAL_ERROR "You must specify at least one flag to add.")
+ endif()
+
+ set(configs ${arg_CONFIGS})
+ set(target_link_types ${arg_TYPES})
+
+ foreach(config ${configs})
+ foreach(t ${target_link_types})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
+ string(APPEND "${flag_var_name}" " ${arg_FLAGS}")
+
+ if(arg_IN_CACHE)
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ elseif(arg_IN_CURRENT_SCOPE)
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ else()
+ message(
+ FATAL_ERROR
+ "qt_internal_add_linker_flags expects a scope argument.")
+ endif()
+ endforeach()
+ endforeach()
+endfunction()
+
+# Convenience function to replace a linker flag with another one, for the given configurations
+# and target link types.
+# Essentially a glorified string(REPLACE).
+# Can be used to remove linker flags.
+#
+# match_string - string to match
+# replace_string - replacement string
+# IN_CACHE - replace them globally (aka in the corresponding cache entries)
+# IN_CURRENT_SCOPE - replace them only in the current directory scope (effectively setting them,
+# if they did not exist beforehand)
+# CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
+# TYPES - should be a list of target link types as expected by CMake's
+# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
+# e.g EXE, MODULE, SHARED, STATIC.
+function(qt_internal_replace_linker_flags match_string replace_string)
+ qt_parse_all_arguments(
+ arg
+ "qt_internal_replace_compiler_flags"
+ "IN_CACHE;IN_CURRENT_SCOPE"
+ ""
+ "CONFIGS;TYPES"
+ ${ARGN})
+
+ if(NOT arg_TYPES)
+ message(FATAL_ERROR
+ "You must specify at least one linker target type for which to replace the flags.")
+ endif()
+ if(NOT arg_CONFIGS)
+ message(FATAL_ERROR
+ "You must specify at least one configuration for which to replace the flags.")
+ endif()
+
+ set(configs ${arg_CONFIGS})
+ set(target_link_types ${arg_TYPES})
+
+ foreach(config ${configs})
+ foreach(t ${target_link_types})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
+
+ # Handle an empty input string and an empty match string as a set().
+ if(match_string STREQUAL "" AND "${${flag_var_name}}" STREQUAL "")
+ set(${flag_var_name} "${replace_string}")
+ else()
+ string(REPLACE
+ "${match_string}" "${replace_string}"
+ "${flag_var_name}" "${${flag_var_name}}")
+ endif()
+
+ if(arg_IN_CACHE)
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ elseif(arg_IN_CURRENT_SCOPE)
+ set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
+ else()
+ message(
+ FATAL_ERROR
+ "qt_internal_replace_compiler_flags expects a scope argument.")
+ endif()
+ endforeach()
+ endforeach()
+endfunction()
+
+# This function finds the optimization flags set by the default CMake platform modules or toolchain
+# files and replaces them with flags that Qt qmake builds expect, for all the usual
+# CMAKE_BUILD_TYPE configurations.
+# This normalizes things like using -O2 for both Release and RelWithDebInfo, among other compilation
+# flags. Also some linker flags specific to MSVC.
+# See QTBUG-85992 for details.
+function(qt_internal_set_up_config_optimizations_like_in_qmake)
+ # Allow opt out.
+ if(QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS)
+ return()
+ endif()
+
+ qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
+ qt_internal_get_configs_for_flag_manipulation(configs)
+ qt_internal_get_target_link_types_for_flag_manipulation(target_link_types)
+
+ # You can set QT_DEBUG_OPTIMIZATION_FLAGS to see the before and after results.
+ set(QT_DEBUG_OPTIMIZATION_FLAGS TRUE)
+ if(QT_DEBUG_OPTIMIZATION_FLAGS)
+ message(STATUS "")
+ message(STATUS "DEBUG: Original CMake optimization flags.\n")
+ qt_internal_print_optimization_flags_values_helper("${enabled_languages}" "${configs}"
+ "${target_link_types}")
+ endif()
+
+ # Remove known optimization flags.
+ qt_internal_remove_known_optimization_flags(IN_CACHE CONFIGS ${configs})
# Re-add optimization flags as per qmake mkspecs.
foreach(lang ${enabled_languages})
foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+ set(value_to_append "")
# Release and RelWithDebInfo should get the same base optimization flags.
if(config STREQUAL "RELEASE" AND QT_CFLAGS_OPTIMIZE)
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE}")
elseif(config STREQUAL "RELWITHDEBINFO" AND QT_CFLAGS_OPTIMIZE)
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE}")
# MinSizeRel should get the optimize size flag if available, otherwise the regular
# release flag.
elseif(config STREQUAL "MINSIZEREL")
if(QT_CFLAGS_OPTIMIZE_SIZE)
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE_SIZE}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE_SIZE}")
else()
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE}")
endif()
endif()
# Debug should get the OPTIMIZE_DEBUG flag if the respective feature is ON.
if(config STREQUAL "DEBUG" AND QT_FEATURE_optimize_debug)
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE_DEBUG}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE_DEBUG}")
endif()
set(configs_for_optimize_size RELEASE RELWITHDEBINFO)
if(QT_FEATURE_optimize_size AND config IN_LIST configs_for_optimize_size)
- string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE_SIZE}")
+ set(value_to_append "${QT_CFLAGS_OPTIMIZE_SIZE}")
endif()
# Assign value to the cache entry.
- get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
- set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ if(value_to_append)
+ string(APPEND "${flag_var_name}" " ${value_to_append}")
+ get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
+ set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
+ endif()
+
endforeach()
endforeach()
@@ -379,36 +807,26 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
# Handle MSVC /INCREMENTAL flag which should not be enabled for Release configurations.
# First remove them from all configs, and re-add INCREMENTAL for Debug only.
set(flag_values "/INCREMENTAL:YES" "/INCREMENTAL:NO" "/INCREMENTAL")
- foreach(config ${configs})
- foreach(t ${target_link_types})
- set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
- foreach(flag_value ${flag_values})
- string(REPLACE "${flag_value}" "" "${flag_var_name}" "${${flag_var_name}}")
- string(STRIP "${${flag_var_name}}" "${flag_var_name}")
- endforeach()
- endforeach()
+ foreach(flag_value ${flag_values})
+ qt_internal_replace_linker_flags(
+ "${flag_value}" ""
+ CONFIGS ${configs}
+ TYPES ${target_link_types}
+ IN_CACHE)
endforeach()
- foreach(config ${configs})
- foreach(t ${target_link_types})
- set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
-
- if(config STREQUAL "RELEASE" OR config STREQUAL "RELWITHDEBINFO"
- OR config STREQUAL "MINSIZEREL")
- string(APPEND "${flag_var_name}" " /INCREMENTAL:NO")
- endif()
-
- # Assign value to the cache entry.
- get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
- set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
- endforeach()
- endforeach()
+ set(flag_value "/INCREMENTAL:NO")
+ qt_internal_add_linker_flags(
+ FLAGS "${flag_value}"
+ CONFIGS RELEASE RELWITHDEBINFO MINSIZEREL
+ TYPES ${target_link_types}
+ IN_CACHE)
endif()
if(QT_DEBUG_OPTIMIZATION_FLAGS)
message(STATUS "")
message(STATUS "DEBUG: Modified optimization flags to mirror qmake mkspecs.\n")
- qt_internal_print_optimization_flags_values("${enabled_languages}" "${configs}"
- "${target_link_types}")
+ qt_internal_print_optimization_flags_values_helper("${enabled_languages}" "${configs}"
+ "${target_link_types}")
endif()
endfunction()
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 3ad8f86772..802aa274f5 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -1332,4 +1332,9 @@ if(NOT QT_FEATURE_system_zlib)
NO_CONFIG_HEADER_FILE
)
endif()
+
+qt_internal_print_optimization_flags_values()
+qt_internal_add_optimize_full_flags(IN_CURRENT_SCOPE)
+qt_internal_print_optimization_flags_values()
+
# special case end
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index e4849939fc..661a887dc8 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -1028,3 +1028,8 @@ qt_internal_add_docs(Gui
doc/qtgui.qdocconf
)
+# special case begin
+qt_internal_print_optimization_flags_values()
+qt_internal_add_optimize_full_flags(IN_CURRENT_SCOPE)
+qt_internal_print_optimization_flags_values()
+# special case end
diff --git a/src/winmain/CMakeLists.txt b/src/winmain/CMakeLists.txt
index 1a74a1e3ae..3f3e6f0f1c 100644
--- a/src/winmain/CMakeLists.txt
+++ b/src/winmain/CMakeLists.txt
@@ -16,8 +16,10 @@ qt_internal_add_module(WinMain
if (MSVC)
# Store debug information inside the static lib
- string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
- string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
+ qt_internal_replace_compiler_flags(
+ "/Zi" "/Z7"
+ CONFIGS DEBUG RELWITHDEBINFO
+ IN_CURRENT_SCOPE)
endif()
set_property(TARGET WinMain PROPERTY OUTPUT_NAME qtmain)
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 79da3331a8..89b196e593 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -4,6 +4,16 @@ if(QT_BUILD_STANDALONE_TESTS)
# Add qt_find_package calls for extra dependencies that need to be found when building
# the standalone tests here.
# special case begin
+
+ # Needed for early feature values, despite it being found later on in qt_build_tests().
+ # Needs to be find_package, not qt_find_package, because qt_find_package doesn't handle finding
+ # component for a super-package that has already been found.
+ find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS Core)
+
+ # Modify the optimization flags specifically for qtbase standalone tests. Other projects
+ # are handled by qt_enable_cmake_languages().
+ qt_internal_set_up_config_optimizations_like_in_qmake()
+
qt_find_package(WrapDBus1 PROVIDED_TARGETS dbus-1)
qt_find_package(ICU COMPONENTS i18n uc data PROVIDED_TARGETS ICU::i18n ICU::uc ICU::data)
qt_find_package(WrapOpenSSL PROVIDED_TARGETS WrapOpenSSL::WrapOpenSSL)