summaryrefslogtreecommitdiffstats
path: root/cmake/QtFlagHandlingHelpers.cmake
diff options
context:
space:
mode:
Diffstat (limited to 'cmake/QtFlagHandlingHelpers.cmake')
-rw-r--r--cmake/QtFlagHandlingHelpers.cmake215
1 files changed, 170 insertions, 45 deletions
diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake
index d8597326cc..6a62b85c03 100644
--- a/cmake/QtFlagHandlingHelpers.cmake
+++ b/cmake/QtFlagHandlingHelpers.cmake
@@ -1,6 +1,23 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+# Sets '${var}' to a genex that extracts the target's property.
+# Sets 'have_${var}' to a genex that checks that the property has a
+# non-empty value.
+macro(qt_internal_genex_get_property var target property)
+ set(${var} "$<TARGET_PROPERTY:${target},${property}>")
+ set(have_${var} "$<BOOL:${${var}}>")
+endmacro()
+
+# Sets '${var}' to a genex that will join the given property values
+# using '${glue}' and will surround the entire output with '${prefix}'
+# and '${suffix}'.
+macro(qt_internal_genex_get_joined_property var target property prefix suffix glue)
+ qt_internal_genex_get_property("${var}" "${target}" "${property}")
+ set(${var}
+ "$<${have_${var}}:${prefix}$<JOIN:${${var}},${glue}>${suffix}>")
+endmacro()
+
# This function generates LD version script for the target and uses it in the target linker line.
# Function has two modes dependending on the specified arguments.
# Arguments:
@@ -23,7 +40,40 @@ function(qt_internal_add_linker_version_script target)
endif()
if(TEST_ld_version_script)
- set(contents "Qt_${PROJECT_VERSION_MAJOR}_PRIVATE_API {\n qt_private_api_tag*;\n")
+ # Create a list of mangled symbol matches for all "std::" symbols. This
+ # list will catch most symbols, but will miss global-namespace symbols
+ # that only have std parameters.
+ # See https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangle.name for reference
+ set(contents "NonQt {\nlocal:")
+
+ # For types: vtable, VTT, typeinfo, typeinfo name
+ foreach(ptrqualifier "" "P" "PK") # T, T *, const T * (volatile ignored)
+ string(APPEND contents "\n _ZT[VTIS]${ptrqualifier}S*;"
+ "_ZT[VTIS]${ptrqualifier}NS*;")
+ endforeach()
+
+ # For functions and variables
+ foreach(special ""
+ "G[VR]" # guard variables, extended-lifetime references
+ "GTt") # transaction entry points
+ foreach(cvqualifier "" "[VK]" "VK") # plain, const|volatile, const volatile
+ string(APPEND contents "\n ")
+ foreach(refqualifier "" "[RO]") # plain, & or &&
+ # For names in the std:: namespace, compression applies
+ # (https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression)
+ string(APPEND contents
+ " _Z${special}${cvqualifier}${refqualifier}S*;" # plain
+ " _Z${special}N${cvqualifier}${refqualifier}S*;" # nested name
+ )
+ endforeach()
+ endforeach()
+ endforeach()
+
+ string(APPEND contents "\n};\nQt_${PROJECT_VERSION_MAJOR}")
+ if(QT_FEATURE_elf_private_full_version)
+ string(APPEND contents ".${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
+ endif()
+ string(APPEND contents "_PRIVATE_API { qt_private_api_tag*;\n")
if(arg_PRIVATE_HEADERS)
foreach(ph ${arg_PRIVATE_HEADERS})
string(APPEND contents " @FILE:${ph}@\n")
@@ -33,22 +83,27 @@ function(qt_internal_add_linker_version_script target)
endif()
string(APPEND contents "};\n")
set(current "Qt_${PROJECT_VERSION_MAJOR}")
- if (QT_NAMESPACE STREQUAL "")
- set(tag_symbol "qt_version_tag")
- else()
- set(tag_symbol "qt_version_tag_${QT_NAMESPACE}")
+ string(APPEND contents "${current} {\n *;")
+
+ get_target_property(target_type ${target} TYPE)
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set(genex_prefix "\n ")
+ set(genex_glue "$<SEMICOLON>\n ")
+ set(genex_suffix "$<SEMICOLON>")
+ qt_internal_genex_get_joined_property(
+ linker_exports "${target}" _qt_extra_linker_script_exports
+ "${genex_prefix}" "${genex_suffix}" "${genex_glue}"
+ )
+ string(APPEND contents "${linker_exports}")
+ endif()
+ string(APPEND contents "\n};\n")
+
+ if(NOT target_type STREQUAL "INTERFACE_LIBRARY")
+ set(property_genex "$<TARGET_PROPERTY:${target},_qt_extra_linker_script_content>")
+ set(check_genex "$<BOOL:${property_genex}>")
+ string(APPEND contents
+ "$<${check_genex}:${property_genex}>")
endif()
- string(APPEND contents "${current} { *; };\n")
-
- foreach(minor_version RANGE ${PROJECT_VERSION_MINOR})
- set(previous "${current}")
- set(current "Qt_${PROJECT_VERSION_MAJOR}.${minor_version}")
- if (minor_version EQUAL ${PROJECT_VERSION_MINOR})
- string(APPEND contents "${current} { ${tag_symbol}; } ${previous};\n")
- else()
- string(APPEND contents "${current} {} ${previous};\n")
- endif()
- endforeach()
set(infile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version.in")
set(outfile "${CMAKE_CURRENT_BINARY_DIR}/${target}.version")
@@ -87,6 +142,17 @@ function(qt_internal_add_link_flags_no_undefined target)
if (NOT QT_BUILD_SHARED_LIBS OR WASM)
return()
endif()
+ if (VXWORKS)
+ # VxWorks requires thread_local-related symbols to be found at
+ # runtime, resulting in linker error when no-undefined flag is
+ # set and thread_local is used
+ return()
+ endif()
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
+ # ld64 defaults to -undefined,error, and in Xcode 15
+ # passing this option is deprecated, causing a warning.
+ return()
+ endif()
if ((GCC OR CLANG) AND NOT MSVC)
if(CLANG AND QT_FEATURE_sanitizer)
return()
@@ -124,11 +190,20 @@ endfunction()
function(qt_internal_apply_gc_binaries target visibility)
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
- list(FIND possible_visibilities "${visibility}" known_visibility)
- if (known_visibility EQUAL "-1")
+ if(NOT visibility IN_LIST possible_visibilities)
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
endif()
+ string(JOIN "" clang_or_gcc_begin
+ "$<$<OR:"
+ "$<CXX_COMPILER_ID:GNU>,"
+ "$<CXX_COMPILER_ID:Clang>,"
+ "$<CXX_COMPILER_ID:AppleClang>,"
+ "$<CXX_COMPILER_ID:IntelLLVM>"
+ ">:"
+ )
+ set(clang_or_gcc_end ">")
+
if ((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
if(APPLE)
set(gc_sections_flag "-Wl,-dead_strip")
@@ -137,16 +212,26 @@ function(qt_internal_apply_gc_binaries target visibility)
elseif(LINUX OR BSD OR WIN32 OR ANDROID)
set(gc_sections_flag "-Wl,--gc-sections")
endif()
+
+ # Save the flag value with and without genex wrapping, so we can remove the wrapping
+ # when generating .pc pkgconfig files.
+ set_property(GLOBAL PROPERTY _qt_internal_gc_sections_without_genex "${gc_sections_flag}")
+
+ set(gc_sections_flag
+ "${clang_or_gcc_begin}${gc_sections_flag}${clang_or_gcc_end}")
+
+ set_property(GLOBAL PROPERTY _qt_internal_gc_sections_with_genex "${gc_sections_flag}")
endif()
if(gc_sections_flag)
target_link_options("${target}" ${visibility} "${gc_sections_flag}")
endif()
if((GCC OR CLANG) AND NOT WASM AND NOT UIKIT AND NOT MSVC)
- set(split_sections_flags "-ffunction-sections" "-fdata-sections")
+ set(split_sections_flags
+ "${clang_or_gcc_begin}-ffunction-sections;-fdata-sections${clang_or_gcc_end}")
endif()
if(split_sections_flags)
- target_compile_options("${target}" ${visibility} ${split_sections_flags})
+ target_compile_options("${target}" ${visibility} "${split_sections_flags}")
endif()
endfunction()
@@ -156,13 +241,17 @@ function(qt_internal_apply_intel_cet target visibility)
endif()
set(possible_visibilities PRIVATE INTERFACE PUBLIC)
- list(FIND possible_visibilities "${visibility}" known_visibility)
- if (known_visibility EQUAL "-1")
+ if(NOT visibility IN_LIST possible_visibilities)
message(FATAL_ERROR "Visibitily setting must be one of PRIVATE, INTERFACE or PUBLIC.")
endif()
if(GCC)
- set(flags "-mshstk")
+ string(JOIN "" flags
+ "$<$<OR:"
+ "$<CXX_COMPILER_ID:GNU>,"
+ "$<CXX_COMPILER_ID:Clang>,"
+ "$<CXX_COMPILER_ID:AppleClang>"
+ ">:-mshstk>")
endif()
if(flags)
target_compile_options("${target}" ${visibility} "${flags}")
@@ -200,21 +289,21 @@ function(qt_internal_set_exceptions_flags target exceptions_on)
if(MSVC)
set(_flag "/EHsc")
if((MSVC_VERSION GREATER_EQUAL 1929) AND NOT CLANG)
+ # Use the undocumented compiler flag to make our binary smaller on x64.
+ # https://devblogs.microsoft.com/cppblog/making-cpp-exception-handling-smaller-x64/
+ # NOTE: It seems we'll use this new exception handling model unconditionally without
+ # this hack since some unknown MSVC version.
set(_flag ${_flag} "/d2FH4")
endif()
+ else()
+ set(_flag "-fexceptions")
endif()
else()
set(_defs "QT_NO_EXCEPTIONS")
- if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
+ if(MSVC)
set(_flag "/EHs-c-" "/wd4530" "/wd4577")
- elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU|AppleClang|InteLLLVM")
+ else()
set(_flag "-fno-exceptions")
- elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
- if (MSVC)
- set(_flag "/EHs-c-" "/wd4530" "/wd4577")
- else()
- set(_flag "-fno-exceptions")
- endif()
endif()
endif()
@@ -287,14 +376,15 @@ function(qt_set_msvc_cplusplus_options target visibility)
# Check qt_config_compile_test for more info.
if(MSVC AND MSVC_VERSION GREATER_EQUAL 1913)
set(flags "-Zc:__cplusplus" "-permissive-")
- target_compile_options("${target}" ${visibility} "$<$<COMPILE_LANGUAGE:CXX>:${flags}>")
+ target_compile_options("${target}" ${visibility}
+ "$<$<AND:$<CXX_COMPILER_ID:MSVC>,$<COMPILE_LANGUAGE:CXX>>:${flags}>")
endif()
endfunction()
function(qt_enable_utf8_sources target)
set(utf8_flags "")
if(MSVC)
- list(APPEND utf8_flags "-utf-8")
+ list(APPEND utf8_flags "$<$<CXX_COMPILER_ID:MSVC>:-utf-8>")
endif()
if(utf8_flags)
@@ -314,7 +404,7 @@ function(qt_internal_enable_unicode_defines)
set(no_unicode_condition
"$<NOT:$<BOOL:$<TARGET_PROPERTY:QT_NO_UNICODE_DEFINES>>>")
target_compile_definitions(Platform
- INTERFACE "$<${no_unicode_condition}:UNICODE;_UNICODE>")
+ INTERFACE "$<${no_unicode_condition}:UNICODE$<SEMICOLON>_UNICODE>")
endif()
endfunction()
@@ -557,12 +647,20 @@ endfunction()
# Removes specified flags from CMAKE_<LANGUAGES>_FLAGS[_CONFIGS] variables
#
-# IN_CACHE enables flags removal from CACHE
-# CONFIGS list of configurations that need to clear flags. Clears all configs by default if not
-# specified.
-# LANGUAGES list of LANGUAGES that need clear flags. Clears all languages by default if not
-# specified.
-# REGEX enables the flag processing as a regular expression.
+# Option Arguments:
+# IN_CACHE
+# Enables flags removal from CACHE
+# REGEX
+# Enables the flag processing as a regular expression.
+#
+# Multi-value Arguments:
+# CONFIGS
+# List of configurations that need to clear flags. Clears all configs by default if not
+# specified.
+#
+# LANGUAGES
+# List of LANGUAGES that need clear flags. Clears all languages by default if not
+# specified.
function(qt_internal_remove_compiler_flags flags)
cmake_parse_arguments(PARSE_ARGV 1 arg
"IN_CACHE;REGEX"
@@ -585,8 +683,7 @@ function(qt_internal_remove_compiler_flags flags)
if(arg_CONFIGS)
set(configs "${arg_CONFIGS}")
else()
- message(FATAL_ERROR
- "You must specify at least one configuration for which to remove the flags.")
+ qt_internal_get_configs_for_flag_manipulation(configs)
endif()
if(arg_REGEX)
@@ -992,14 +1089,42 @@ function(qt_internal_set_up_config_optimizations_like_in_qmake)
IN_CACHE)
endif()
+ # Legacy Android toolchain file adds the `-g` flag to CMAKE_<LANG>_FLAGS, as a
+ # result, our release build ends up containing debug symbols. To avoid that, we
+ # remove the flag from CMAKE_<LANGL>_FLAGS and add
+ # it to CMAKE_<LANG>_FLAGS_DEBUG.
+ #
+ # Note:
+ # The new `android.toolchain.cmake` file does not have this problem, but
+ # it has other issues, eg., https://github.com/android/ndk/issues/1693, so we
+ # cannot force it. While we do load the new toolchain, it automatically falls
+ # back to the legacy toolchain, ie., `android-legacy.toolchain.cmake` which
+ # has the problem described above.
+ #
+ # Todo:
+ # When the new toolchain is fixed, and it doesn't fall back to the legacy
+ # anymore by default, then we should be able to remove this workaround.
+ if(ANDROID AND ANDROID_COMPILER_FLAGS MATCHES "(^| )-g")
+ qt_internal_remove_compiler_flags("-g")
+ qt_internal_add_compiler_flags(FLAGS "-g" CONFIGS DEBUG RELWITHDEBINFO)
+ endif()
+
# Update all relevant flags in the calling scope
- foreach(config ${configs})
- foreach(lang ${enabled_languages})
+ foreach(lang ${enabled_languages})
+ set(flag_var_name "CMAKE_${lang}_FLAGS")
+ set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
+
+ foreach(config ${configs})
set(flag_var_name "CMAKE_${lang}_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()
+ endforeach()
- foreach(t ${target_link_types})
+ foreach(t ${target_link_types})
+ set(flag_var_name "CMAKE_${t}_LINKER_FLAGS")
+ set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
+
+ foreach(config ${configs})
set(flag_var_name "CMAKE_${t}_LINKER_FLAGS_${config}")
set(${flag_var_name} "${${flag_var_name}}" PARENT_SCOPE)
endforeach()