diff options
-rw-r--r-- | bin/qt-cmake.bat.in | 2 | ||||
-rwxr-xr-x | bin/qt-cmake.in | 2 | ||||
-rw-r--r-- | cmake/QtAutoDetect.cmake | 18 | ||||
-rw-r--r-- | cmake/QtBaseConfigureTests.cmake | 8 | ||||
-rw-r--r-- | cmake/QtBaseGlobalTargets.cmake | 20 | ||||
-rw-r--r-- | cmake/QtBuild.cmake | 48 | ||||
-rw-r--r-- | cmake/QtBuildInternalsExtra.cmake.in | 4 | ||||
-rw-r--r-- | cmake/QtPostProcess.cmake | 27 | ||||
-rw-r--r-- | cmake/QtSetup.cmake | 14 | ||||
-rw-r--r-- | coin/instructions/call_cmake.yaml | 1 | ||||
-rw-r--r-- | src/corelib/Qt6CoreMacros.cmake | 21 | ||||
-rw-r--r-- | src/tools/cmake_automoc_parser/main.cpp | 12 |
12 files changed, 161 insertions, 16 deletions
diff --git a/bin/qt-cmake.bat.in b/bin/qt-cmake.bat.in index f27818a61b..6e5b27010b 100644 --- a/bin/qt-cmake.bat.in +++ b/bin/qt-cmake.bat.in @@ -1 +1 @@ -"@CMAKE_COMMAND@" -DCMAKE_TOOLCHAIN_FILE="@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake" %* +"@CMAKE_COMMAND@" -DCMAKE_TOOLCHAIN_FILE="@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake" @__qt_cmake_extra@ %* diff --git a/bin/qt-cmake.in b/bin/qt-cmake.in index 1797d2ded5..2b42592267 100755 --- a/bin/qt-cmake.in +++ b/bin/qt-cmake.in @@ -1,3 +1,3 @@ #!/bin/sh -exec @CMAKE_COMMAND@ -DCMAKE_TOOLCHAIN_FILE=@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake $* +exec @CMAKE_COMMAND@ -DCMAKE_TOOLCHAIN_FILE=@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake @__qt_cmake_extra@ "$@" diff --git a/cmake/QtAutoDetect.cmake b/cmake/QtAutoDetect.cmake index 1823d1e572..95ace249ad 100644 --- a/cmake/QtAutoDetect.cmake +++ b/cmake/QtAutoDetect.cmake @@ -156,6 +156,24 @@ function(qt_auto_detect_ios) endif() endfunction() +function(qt_auto_detect_cmake_config) + if(CMAKE_CONFIGURATION_TYPES) + # Allow users to specify this option. + if(NOT QT_MULTI_CONFIG_FIRST_CONFIG) + list(GET CMAKE_CONFIGURATION_TYPES 0 first_config_type) + set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}") + set(QT_MULTI_CONFIG_FIRST_CONFIG "${first_config_type}" PARENT_SCOPE) + endif() + + set(CMAKE_TRY_COMPILE_CONFIGURATION "${QT_MULTI_CONFIG_FIRST_CONFIG}" PARENT_SCOPE) + if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config") + set(CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE ON PARENT_SCOPE) + set(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE "${QT_MULTI_CONFIG_FIRST_CONFIG}" PARENT_SCOPE) + endif() + endif() +endfunction() + +qt_auto_detect_cmake_config() qt_auto_detect_ios() qt_auto_detect_android() qt_auto_detect_vpckg() diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake index 777adb7b5f..0d6bb1407b 100644 --- a/cmake/QtBaseConfigureTests.cmake +++ b/cmake/QtBaseConfigureTests.cmake @@ -28,8 +28,14 @@ function(qt_run_config_test_architecture) if (EMSCRIPTEN) set(_arch_file_suffix ".wasm") endif() + + set(arch_test_location "config.tests/arch") + if(QT_MULTI_CONFIG_FIRST_CONFIG) + string(APPEND arch_test_location "/${QT_MULTI_CONFIG_FIRST_CONFIG}") + endif() + set(_arch_file - "${CMAKE_CURRENT_BINARY_DIR}/config.tests/arch/architecture_test${_arch_file_suffix}") + "${CMAKE_CURRENT_BINARY_DIR}/${arch_test_location}/architecture_test${_arch_file_suffix}") if (NOT EXISTS "${_arch_file}") message(FATAL_ERROR "Failed to find compiled architecture detection executable at ${_arch_file}.") diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 5f38f96681..9274512577 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -137,6 +137,26 @@ else() qt_install(PROGRAMS "${QT_BUILD_DIR}/bin/qt-cmake.bat" DESTINATION "${INSTALL_BINDIR}") endif() +# Provide a private convenience wrapper with options which should not be propagated via the public +# qt-cmake wrapper e.g. CMAKE_GENERATOR. +# These options can not be set in a toolchain file, but only on the command line. +# These options should not be in the public wrapper, because a consumer of Qt might want to build +# their CMake app with the Unix Makefiles generator, while Qt should be built with the Ninja +# generator. +# The private wrapper is more conveient for building Qt itself, because a developer doesn't need +# to specify the same options for each qt module built. +set(__qt_cmake_extra "-G\"${CMAKE_GENERATOR}\"") +if(UNIX) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.in" + "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private" @ONLY) + qt_install(PROGRAMS "${QT_BUILD_DIR}/bin/qt-cmake-private" DESTINATION "${INSTALL_BINDIR}") +else() + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.bat.in" + "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private.bat" @ONLY) + qt_install(PROGRAMS "${QT_BUILD_DIR}/bin/qt-cmake-private.bat" DESTINATION "${INSTALL_BINDIR}") +endif() +unset(__qt_cmake_extra) + ## Library to hold global features: ## These features are stored and accessed via Qt::GlobalConfig, but the ## files always lived in Qt::Core, so we keep it that way diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 0b434045b6..0070aac2d7 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -1463,7 +1463,9 @@ function(qt_finalize_framework_headers_copy target) # Create a fake header file and copy it into the framework by marking it as PUBLIC_HEADER. # CMake now takes care of creating the symlink. set(fake_header ${target}_fake_header.h) - file(GENERATE OUTPUT ${fake_header} CONTENT "// ignore this file\n") + qt_get_main_cmake_configuration(main_config) + file(GENERATE OUTPUT ${fake_header} CONTENT "// ignore this file\n" + CONDITION "$<CONFIG:${main_config}>") string(PREPEND fake_header "${CMAKE_CURRENT_BINARY_DIR}/") target_sources(${target} PRIVATE ${fake_header}) set_source_files_properties(${fake_header} PROPERTIES GENERATED ON) @@ -1475,6 +1477,24 @@ function(qt_finalize_framework_headers_copy target) endif() 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) + set(possible_configs "${CMAKE_BUILD_TYPE}") + if(CMAKE_CONFIGURATION_TYPES) + set(possible_configs "${CMAKE_CONFIGURATION_TYPES}") + endif() + 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() + # This is the main entry function for creating a Qt module, that typically # consists of a library, public header files, private header files and configurable # features. @@ -1542,12 +1562,11 @@ function(qt_add_module target) set_target_properties(${target} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}" RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}" - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${QT_BUILD_DIR}/${INSTALL_BINDIR}" - RUNTIME_OUTPUT_DIRECTORY_DEBUG "${QT_BUILD_DIR}/${INSTALL_BINDIR}" ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}" VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR} ) + qt_handle_multi_config_output_dirs("${target}") if(is_framework) set_target_properties(${target} PROPERTIES @@ -2203,6 +2222,7 @@ function(qt_add_plugin target) RUNTIME_OUTPUT_DIRECTORY "${output_directory}" ARCHIVE_OUTPUT_DIRECTORY "${output_directory}" QT_PLUGIN_CLASS_NAME "${arg_CLASS_NAME}") + qt_handle_multi_config_output_dirs("${target}") qt_internal_library_deprecation_level(deprecation_define) @@ -3028,6 +3048,21 @@ function(qt_add_cmake_library target) endfunction() +function(qt_get_tool_cmake_configuration out_var) + qt_get_main_cmake_configuration("${out_var}") + string(TOUPPER "${${out_var}}" upper_config) + set("${out_var}" "${upper_config}" PARENT_SCOPE) +endfunction() + +function(qt_get_main_cmake_configuration out_var) + if(CMAKE_BUILD_TYPE) + set(config "${CMAKE_BUILD_TYPE}") + elseif(QT_MULTI_CONFIG_FIRST_CONFIG) + set(config "${QT_MULTI_CONFIG_FIRST_CONFIG}") + endif() + set("${out_var}" "${config}" PARENT_SCOPE) +endfunction() + # This function is used to define a "Qt tool", such as moc, uic or rcc. # The BOOTSTRAP option allows building it as standalone program, otherwise # it will be linked against QtCore. @@ -3146,8 +3181,11 @@ function(qt_add_tool name) ) qt_internal_add_target_aliases("${name}") + # If building with a multi-config configuration, the main configuration tool will be placed in + # ./bin, while the rest will be in <CONFIG> specific subdirectories. + qt_get_tool_cmake_configuration(tool_cmake_configuration) set_target_properties("${name}" PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_RELEASE "${QT_BUILD_DIR}/${INSTALL_BINDIR}" + RUNTIME_OUTPUT_DIRECTORY_${tool_cmake_configuration} "${QT_BUILD_DIR}/${INSTALL_BINDIR}" ) if(NOT arg_NO_INSTALL AND arg_TOOLS_TARGET) @@ -3394,7 +3432,7 @@ function(qt_add_docs) # Generate include dir list - set(target_include_dirs_file "${doc_ouput_dir}/includes.txt") + set(target_include_dirs_file "${doc_ouput_dir}/$<CONFIG>/includes.txt") set(include_paths_property "$<TARGET_PROPERTY:${target},INCLUDE_DIRECTORIES>") if (NOT target_type STREQUAL "INTERFACE_LIBRARY") diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in index 68e1271781..5278890337 100644 --- a/cmake/QtBuildInternalsExtra.cmake.in +++ b/cmake/QtBuildInternalsExtra.cmake.in @@ -3,7 +3,6 @@ set(QT_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) option(BUILD_SHARED_LIBS "Build Qt statically or dynamically" @BUILD_SHARED_LIBS@) set(QT_CMAKE_EXPORT_NAMESPACE @QT_CMAKE_EXPORT_NAMESPACE@) set(INSTALL_CMAKE_NAMESPACE @INSTALL_CMAKE_NAMESPACE@) -set(CMAKE_BUILD_TYPE @CMAKE_BUILD_TYPE@) set(QT_BUILD_INTERNALS_PATH "${CMAKE_CURRENT_LIST_DIR}") # Propagate the original install prefix, so that a developer building a child module can @@ -31,5 +30,8 @@ set(QT_NO_MAKE_TESTS @QT_NO_MAKE_TESTS@ CACHE BOOL set(QT_NO_MAKE_EXAMPLES @QT_NO_MAKE_EXAMPLES@ CACHE BOOL "Should examples be built as part of the default 'all' target.") +# Propagate usage of ccache. +set(QT_USE_CCACHE @QT_USE_CCACHE@ CACHE BOOL "Enable the use of ccache") + # Extra set of exported variables @QT_EXTRA_BUILD_INTERNALS_VARS@ diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake index b20b85bef9..807b32063d 100644 --- a/cmake/QtPostProcess.cmake +++ b/cmake/QtPostProcess.cmake @@ -298,7 +298,6 @@ endfunction() function(qt_generate_build_internals_extra_cmake_code) if(PROJECT_NAME STREQUAL "QtBase") - set(QT_EXTRA_BUILD_INTERNALS_VARS) foreach(var IN LISTS QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT) string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "set(${var} \"${${var}}\" CACHE INTERNAL \"\")\n") endforeach() @@ -307,6 +306,32 @@ function(qt_generate_build_internals_extra_cmake_code) qt_path_join(extra_file_path ${QT_CONFIG_BUILD_DIR} ${INSTALL_CMAKE_NAMESPACE}BuildInternals/QtBuildInternalsExtra.cmake) + + if(CMAKE_BUILD_TYPE) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(CMAKE_BUILD_TYPE \"${CMAKE_BUILD_TYPE}\")\n") + endif() + if(CMAKE_CONFIGURATION_TYPES) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(CMAKE_CONFIGURATION_TYPES \"${CMAKE_CONFIGURATION_TYPES}\")\n") + endif() + if(CMAKE_TRY_COMPILE_CONFIGURATION) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(CMAKE_TRY_COMPILE_CONFIGURATION \"${CMAKE_TRY_COMPILE_CONFIGURATION}\")\n") + endif() + if(QT_MULTI_CONFIG_FIRST_CONFIG) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(QT_MULTI_CONFIG_FIRST_CONFIG \"${QT_MULTI_CONFIG_FIRST_CONFIG}\")\n") + endif() + if(CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE \"${CMAKE_NINJA_MULTI_CROSS_CONFIG_ENABLE}\")\n") + endif() + if(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE) + string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS + "set(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE \"${CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE}\")\n") + endif() + configure_file( "${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake.in" "${extra_file_path}" diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index 65bd5b9a21..90588c99b3 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -10,10 +10,22 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/.git") set(_default_build_type "Debug") endif() +# Reset content of extra build internal vars for each inclusion of QtSetup. +unset(QT_EXTRA_BUILD_INTERNALS_VARS) + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) message(STATUS "Setting build type to '${_default_build_type}' as none was specified.") set(CMAKE_BUILD_TYPE "${_default_build_type}" CACHE STRING "Choose the type of build." FORCE) - set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") # Set the possible values of build type for cmake-gui + set_property(CACHE CMAKE_BUILD_TYPE + PROPERTY STRINGS + "Debug" "Release" "MinSizeRel" "RelWithDebInfo") # Set the possible values for cmake-gui. +elseif(CMAKE_CONFIGURATION_TYPES) + message(STATUS "Building for multiple configurations: ${CMAKE_CONFIGURATION_TYPES}.") + message(STATUS "Main configuration is: ${QT_MULTI_CONFIG_FIRST_CONFIG}.") + if(CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE) + message(STATUS + "Default build configuration set to '${CMAKE_NINJA_MULTI_DEFAULT_BUILD_TYPE}'.") + endif() endif() # Appends a 'debug postfix' to library targets (not executables) diff --git a/coin/instructions/call_cmake.yaml b/coin/instructions/call_cmake.yaml index 06a8980099..421a7c2ed1 100644 --- a/coin/instructions/call_cmake.yaml +++ b/coin/instructions/call_cmake.yaml @@ -13,6 +13,7 @@ instructions: equals_value: Windows - type: ExecuteCommand command: "{{.InstallDir}}/bin/qt-cmake {{.Env.COIN_CMAKE_ARGS}}" + executeCommandArgumentSplitingBehavior: SplitAfterVariableSubstitution maxTimeInSeconds: 6000 maxTimeBetweenOutput: 1200 userMessageOnFailure: > diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index da0b4641ae..cf860cd9ad 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -543,8 +543,20 @@ function(qt6_generate_meta_types_json_file target) get_target_property(target_binary_dir ${target} BINARY_DIR) - set(cmake_autogen_cache_file - "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache.txt") + if(CMAKE_BUILD_TYPE) + set(cmake_autogen_cache_file + "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache.txt") + set(mutli_config_args + --cmake-autogen-include-dir-path "${target_binary_dir}/${target}_autogen/include" + ) + else() + set(cmake_autogen_cache_file + "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/ParseCache_$<CONFIG>.txt") + set(mutli_config_args + --cmake-autogen-include-dir-path "${target_binary_dir}/${target}_autogen/include_$<CONFIG>" + "--cmake-multi-config") + endif() + set(cmake_autogen_info_file "${target_binary_dir}/CMakeFiles/${target}_autogen.dir/AutogenInfo.json") set(type_list_file "${target_binary_dir}/meta_types/json_file_list.txt") @@ -556,8 +568,9 @@ function(qt6_generate_meta_types_json_file target) --cmake-autogen-cache-file "${cmake_autogen_cache_file}" --cmake-autogen-info-file "${cmake_autogen_info_file}" --output-file-path "${type_list_file}" - --cmake-autogen-include-dir-path "${target_binary_dir}/${target}_autogen/include" + ${mutli_config_args} COMMENT "Running Automoc file extraction" + COMMAND_EXPAND_LISTS ) add_dependencies(${target}_automoc_json_extraction ${target}_autogen) @@ -565,7 +578,7 @@ function(qt6_generate_meta_types_json_file target) if (CMAKE_BUILD_TYPE) string(TOLOWER ${target}_${CMAKE_BUILD_TYPE} target_lowercase) else() - message(FATAL_ERROR "add_custom_command's OUTPUT parameter does not support generator expressions, so we can't generate this file for multi-config generators") + string(TOLOWER ${target} target_lowercase) endif() set(metatypes_file "${target_binary_dir}/meta_types/qt6${target_lowercase}_metatypes.json") add_custom_command(OUTPUT ${metatypes_file} diff --git a/src/tools/cmake_automoc_parser/main.cpp b/src/tools/cmake_automoc_parser/main.cpp index 456b06b072..60eb4b2977 100644 --- a/src/tools/cmake_automoc_parser/main.cpp +++ b/src/tools/cmake_automoc_parser/main.cpp @@ -264,6 +264,12 @@ int main(int argc, char **argv) cmakeAutogenIncludeDirOption.setValueName(QStringLiteral("CMake AutoGen include directory")); parser.addOption(cmakeAutogenIncludeDirOption); + QCommandLineOption isMultiConfigOption( + QStringLiteral("cmake-multi-config")); + isMultiConfigOption.setDescription( + QStringLiteral("Set this option when using CMake with a multi-config generator")); + parser.addOption(isMultiConfigOption); + QStringList arguments = QCoreApplication::arguments(); parser.process(arguments); @@ -354,13 +360,17 @@ int main(int argc, char **argv) } // 2) Process headers + const bool isMultiConfig = parser.isSet(isMultiConfigOption); for (auto mapIt = autoGenHeaders.begin(); mapIt != autoGenHeaders.end(); ++mapIt) { auto it = parseCacheEntries.find(mapIt.key()); if (it == parseCacheEntries.end()) { continue; } + const QString pathPrefix = !isMultiConfig + ? QStringLiteral("../") + : QString(); const QString jsonPath = - dir.filePath(QLatin1String("../") + mapIt.value() + QLatin1String(".json")); + dir.filePath(pathPrefix + mapIt.value() + QLatin1String(".json")); jsonFileList.push_back(jsonPath); } |