summaryrefslogtreecommitdiffstats
path: root/cmake/QtTargetHelpers.cmake
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2020-08-13 17:37:47 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2020-08-14 13:17:11 +0200
commit44cce1a2ea9dadd8b2de93f40de34269dda703c0 (patch)
treeeca02c6e828da9e84c4c2de6ff643cafad794024 /cmake/QtTargetHelpers.cmake
parent9d3a908e9ed154294ed4c58429d22a9ff8541ba4 (diff)
CMake: Split QtBuild.cmake into smaller files
QtBuild.cmake is huge. Split it. Move module, plugin, tools, executables and test related functions out of QtBuild.cmake into separate files. Do the same for many other things too. An additional requirement is that all the new Helpers files only define functions and macros. No global variable definitions are allowed, nor execution of commands with side effects. Some notes: qt_install_qml_files is removed because it's dead code. Some functions still need to be figured out, because they are interspersed and depend on various global state assignments. Task-number: QTBUG-86035 Change-Id: I21d79ff02eef923c202eb1000422888727cb0e2c Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
Diffstat (limited to 'cmake/QtTargetHelpers.cmake')
-rw-r--r--cmake/QtTargetHelpers.cmake335
1 files changed, 335 insertions, 0 deletions
diff --git a/cmake/QtTargetHelpers.cmake b/cmake/QtTargetHelpers.cmake
new file mode 100644
index 0000000000..c79ce47363
--- /dev/null
+++ b/cmake/QtTargetHelpers.cmake
@@ -0,0 +1,335 @@
+# This function can be used to add sources/libraries/etc. to the specified CMake target
+# if the provided CONDITION evaluates to true.
+function(qt_extend_target target)
+ # Don't try to extend_target when cross compiling an imported host target (like a tool).
+ qt_is_imported_target("${target}" is_imported)
+ if(is_imported)
+ return()
+ endif()
+
+ if (NOT TARGET "${target}")
+ message(FATAL_ERROR "Trying to extend non-existing target \"${target}\".")
+ endif()
+ qt_parse_all_arguments(arg "qt_extend_target" "HEADER_MODULE" "PRECOMPILED_HEADER"
+ "CONDITION;${__default_public_args};${__default_private_args};${__default_private_module_args};COMPILE_FLAGS;NO_PCH_SOURCES" ${ARGN})
+ if ("x${arg_CONDITION}" STREQUAL x)
+ set(arg_CONDITION ON)
+ endif()
+
+ qt_evaluate_config_expression(result ${arg_CONDITION})
+ if (${result})
+ if(QT_CMAKE_DEBUG_EXTEND_TARGET)
+ message("qt_extend_target(${target} CONDITION ${arg_CONDITION} ...): Evaluated")
+ endif()
+ set(dbus_sources "")
+ foreach(adaptor ${arg_DBUS_ADAPTOR_SOURCES})
+ qt_create_qdbusxml2cpp_command("${target}" "${adaptor}" ADAPTOR BASENAME "${arg_DBUS_ADAPTOR_BASENAME}" FLAGS "${arg_DBUS_ADAPTOR_FLAGS}")
+ list(APPEND dbus_sources "${sources}")
+ endforeach()
+
+ foreach(interface ${arg_DBUS_INTERFACE_SOURCES})
+ qt_create_qdbusxml2cpp_command("${target}" "${interface}" INTERFACE BASENAME "${arg_DBUS_INTERFACE_BASENAME}" FLAGS "${arg_DBUS_INTERFACE_FLAGS}")
+ list(APPEND dbus_sources "${sources}")
+ endforeach()
+
+ get_target_property(target_type ${target} TYPE)
+ set(is_library FALSE)
+ if (${target_type} STREQUAL "STATIC_LIBRARY" OR ${target_type} STREQUAL "SHARED_LIBRARY")
+ set(is_library TRUE)
+ endif()
+ foreach(lib ${arg_PUBLIC_LIBRARIES} ${arg_LIBRARIES})
+ # Automatically generate PCH for 'target' using dependencies
+ # if 'target' is a library/module!
+ if (${is_library})
+ qt_update_precompiled_header_with_library("${target}" "${lib}")
+ endif()
+
+ string(REGEX REPLACE "_nolink$" "" base_lib "${lib}")
+ if(NOT base_lib STREQUAL lib)
+ qt_create_nolink_target("${base_lib}" ${target})
+ endif()
+ endforeach()
+
+ # Set-up the target
+ target_sources("${target}" PRIVATE ${arg_SOURCES} ${dbus_sources})
+ if (arg_COMPILE_FLAGS)
+ set_source_files_properties(${arg_SOURCES} PROPERTIES COMPILE_FLAGS "${arg_COMPILE_FLAGS}")
+ endif()
+
+ set(public_visibility_option "PUBLIC")
+ set(private_visibility_option "PRIVATE")
+ if(arg_HEADER_MODULE)
+ set(public_visibility_option "INTERFACE")
+ set(private_visibility_option "INTERFACE")
+ endif()
+ target_include_directories("${target}"
+ ${public_visibility_option} ${arg_PUBLIC_INCLUDE_DIRECTORIES}
+ ${private_visibility_option} ${arg_INCLUDE_DIRECTORIES})
+ target_compile_definitions("${target}"
+ ${public_visibility_option} ${arg_PUBLIC_DEFINES}
+ ${private_visibility_option} ${arg_DEFINES})
+ target_link_libraries("${target}"
+ ${public_visibility_option} ${arg_PUBLIC_LIBRARIES}
+ ${private_visibility_option} ${arg_LIBRARIES})
+ target_compile_options("${target}"
+ ${public_visibility_option} ${arg_PUBLIC_COMPILE_OPTIONS}
+ ${private_visibility_option} ${arg_COMPILE_OPTIONS})
+ target_link_options("${target}"
+ ${public_visibility_option} ${arg_PUBLIC_LINK_OPTIONS}
+ ${private_visibility_option} ${arg_LINK_OPTIONS})
+
+ if(NOT arg_HEADER_MODULE)
+ set_property (TARGET "${target}" APPEND PROPERTY
+ AUTOMOC_MOC_OPTIONS "${arg_MOC_OPTIONS}"
+ )
+ endif()
+
+ # When computing the private library dependencies, we need to check not only the known
+ # modules added by this repo's qt_build_repo(), but also all module dependencies that
+ # were found via find_package().
+ qt_internal_get_qt_all_known_modules(known_modules)
+
+ # When a public module depends on a private module (Gui on CorePrivate)
+ # make its private module depend on the other private module (GuiPrivate will depend on
+ # CorePrivate).
+ set(qt_libs_private "")
+ foreach(it ${known_modules})
+ list(FIND arg_LIBRARIES "Qt::${it}Private" pos)
+ if(pos GREATER -1)
+ list(APPEND qt_libs_private "Qt::${it}Private")
+ endif()
+ endforeach()
+
+ set(target_private "${target}Private")
+ if(TARGET "${target_private}")
+ target_link_libraries("${target_private}"
+ INTERFACE ${arg_PRIVATE_MODULE_INTERFACE})
+ endif()
+ qt_register_target_dependencies("${target}"
+ "${arg_PUBLIC_LIBRARIES}"
+ "${qt_libs_private};${arg_LIBRARIES}")
+
+
+ qt_autogen_tools(${target}
+ ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
+ DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS})
+
+ qt_update_precompiled_header("${target}" "${arg_PRECOMPILED_HEADER}")
+ qt_update_ignore_pch_source("${target}" "${arg_NO_PCH_SOURCES}")
+ ## Ignore objective-c files for PCH (not supported atm)
+ qt_ignore_pch_obj_c_sources("${target}" "${arg_SOURCES}")
+
+ else()
+ if(QT_CMAKE_DEBUG_EXTEND_TARGET)
+ message("qt_extend_target(${target} CONDITION ${arg_CONDITION} ...): Skipped")
+ endif()
+ endif()
+endfunction()
+
+function(qt_is_imported_target target out_var)
+ if(NOT TARGET "${target}")
+ set(target "${QT_CMAKE_EXPORT_NAMESPACE}::${target}")
+ endif()
+ if(NOT TARGET "${target}")
+ message(FATAL_ERROR "Invalid target given to qt_is_imported_target: ${target}")
+ endif()
+ get_target_property(is_imported "${target}" IMPORTED)
+ set(${out_var} "${is_imported}" PARENT_SCOPE)
+endfunction()
+
+# Add Qt::target and Qt6::target as aliases for the target
+function(qt_internal_add_target_aliases target)
+ get_target_property(type "${target}" TYPE)
+ if (type STREQUAL EXECUTABLE)
+ add_executable("Qt::${target}" ALIAS "${target}")
+ add_executable("Qt${PROJECT_VERSION_MAJOR}::${target}" ALIAS "${target}")
+ else()
+ add_library("Qt::${target}" ALIAS "${target}")
+ add_library("Qt${PROJECT_VERSION_MAJOR}::${target}" ALIAS "${target}")
+ endif()
+endfunction()
+
+function(qt_get_cmake_configurations out_var)
+ set(possible_configs "${CMAKE_BUILD_TYPE}")
+ if(CMAKE_CONFIGURATION_TYPES)
+ set(possible_configs "${CMAKE_CONFIGURATION_TYPES}")
+ endif()
+ set(${out_var} "${possible_configs}" PARENT_SCOPE)
+endfunction()
+
+function(qt_clone_property_for_configs target property configs)
+ get_target_property(value "${target}" "${property}")
+ foreach(config ${configs})
+ string(TOUPPER "${config}" upper_config)
+ set_property(TARGET "${target}" PROPERTY "${property}_${upper_config}" "${value}")
+ endforeach()
+endfunction()
+
+function(qt_handle_multi_config_output_dirs target)
+ qt_get_cmake_configurations(possible_configs)
+ qt_clone_property_for_configs(${target} LIBRARY_OUTPUT_DIRECTORY "${possible_configs}")
+ qt_clone_property_for_configs(${target} RUNTIME_OUTPUT_DIRECTORY "${possible_configs}")
+ qt_clone_property_for_configs(${target} ARCHIVE_OUTPUT_DIRECTORY "${possible_configs}")
+endfunction()
+
+# Set target properties that are the same for all modules, plugins, executables
+# and 3rdparty libraries.
+function(qt_set_common_target_properties target)
+ if(FEATURE_static_runtime)
+ if(MSVC)
+ set_property(TARGET ${target} PROPERTY
+ MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
+ elseif(MINGW)
+ target_link_options(${target} INTERFACE "LINKER:-static")
+ endif()
+ endif()
+endfunction()
+
+# Set common, informational target properties.
+#
+# On Windows, these properties are used to generate the version information resource.
+function(qt_set_target_info_properties target)
+ cmake_parse_arguments(arg "" "${__default_target_info_args}" "" ${ARGN})
+ if("${arg_TARGET_VERSION}" STREQUAL "")
+ set(arg_TARGET_VERSION "${PROJECT_VERSION}.0")
+ endif()
+ if("${arg_TARGET_PRODUCT}" STREQUAL "")
+ set(arg_TARGET_PRODUCT "Qt6")
+ endif()
+ if("${arg_TARGET_DESCRIPTION}" STREQUAL "")
+ set(arg_TARGET_DESCRIPTION "C++ Application Development Framework")
+ endif()
+ if("${arg_TARGET_COMPANY}" STREQUAL "")
+ set(arg_TARGET_COMPANY "The Qt Company Ltd.")
+ endif()
+ if("${arg_TARGET_COPYRIGHT}" STREQUAL "")
+ set(arg_TARGET_COPYRIGHT "Copyright (C) 2020 The Qt Company Ltd.")
+ endif()
+ set_target_properties(${target} PROPERTIES
+ QT_TARGET_VERSION "${arg_TARGET_VERSION}"
+ QT_TARGET_COMPANY_NAME "${arg_TARGET_COMPANY}"
+ QT_TARGET_DESCRIPTION "${arg_TARGET_DESCRIPTION}"
+ QT_TARGET_COPYRIGHT "${arg_TARGET_COPYRIGHT}"
+ QT_TARGET_PRODUCT_NAME "${arg_TARGET_PRODUCT}")
+endfunction()
+
+# Uses the QT_DELAYED_TARGET_* property values to set the final QT_TARGET_* properties.
+# Needed when doing executable finalization at the end of a subdirectory scope
+# (aka scope finalization).
+function(qt_internal_set_target_info_properties_from_delayed_properties target)
+ set(args "")
+ foreach(prop ${__default_target_info_args})
+ get_target_property(prop_value "${target}" "QT_DELAYED_${prop}")
+ list(APPEND args "${prop}" "${prop_value}")
+ endforeach()
+ qt_set_target_info_properties(${target} ${args})
+endfunction()
+
+# Updates the QT_DELAYED_ properties with values from the QT_ variants, in case if they were
+# set in-between a qt_add_* call and before scope finalization.
+function(qt_internal_update_delayed_target_info_properties target)
+ foreach(prop ${__default_target_info_args})
+ get_target_property(prop_value "${target}" "QT_${prop}")
+ get_target_property(delayed_prop_value ${target} "QT_DELAYED_${prop}")
+ set(final_value "${delayed_prop_value}")
+ if(prop_value)
+ set(final_value "${prop_value}")
+ endif()
+ set_target_properties(${target} PROPERTIES "QT_DELAYED_${prop}" "${final_value}")
+ endforeach()
+endfunction()
+
+function(qt_internal_check_directory_or_type name dir type default result_var)
+ if ("x${dir}" STREQUAL x)
+ if("x${type}" STREQUAL x)
+ message(FATAL_ERROR "qt_internal_add_plugin called without setting either TYPE or ${name}.")
+ endif()
+ set(${result_var} "${default}" PARENT_SCOPE)
+ else()
+ set(${result_var} "${dir}" PARENT_SCOPE)
+ endif()
+endfunction()
+
+function(qt_internal_apply_win_prefix_and_suffix target)
+ if(WIN32)
+ # Table of prefix / suffixes for MSVC libraries as qmake expects them to be created.
+ # static - Qt6EdidSupport.lib (platform support libraries / or static QtCore, etc)
+ # shared - Qt6Core.dll
+ # shared import library - Qt6Core.lib
+ # module aka Qt plugin - qwindows.dll
+ # module import library - qwindows.lib
+ #
+ # The CMake defaults are fine for us.
+
+ # Table of prefix / suffixes for MinGW libraries as qmake expects them to be created.
+ # static - libQt6EdidSupport.a (platform support libraries / or static QtCore, etc)
+ # shared - Qt6Core.dll
+ # shared import library - libQt6Core.a
+ # module aka Qt plugin - qwindows.dll
+ # module import library - libqwindows.a
+ #
+ # CMake for Windows-GNU platforms defaults the prefix to "lib".
+ # CMake for Windows-GNU platforms defaults the import suffix to ".dll.a".
+ # These CMake defaults are not ok for us.
+
+ # This should cover both MINGW with GCC and CLANG.
+ if(NOT MSVC)
+ set_property(TARGET "${target}" PROPERTY IMPORT_SUFFIX ".a")
+
+ get_target_property(target_type ${target} TYPE)
+ if(target_type STREQUAL "STATIC_LIBRARY")
+ set_property(TARGET "${target}" PROPERTY PREFIX "lib")
+ else()
+ set_property(TARGET "${target}" PROPERTY PREFIX "")
+ set_property(TARGET "${target}" PROPERTY IMPORT_PREFIX "lib")
+ endif()
+ endif()
+ endif()
+endfunction()
+
+function(qt_internal_strip_target_directory_scope_token target out_var)
+ # In CMake versions earlier than CMake 3.18, a subdirectory scope id is appended to the
+ # target name if the target is referenced in a target_link_libraries command from a
+ # different directory scope than where the target was created.
+ # Strip it.
+ #
+ # For informational purposes, in CMake 3.18, the target name looks as follows:
+ # ::@(0x5604cb3f6b50);Threads::Threads;::@
+ # This case doesn't have to be stripped (at least for now), because when we iterate over
+ # link libraries, the tokens appear as separate target names.
+ #
+ # Example: Threads::Threads::@<0x5604cb3f6b50>
+ # Output: Threads::Threads
+ string(REGEX REPLACE "::@<.+>$" "" target "${target}")
+ set("${out_var}" "${target}" PARENT_SCOPE)
+endfunction()
+
+function(qt_internal_export_modern_cmake_config_targets_file)
+ cmake_parse_arguments(__arg "" "EXPORT_NAME_PREFIX;CONFIG_INSTALL_DIR" "TARGETS" ${ARGN})
+
+ set(export_name "${__arg_EXPORT_NAME_PREFIX}VersionlessTargets")
+ foreach(target ${__arg_TARGETS})
+ if (TARGET "${target}Versionless")
+ continue()
+ endif()
+
+ add_library("${target}Versionless" INTERFACE)
+ target_link_libraries("${target}Versionless" INTERFACE "${target}")
+ set_target_properties("${target}Versionless" PROPERTIES
+ EXPORT_NAME "${target}"
+ _qt_is_versionless_target "TRUE")
+ set_property(TARGET "${target}Versionless"
+ APPEND PROPERTY EXPORT_PROPERTIES _qt_is_versionless_target)
+
+ qt_install(TARGETS "${target}Versionless" EXPORT ${export_name})
+ endforeach()
+ qt_install(EXPORT ${export_name} NAMESPACE Qt:: DESTINATION "${__arg_CONFIG_INSTALL_DIR}")
+endfunction()
+
+function(qt_create_tracepoints name tracePointsFile)
+ #### TODO
+ string(TOLOWER "${name}" name)
+
+ file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/qt${name}_tracepoints_p.h" CONTENT
+ "#include <private/qtrace_p.h>")
+endfunction()