summaryrefslogtreecommitdiffstats
path: root/cmake/QtFlagHandlingHelpers.cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2020-08-17 17:32:28 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2020-08-19 18:25:59 +0200
commitcb1600145b7086388c5e5ca0292629ade9d1da58 (patch)
tree4fa289b83616e75b96eba185890bbad173ffd2f3 /cmake/QtFlagHandlingHelpers.cmake
parenta1cc2fbbda4955a496e609fa8edd683e42f2118b (diff)
CMake: Adjust compiler flag optimizations to qmake mkspec ones
There are inconsistencies in the default optimization flags added by CMake across configurations like Release and RelWithDebInfo. In particular Release uses -O3, whereas RelWithDebInfo uses -O2, as well as usage of /INCREMENTAL in release configs with MSVC, etc. To make sure that the Qt 6 binaries built with CMake are consistent across configs, as well as consistent with the flags we used when building Qt 5 with qmake, add a horrible search and replace mechanism to replaces the CMake flags with what our mkspecs indicate to use. Ideally this would be done by providing custom CMake toolchain files for each platform we support, and we might revisit that later if the need really arises. To implement the replacing, we first need the flags that should be added. Port the QMAKE_CFLAGS_OPTIMIZE variables to CMake, which is done in QtCompilerOptimization.cmake. Then a new function called qt_internal_set_up_config_optimizations_like_in_qmake will look for any kind of optimization flags set in the CMAKE_<LANG>_FLAGS_<CONFIG> style variables, remove them, and add the appropriate flags that qmake mkspecs provide. On some platforms (like Windows MSVC) the function also alters the linker CMAKE_${TYPE}_LINKER_FLAGS_<CONFIG> style variables. The mechanism allows opting out of this replacing by setting the QT_USE_DEFAULT_CMAKE_OPTIMIZATION_FLAGS value. It also allows opting into removal of flags for custom configs by providing QT_ADDITIONAL_OPTIMIZATION_FLAG_CONFIGS. It's only removal, because we wouldn't know what kind of config it is, and thus what flags to add. The currently modified configs are: Release, RelWithDebInfo, MinSizeRel, Debug aka the usual default CMake provided ones. The mechanism is only applied to C-like languages. ASM is not handled to be on the safe side due to not knowing what kind of compiler flags the platform assembler might take. It's also important to skip RC on MSVC platforms. Task-number: QTBUG-85992 Change-Id: I3712d5cd5a34fceab54f56a6fa46b4e678952362 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Adam <cristian.adam@qt.io>
Diffstat (limited to 'cmake/QtFlagHandlingHelpers.cmake')
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake160
1 files changed, 160 insertions, 0 deletions
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index ea06a24865..cddaa0da39 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -241,3 +241,163 @@ function(qt_enable_utf8_sources target)
target_compile_options("${target}" INTERFACE "${utf8_flags}")
endif()
endfunction()
+
+function(qt_internal_get_all_possible_optimization_flag_values out_var)
+ set(flag_values "")
+ set(vars QT_CFLAGS_OPTIMIZE QT_CFLAGS_OPTIMIZE_FULL
+ QT_CFLAGS_OPTIMIZE_DEBUG QT_CFLAGS_OPTIMIZE_SIZE)
+ foreach(optimize_var ${vars})
+ set(value "${${optimize_var}}")
+ if(value)
+ list(APPEND flag_values "${value}")
+ endif()
+ endforeach()
+
+ # Additional flag values which might not be used in qmake mkspecs, but might be set by CMake,
+ # aka flags that are recognized by the compile which we might want to remove.
+ if(QT_CFLAGS_OPTIMIZE_VALID_VALUES)
+ list(APPEND flag_values ${QT_CFLAGS_OPTIMIZE_VALID_VALUES})
+ endif()
+
+ set("${out_var}" "${flag_values}" PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_print_optimization_flags_values languages configs target_link_types)
+ foreach(lang ${languages})
+ set(flag_var_name "CMAKE_${lang}_FLAGS")
+ message(STATUS "${flag_var_name}: ${${flag_var_name}}")
+
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+ message(STATUS "${flag_var_name}: ${${flag_var_name}}")
+ endforeach()
+ endforeach()
+
+ foreach(t ${target_link_types})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS")
+ message(STATUS "${flag_var_name}: ${${flag_var_name}}")
+
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
+ message(STATUS "${flag_var_name}: ${${flag_var_name}}")
+ endforeach()
+ 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()
+ endif()
+
+ # 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)
+ get_property(globally_enabled_languages GLOBAL PROPERTY ENABLED_LANGUAGES)
+ set(enabled_languages "")
+ foreach(lang ${languages_to_process})
+ if(lang IN_LIST globally_enabled_languages)
+ list(APPEND enabled_languages "${lang}")
+ endif()
+ endforeach()
+
+ 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})
+ 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}")
+ endif()
+
+ # Remove known optimization flags.
+ qt_internal_get_all_possible_optimization_flag_values(flag_values)
+ 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()
+ endforeach()
+ endforeach()
+
+ # Re-add optimization flags as per qmake mkspecs.
+ foreach(lang ${enabled_languages})
+ foreach(config ${configs})
+ set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
+
+ # 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}")
+ elseif(config STREQUAL "RELWITHDEBINFO" AND QT_CFLAGS_OPTIMIZE)
+ string(APPEND "${flag_var_name}" " ${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}")
+ else()
+ string(APPEND "${flag_var_name}" " ${QT_CFLAGS_OPTIMIZE}")
+ endif()
+ 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()
+
+ if(MSVC)
+ # 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()
+ 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")
+ elseif(config STREQUAL "DEBUG")
+ string(APPEND "${flag_var_name}" " /INCREMENTAL:YES")
+ 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()
+ 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}")
+ endif()
+endfunction()