Prevent compiler and linker flags from growing every cmake run

Functions in QtFlagHandlingHelpers.cmake try to update the CMake cache
variables for compiler and linker flags. These were using the current
value of those variables and writing the modified ones back to the
cache every time CMake ran. If a toolchain file sets or modifies any of
these variables, that updated value is used and written back into the
cache instead of the original cache variable's value. The next time
CMake executes, the toolchain file re-applies the same change and the
variable grows longer each time with flags repeated. With Ninja, this
causes a complete rebuild every time CMake is re-run. The Android NDK
toolchain file is one example where this behavior is triggered (the
fault is shared, one could argue that the NDK should only be setting
..._INIT variables, but that's out of our control).

Another related bug in the previous implementation was that the flags
used to build after the first CMake execution could be different to
those used for all builds after the second and later CMake runs. This
is because the CMake cache was being updated, but not always the
calling scope of the functions that modified them. If a toolchain file
set any of the compiler or linker flag variables as non-cache
variables, then updating the cache variable would have no effect on
the calling scope. The non-cache variable would continue to take
precedence for that scope for that run. The next time CMake executes
though, the updated cache variable would now have been used by the
toolchain file and the change *will* be part of the non-cache
variable's value.

The above are examples of why you should try to avoid updating these
cache variables from project code. We could leave the cache alone and
always update only non-cache variables, but then a developer looking
at the cache may wonder why the values they see there don't match the
values being used in builds. Or worse, they think the cache values
are being used and don't realize the builds are using something
different. Ultimately, we have to choose which downside we are happy
to live with. The changes here preserve the previous intent of
updating the cache, but it's still a bit fragile.

Fixes: QTBUG-89821
Task-number: QTBUG-85992
Task-number: QTBUG-86866
Change-Id: I8a16753e159bde338e6d2e5dd2ce91fc8ac5c39d
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
This commit is contained in:
Craig Scott 2021-01-07 16:53:43 +11:00
parent 77350b7a71
commit 257edbfa53
4 changed files with 185 additions and 161 deletions

View File

@ -358,27 +358,113 @@ function(qt_internal_get_enabled_languages_for_flag_manipulation out_var)
set(${out_var} "${enabled_languages}" PARENT_SCOPE) set(${out_var} "${enabled_languages}" PARENT_SCOPE)
endfunction() endfunction()
# Helper function used to update compiler and linker flags further below
function(qt_internal_replace_flags_impl flag_var_name match_string replace_string IN_CACHE)
# This must come before cache variable modification because setting the
# cache variable with FORCE will overwrite the non-cache variable, but
# we need to use the original value on entry to this function.
# 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}" PARENT_SCOPE)
else()
string(REPLACE
"${match_string}" "${replace_string}"
${flag_var_name} "${${flag_var_name}}")
string(STRIP "${${flag_var_name}}" ${flag_var_name})
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endif()
if(IN_CACHE)
# We must not use the non-cache variable's value because toolchain files
# might be appending things to the cache variable's value and storing it
# in a non-cache variable (e.g. Android NDK toolchain file does this).
# Work exclusively on cache variable value only.
get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING)
# Handle an empty input string and an empty match string as a set().
if(match_string STREQUAL "" AND "$CACHE{${flag_var_name}}" STREQUAL "")
set(${flag_var_name} "${replace_string}" CACHE STRING "${help_text}" FORCE)
else()
set(mod_flags "$CACHE{${flag_var_name}}")
string(REPLACE
"${match_string}" "${replace_string}"
mod_flags "${mod_flags}")
string(STRIP "${mod_flags}" mod_flags)
set(${flag_var_name} "${mod_flags}" CACHE STRING "${help_text}" FORCE)
endif()
endif()
endfunction()
# Helper function used to update compiler and linker flags further below
function(qt_internal_remove_flags_impl flag_var_name flag_values IN_CACHE)
# This must come before cache variable modification because setting the
# cache variable with FORCE will overwrite the non-cache variable in this
# function scope, but we need to use the original value before that change.
foreach(flag_value IN LISTS flag_values)
string(REPLACE "${flag_value}" "" ${flag_var_name} "${${flag_var_name}}")
endforeach()
string(STRIP "${${flag_var_name}}" ${flag_var_name})
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
if(IN_CACHE)
# We must not use the non-cache variable's value because toolchain files
# might be appending things to the cache variable's value and storing it
# in a non-cache variable (e.g. Android NDK toolchain file does this).
# Work exclusively on cache variable value only.
set(mod_flags $CACHE{${flag_var_name}})
foreach(flag_value IN LISTS flag_values)
string(REPLACE "${flag_value}" "" mod_flags "${mod_flags}")
endforeach()
string(STRIP "${mod_flags}" mod_flags)
get_property(help_text CACHE ${flag_var_name} PROPERTY HELPSTRING)
set(${flag_var_name} "${mod_flags}" CACHE STRING "${help_text}" FORCE)
endif()
endfunction()
# Helper function used to update compiler and linker flags further below
function(qt_internal_add_flags_impl flag_var_name flags IN_CACHE)
# This must come before cache variable modification because setting the
# cache variable with FORCE will overwrite the non-cache variable, but
# we need to use the original value on entry to this function.
set(${flag_var_name} "${${flag_var_name}} ${flags}")
string(STRIP "${${flag_var_name}}" ${flag_var_name})
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
if(IN_CACHE)
# We must not use the non-cache variable's value because toolchain files
# might be appending things to the cache variable's value and storing it
# in a non-cache variable (e.g. Android NDK toolchain file does this).
# Work exclusively on cache variable value only.
set(mod_flags "$CACHE{${flag_var_name}} ${flags}")
string(STRIP "${mod_flags}" mod_flags)
get_property(help_text CACHE ${flag_var_name} PROPERTY HELPSTRING)
set(${flag_var_name} "${mod_flags}" CACHE STRING "${help_text}" FORCE)
endif()
endfunction()
# Removes all known compiler optimization flags for the given CONFIGS, for all enabled 'safe' # Removes all known compiler optimization flags for the given CONFIGS, for all enabled 'safe'
# languages. # languages. The flag variables are always updated in the calling scope, even if they did not
# exist beforehand.
# #
# IN_CACHE - remove them globally (aka in the corresponding cache entries) # IN_CACHE - remove them from the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - remove them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
# 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
# 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
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_remove_known_optimization_flags) function(qt_internal_remove_known_optimization_flags)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_remove_known_optimization_flags" "qt_internal_remove_known_optimization_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"" ""
"CONFIGS;LANGUAGES" "CONFIGS;LANGUAGES"
${ARGN}) ${ARGN})
if(NOT arg_CONFIGS) if(NOT arg_CONFIGS)
message(FATAL_ERROR message(FATAL_ERROR
"You must specify at least one configuration for which to add the flags.") "You must specify at least one configuration for which to remove the flags.")
endif() endif()
if(arg_LANGUAGES) if(arg_LANGUAGES)
@ -393,40 +479,27 @@ function(qt_internal_remove_known_optimization_flags)
foreach(lang ${enabled_languages}) foreach(lang ${enabled_languages})
foreach(config ${configs}) foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
foreach(flag_value ${flag_values}) qt_internal_remove_flags_impl(${flag_var_name} "${flag_values}" "${arg_IN_CACHE}")
string(REPLACE "${flag_value}" "" "${flag_var_name}" "${${flag_var_name}}") set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
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()
endforeach() endforeach()
endfunction() endfunction()
# Adds compiler flags for the given CONFIGS either in the current scope or globally in the # Adds compiler flags for the given CONFIGS in the calling scope. Can also update the cache
# cache. # if asked to do so. The flag variables are always updated in the calling scope, even if they
# did not exist beforehand.
# #
# FLAGS - should be a single string of flags separated by spaces. # FLAGS - should be a single string of flags separated by spaces.
# IN_CACHE - add them globally (aka in the corresponding cache entries) # IN_CACHE - add them to the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
# 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
# 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
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_add_compiler_flags) function(qt_internal_add_compiler_flags)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_add_compiler_flags" "qt_internal_add_compiler_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"FLAGS" "FLAGS"
"CONFIGS;LANGUAGES" "CONFIGS;LANGUAGES"
${ARGN}) ${ARGN})
@ -450,35 +523,26 @@ function(qt_internal_add_compiler_flags)
foreach(lang ${enabled_languages}) foreach(lang ${enabled_languages})
foreach(config ${configs}) foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
string(APPEND "${flag_var_name}" " ${arg_FLAGS}") qt_internal_add_flags_impl(${flag_var_name} "${arg_FLAGS}" "${arg_IN_CACHE}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
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()
endforeach() endforeach()
endfunction() endfunction()
# Convenience function that adds compiler flags for all release configurations. # Convenience function that adds compiler flags for all release configurations.
# The flag variables are always updated in the calling scope, even if they did not
# exist beforehand.
# #
# FLAGS - should be a single string of flags separated by spaces. # FLAGS - should be a single string of flags separated by spaces.
# IN_CACHE - add them globally (aka in the corresponding cache entries) # IN_CACHE - add them to the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # LANGUAGES - optional list of languages like 'C', 'CXX', for which to add the flags
# 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
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_add_compiler_flags_for_release_configs) function(qt_internal_add_compiler_flags_for_release_configs)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_add_compiler_flags_for_release_configs" "qt_internal_add_compiler_flags_for_release_configs"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"FLAGS" "FLAGS"
"LANGUAGES" "LANGUAGES"
${ARGN}) ${ARGN})
@ -502,21 +566,16 @@ function(qt_internal_add_compiler_flags_for_release_configs)
if(arg_IN_CACHE) if(arg_IN_CACHE)
list(APPEND args IN_CACHE) list(APPEND args IN_CACHE)
endif() endif()
if(arg_IN_CURRENT_SCOPE)
list(APPEND args IN_CURRENT_SCOPE)
endif()
list(APPEND args LANGUAGES ${enabled_languages}) list(APPEND args LANGUAGES ${enabled_languages})
qt_internal_add_compiler_flags(${args}) qt_internal_add_compiler_flags(${args})
if(arg_IN_CURRENT_SCOPE) foreach(lang ${enabled_languages})
foreach(lang ${enabled_languages}) foreach(config ${configs})
foreach(config ${configs}) set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
endforeach() endforeach()
endif() endforeach()
endfunction() endfunction()
# Convenience function that replaces all optimization flags with the equivalent of '-O3' # Convenience function that replaces all optimization flags with the equivalent of '-O3'
@ -529,7 +588,7 @@ function(qt_internal_add_optimize_full_flags)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_add_optimize_full_flags" "qt_internal_add_optimize_full_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"" ""
"" ""
${ARGN}) ${ARGN})
@ -538,9 +597,6 @@ function(qt_internal_add_optimize_full_flags)
if(arg_IN_CACHE) if(arg_IN_CACHE)
list(APPEND args IN_CACHE) list(APPEND args IN_CACHE)
endif() endif()
if(arg_IN_CURRENT_SCOPE)
list(APPEND args IN_CURRENT_SCOPE)
endif()
qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages) qt_internal_get_enabled_languages_for_flag_manipulation(enabled_languages)
set(configs RELEASE RELWITHDEBINFO MINSIZEREL) set(configs RELEASE RELWITHDEBINFO MINSIZEREL)
@ -554,34 +610,33 @@ function(qt_internal_add_optimize_full_flags)
qt_internal_add_compiler_flags_for_release_configs(${args}) qt_internal_add_compiler_flags_for_release_configs(${args})
if(arg_IN_CURRENT_SCOPE) foreach(lang ${enabled_languages})
foreach(lang ${enabled_languages}) foreach(config ${configs})
foreach(config ${configs}) set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
set("${flag_var_name}" "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
endforeach() endforeach()
endif() endforeach()
endfunction() endfunction()
# Convenience function to replace a compiler flag with another one, for the given configurations # Convenience function to replace a compiler flag with another one, for the given configurations
# for all enabled 'safe' languages. # for all enabled 'safe' languages.
# Essentially a glorified string(REPLACE). # Essentially a glorified string(REPLACE).
# Can be used to remove compiler flags. # Can be used to remove compiler flags.
# The flag variables are always updated in the calling scope, even if they did not
# exist beforehand.
# #
# match_string - string to match # match_string - string to match
# replace_string - replacement string # replace_string - replacement string
# IN_CACHE - replace them globally (aka in the corresponding cache entries) # IN_CACHE - replace them in the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - replace them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
# 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
# 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
# if not provided, defaults to the list of enabled C-like languages
function(qt_internal_replace_compiler_flags match_string replace_string) function(qt_internal_replace_compiler_flags match_string replace_string)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_replace_compiler_flags" "qt_internal_replace_compiler_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"" ""
"CONFIGS;LANGUAGES" "CONFIGS;LANGUAGES"
${ARGN}) ${ARGN})
@ -601,45 +656,28 @@ function(qt_internal_replace_compiler_flags match_string replace_string)
foreach(lang ${enabled_languages}) foreach(lang ${enabled_languages})
foreach(config ${configs}) foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}") set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
qt_internal_replace_flags_impl(${flag_var_name}
# Handle an empty input string and an empty match string as a set(). "${match_string}" "${replace_string}" "${arg_IN_CACHE}")
if(match_string STREQUAL "" AND "${${flag_var_name}}" STREQUAL "") set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
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()
endforeach() endforeach()
endfunction() endfunction()
# Convenience function to add linker flags, for the given configurations and target link types. # Convenience function to add linker flags, for the given configurations and target link types.
# The flag variables are always updated in the calling scope, even if they did not exist beforehand.
# #
# FLAGS - should be a single string of flags separated by spaces. # FLAGS - should be a single string of flags separated by spaces.
# IN_CACHE - add them globally (aka in the corresponding cache entries) # IN_CACHE - add them to the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - add them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
# 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
# TYPES - should be a list of target link types as expected by CMake's # CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable. # e.g EXE, MODULE, SHARED, STATIC.
# e.g EXE, MODULE, SHARED, STATIC.
function(qt_internal_add_linker_flags) function(qt_internal_add_linker_flags)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_add_linker_flags" "qt_internal_add_linker_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"FLAGS" "FLAGS"
"CONFIGS;TYPES" "CONFIGS;TYPES"
${ARGN}) ${ARGN})
@ -662,18 +700,8 @@ function(qt_internal_add_linker_flags)
foreach(config ${configs}) foreach(config ${configs})
foreach(t ${target_link_types}) foreach(t ${target_link_types})
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}") set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
string(APPEND "${flag_var_name}" " ${arg_FLAGS}") qt_internal_add_flags_impl(${flag_var_name} "${arg_FLAGS}" "${arg_IN_CACHE}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
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()
endforeach() endforeach()
endfunction() endfunction()
@ -682,21 +710,21 @@ endfunction()
# and target link types. # and target link types.
# Essentially a glorified string(REPLACE). # Essentially a glorified string(REPLACE).
# Can be used to remove linker flags. # Can be used to remove linker flags.
# The flag variables are always updated in the calling scope, even if they did not exist beforehand.
# #
# match_string - string to match # match_string - string to match
# replace_string - replacement string # replace_string - replacement string
# IN_CACHE - replace them globally (aka in the corresponding cache entries) # IN_CACHE - replace them in the corresponding cache variable too. Note that the cache
# IN_CURRENT_SCOPE - replace them only in the current directory scope (effectively setting them, # variable may have a different value to the non-cache variable.
# if they did not exist beforehand) # CONFIGS - should be a list of upper case configs like DEBUG, RELEASE, RELWITHDEBINFO.
# 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
# TYPES - should be a list of target link types as expected by CMake's # CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable.
# CMAKE_<LINKER_TYPE>_LINKER_FLAGS_<CONFIG> cache variable. # e.g EXE, MODULE, SHARED, STATIC.
# e.g EXE, MODULE, SHARED, STATIC.
function(qt_internal_replace_linker_flags match_string replace_string) function(qt_internal_replace_linker_flags match_string replace_string)
qt_parse_all_arguments( qt_parse_all_arguments(
arg arg
"qt_internal_replace_compiler_flags" "qt_internal_replace_compiler_flags"
"IN_CACHE;IN_CURRENT_SCOPE" "IN_CACHE"
"" ""
"CONFIGS;TYPES" "CONFIGS;TYPES"
${ARGN}) ${ARGN})
@ -716,26 +744,9 @@ function(qt_internal_replace_linker_flags match_string replace_string)
foreach(config ${configs}) foreach(config ${configs})
foreach(t ${target_link_types}) foreach(t ${target_link_types})
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}") set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
qt_internal_replace_flags_impl(${flag_var_name}
# Handle an empty input string and an empty match string as a set(). "${match_string}" "${replace_string}" "${arg_IN_CACHE}")
if(match_string STREQUAL "" AND "${${flag_var_name}}" STREQUAL "") set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
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()
endforeach() endforeach()
endfunction() endfunction()
@ -746,6 +757,8 @@ endfunction()
# This normalizes things like using -O2 for both Release and RelWithDebInfo, among other compilation # This normalizes things like using -O2 for both Release and RelWithDebInfo, among other compilation
# flags. Also some linker flags specific to MSVC. # flags. Also some linker flags specific to MSVC.
# See QTBUG-85992 for details. # See QTBUG-85992 for details.
#
# Note that both the calling scope and the CMake cache are updated.
function(qt_internal_set_up_config_optimizations_like_in_qmake) function(qt_internal_set_up_config_optimizations_like_in_qmake)
# Allow opt out. # Allow opt out.
if(QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS) if(QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS)
@ -810,9 +823,8 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
# Assign value to the cache entry. # Assign value to the cache entry.
if(value_to_append) if(value_to_append)
string(APPEND "${flag_var_name}" " ${value_to_append}") qt_internal_add_flags_impl(${flag_var_name} "${value_to_append}" TRUE)
get_property(help_text CACHE "${flag_var_name}" PROPERTY HELPSTRING) # Delay updating the calling scope's variables to the end of this function
set("${flag_var_name}" "${${flag_var_name}}" CACHE STRING "${help_text}" FORCE)
endif() endif()
endforeach() endforeach()
@ -849,6 +861,19 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
IN_CACHE) IN_CACHE)
endif() endif()
# Update all relevant flags in the calling scope
foreach(config ${configs})
foreach(lang ${enabled_languages})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
foreach(t ${target_link_types})
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
endforeach()
if(QT_DEBUG_OPTIMIZATION_FLAGS) if(QT_DEBUG_OPTIMIZATION_FLAGS)
message(STATUS "") message(STATUS "")
message(STATUS "DEBUG: Modified optimization flags to mirror qmake mkspecs.\n") message(STATUS "DEBUG: Modified optimization flags to mirror qmake mkspecs.\n")

View File

@ -1348,6 +1348,6 @@ if(NOT QT_FEATURE_system_zlib)
) )
endif() endif()
qt_internal_add_optimize_full_flags(IN_CURRENT_SCOPE) qt_internal_add_optimize_full_flags()
# special case end # special case end

View File

@ -59,8 +59,7 @@ if(WIN32)
# Store debug information inside the static lib # Store debug information inside the static lib
qt_internal_replace_compiler_flags( qt_internal_replace_compiler_flags(
"/Zi" "/Z7" "/Zi" "/Z7"
CONFIGS DEBUG RELWITHDEBINFO CONFIGS DEBUG RELWITHDEBINFO)
IN_CURRENT_SCOPE)
endif() endif()
if(MINGW) if(MINGW)

View File

@ -1030,5 +1030,5 @@ qt_internal_add_docs(Gui
) )
# special case begin # special case begin
qt_internal_add_optimize_full_flags(IN_CURRENT_SCOPE) qt_internal_add_optimize_full_flags()
# special case end # special case end