diff options
Diffstat (limited to 'cmake/QtProcessConfigureArgs.cmake')
-rw-r--r-- | cmake/QtProcessConfigureArgs.cmake | 576 |
1 files changed, 455 insertions, 121 deletions
diff --git a/cmake/QtProcessConfigureArgs.cmake b/cmake/QtProcessConfigureArgs.cmake index 258a4a09e1..c64403b209 100644 --- a/cmake/QtProcessConfigureArgs.cmake +++ b/cmake/QtProcessConfigureArgs.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # This script reads Qt configure arguments from config.opt, # translates the arguments to CMake arguments and calls CMake. # @@ -25,11 +28,38 @@ macro(pop_path_argument) file(TO_CMAKE_PATH "${path}" path) endmacro() +function(is_non_empty_valid_arg arg value) + if(value STREQUAL "") + message(FATAL_ERROR "Value supplied to command line option '${arg}' is empty.") + elseif(value MATCHES "^-.*") + message(FATAL_ERROR + "Value supplied to command line option '${arg}' is invalid: ${value}") + endif() +endfunction() + +function(warn_in_per_repo_build arg) + if(NOT TOP_LEVEL) + message(WARNING "Command line option ${arg} is only effective in top-level builds") + endif() +endfunction() + +function(is_valid_qt_hex_version arg version) + if(NOT version MATCHES "^0x[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$") + message(FATAL_ERROR "Incorrect version ${version} specified for ${arg}") + endif() +endfunction() + if("${MODULE_ROOT}" STREQUAL "") # If MODULE_ROOT is not set, assume that we want to build qtbase or top-level. get_filename_component(MODULE_ROOT ".." ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}") + set(qtbase_or_top_level_build TRUE) else() - file(TO_CMAKE_PATH "${MODULE_ROOT}" MODULE_ROOT) + # If MODULE_ROOT is passed without drive letter, we try to add it to the path. + # The check is necessary; otherwise, `get_filename_component` returns an empty string. + if(NOT MODULE_ROOT STREQUAL ".") + get_filename_component(MODULE_ROOT "." REALPATH BASE_DIR "${MODULE_ROOT}") + endif() + set(qtbase_or_top_level_build FALSE) endif() set(configure_filename "configure.cmake") set(commandline_filename "qt_cmdline.cmake") @@ -43,19 +73,29 @@ else() set(commandline_files "${MODULE_ROOT}/${commandline_filename}") endif() file(STRINGS "${OPTFILE}" configure_args) + +# list(TRANSFORM ...) unexpectedly removes semicolon escaping in list items. So the list arguments +# seem to be broken. The 'bracket argument' suppresses this behavior. Right before forwarding +# command line arguments to the cmake call, 'bracket arguments' are replaced by escaped semicolons +# back. +list(TRANSFORM configure_args REPLACE ";" "[[;]]") + list(FILTER configure_args EXCLUDE REGEX "^[ \t]*$") list(TRANSFORM configure_args STRIP) -list(TRANSFORM configure_args REPLACE "\\\\" "\\\\\\\\") unset(generator) -set(auto_detect_generator TRUE) set(auto_detect_compiler TRUE) +set(auto_detect_generator ${qtbase_or_top_level_build}) +set(no_prefix_option FALSE) unset(device_options) +unset(options_json_file) set_property(GLOBAL PROPERTY UNHANDLED_ARGS "") while(NOT "${configure_args}" STREQUAL "") - list(POP_FRONT configure_args arg) - if(arg STREQUAL "-cmake") - # ignore - elseif(arg STREQUAL "-cmake-generator") + list(POP_FRONT configure_args raw_arg) + + # Condense '--foo-bar' arguments into '-foo-bar'. + string(REGEX REPLACE "^--([^-])" "-\\1" arg "${raw_arg}") + + if(arg STREQUAL "-cmake-generator") list(POP_FRONT configure_args generator) elseif(arg STREQUAL "-cmake-use-default-generator") set(auto_detect_generator FALSE) @@ -63,15 +103,38 @@ while(NOT "${configure_args}" STREQUAL "") set(auto_detect_compiler FALSE) elseif(arg STREQUAL "-list-features") set(list_features TRUE) + elseif(arg MATCHES "^-h(elp)?$") + set(display_module_help TRUE) + elseif(arg STREQUAL "-write-options-for-conan") + list(POP_FRONT configure_args options_json_file) elseif(arg STREQUAL "-skip") - list(POP_FRONT configure_args qtrepo) - push("-DBUILD_${qtrepo}=OFF") - elseif(arg STREQUAL "-hostprefix") - message(FATAL_ERROR "${arg} is not supported in the CMake build.") - elseif(arg STREQUAL "-external-hostbindir") - # This points to the bin directory of the Qt installation. - # This can be multiple levels deep and we cannot deduce the QT_HOST_PATH safely. - message(FATAL_ERROR "${arg} is not supported anymore. Use -qt-host-path <dir> instead.") + warn_in_per_repo_build("${arg}") + list(POP_FRONT configure_args qtrepos) + is_non_empty_valid_arg("${arg}" "${qtrepos}") + list(TRANSFORM qtrepos REPLACE "," ";") + foreach(qtrepo IN LISTS qtrepos) + push("-DBUILD_${qtrepo}=OFF") + endforeach() + elseif(arg STREQUAL "-skip-tests") + list(POP_FRONT configure_args qtrepos) + is_non_empty_valid_arg("${arg}" "${qtrepos}") + list(TRANSFORM qtrepos REPLACE "," ";") + foreach(qtrepo IN LISTS qtrepos) + push("-DQT_BUILD_TESTS_PROJECT_${qtrepo}=OFF") + endforeach() + elseif(arg STREQUAL "-skip-examples") + list(POP_FRONT configure_args qtrepos) + is_non_empty_valid_arg("${arg}" "${qtrepos}") + list(TRANSFORM qtrepos REPLACE "," ";") + foreach(qtrepo IN LISTS qtrepos) + push("-DQT_BUILD_EXAMPLES_PROJECT_${qtrepo}=OFF") + endforeach() + elseif(arg STREQUAL "-submodules") + warn_in_per_repo_build("${arg}") + list(POP_FRONT configure_args submodules) + is_non_empty_valid_arg("${arg}" "${submodules}") + list(TRANSFORM submodules REPLACE "," "[[;]]") + push("-DQT_BUILD_SUBMODULES=${submodules}") elseif(arg STREQUAL "-qt-host-path") pop_path_argument() push("-DQT_HOST_PATH=${path}") @@ -81,17 +144,75 @@ while(NOT "${configure_args}" STREQUAL "") string(APPEND path "/mkspecs") endif() push("-DINSTALL_MKSPECSDIR=${path}") - elseif(arg MATCHES "^-host.*dir") - message(FATAL_ERROR "${arg} is not supported anymore.") - elseif(arg STREQUAL "--") + elseif(arg STREQUAL "-developer-build") + set(developer_build TRUE) + push("-DFEATURE_developer_build=ON") + elseif(arg STREQUAL "-no-prefix") + set(no_prefix_option TRUE) + push("-DFEATURE_no_prefix=ON") + elseif(arg STREQUAL "-cmake-file-api") + set(cmake_file_api TRUE) + elseif(arg STREQUAL "-no-cmake-file-api") + set(cmake_file_api FALSE) + elseif(arg STREQUAL "-verbose") + list(APPEND cmake_args "--log-level=STATUS") + elseif(arg STREQUAL "-disable-deprecated-up-to") + list(POP_FRONT configure_args version) + is_valid_qt_hex_version("${arg}" "${version}") + push("-DQT_DISABLE_DEPRECATED_UP_TO=${version}") + elseif(raw_arg STREQUAL "--") # Everything after this argument will be passed to CMake verbatim. - push(${configure_args}) + list(APPEND cmake_args "${configure_args}") break() else() set_property(GLOBAL APPEND PROPERTY UNHANDLED_ARGS "${arg}") endif() endwhile() +# Read the specified manually generator value from CMake command line. +# The '-cmake-generator' argument has higher priority than CMake command line. +if(NOT generator) + set(is_next_arg_generator_name FALSE) + foreach(arg IN LISTS cmake_args) + if(is_next_arg_generator_name) + set(is_next_arg_generator_name FALSE) + if(NOT arg MATCHES "^-.*") + set(generator "${arg}") + set(auto_detect_generator FALSE) + endif() + elseif(arg MATCHES "^-G(.*)") + set(generator "${CMAKE_MATCH_1}") + if(generator) + set(auto_detect_generator FALSE) + else() + set(is_next_arg_generator_name TRUE) + endif() + endif() + endforeach() +endif() + +# Attempt to detect the generator type, either single or multi-config +if("${generator}" STREQUAL "Xcode" + OR "${generator}" STREQUAL "Ninja Multi-Config" + OR "${generator}" MATCHES "^Visual Studio") + set(multi_config ON) +else() + set(multi_config OFF) +endif() + +# Tell the build system we are configuring via the configure script so we can act on that. +# The cache variable is unset at the end of configuration. +push("-DQT_INTERNAL_CALLED_FROM_CONFIGURE:BOOL=TRUE") + +if(FRESH_REQUESTED) + push("-DQT_INTERNAL_FRESH_REQUESTED:BOOL=TRUE") + if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24") + push("--fresh") + else() + file(REMOVE_RECURSE "${CMAKE_BINARY_DIR}/CMakeCache.txt" + "${CMAKE_BINARY_DIR}/CMakeFiles") + endif() +endif() #################################################################################################### # Define functions/macros that are called in configure.cmake files @@ -109,6 +230,11 @@ function(qt_feature feature) set_property(GLOBAL PROPERTY COMMANDLINE_FEATURE_SECTION_${feature} "${arg_SECTION}") endfunction() +function(find_package) + message(FATAL_ERROR "find_package must not be used directly in configure.cmake. " + "Use qt_find_package or guard the call with an if(NOT QT_CONFIGURE_RUNNING) block.") +endfunction() + macro(defstub name) function(${name}) endfunction() @@ -133,15 +259,16 @@ defstub(qt_feature_definition) defstub(qt_find_package) defstub(set_package_properties) defstub(qt_qml_find_python) - +defstub(qt_set01) +defstub(qt_internal_check_if_linker_is_available) #################################################################################################### # Define functions/macros that are called in qt_cmdline.cmake files #################################################################################################### +unset(commandline_known_options) unset(commandline_custom_handlers) set(commandline_nr_of_prefixes 0) -set(commandline_nr_of_assignments 0) macro(qt_commandline_subconfig subconfig) list(APPEND commandline_subconfigs "${subconfig}") @@ -152,15 +279,23 @@ macro(qt_commandline_custom handler) endmacro() function(qt_commandline_option name) - set(options) + set(options CONTROLS_FEATURE) set(oneValueArgs TYPE NAME VALUE) set(multiValueArgs VALUES MAPPING) cmake_parse_arguments(arg "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + set(commandline_known_options "${commandline_known_options};${name}" PARENT_SCOPE) set(commandline_option_${name} "${arg_TYPE}" PARENT_SCOPE) + set(input_name ${name}) if(NOT "${arg_NAME}" STREQUAL "") + set(input_name ${arg_NAME}) set(commandline_option_${name}_variable "${arg_NAME}" PARENT_SCOPE) endif() + set(mapping_type "${arg_TYPE}") + if(arg_CONTROLS_FEATURE) + set(mapping_type "boolean") + endif() + set_property(GLOBAL PROPERTY INPUTTYPE_${input_name} "${mapping_type}") if(NOT "${arg_VALUE}" STREQUAL "") set(commandline_option_${name}_value "${arg_VALUE}" PARENT_SCOPE) endif() @@ -171,6 +306,11 @@ function(qt_commandline_option name) endif() endfunction() +# Add the common command line options for every qt repo. +macro(qt_add_common_commandline_options) + qt_commandline_option(headersclean TYPE boolean) +endmacro() + function(qt_commandline_prefix arg var) set(idx ${commandline_nr_of_prefixes}) set(commandline_prefix_${idx} "${arg}" "${var}" PARENT_SCOPE) @@ -178,18 +318,17 @@ function(qt_commandline_prefix arg var) set(commandline_nr_of_prefixes ${n} PARENT_SCOPE) endfunction() -function(qt_commandline_assignment var internal_var) - set(idx ${commandline_nr_of_assignments}) - set(commandline_assignment_${idx} "${var}" "${internal_var}" PARENT_SCOPE) - math(EXPR n "${commandline_nr_of_assignments} + 1") - set(commandline_nr_of_assignments ${n} PARENT_SCOPE) -endfunction() +# Check the following variable in configure.cmake files to guard code that is not covered by the +# stub functions above. +set(QT_CONFIGURE_RUNNING ON) #################################################################################################### # Load qt_cmdline.cmake files #################################################################################################### +qt_add_common_commandline_options() + while(commandline_files) list(POP_FRONT commandline_files commandline_file) get_filename_component(commandline_file_directory "${commandline_file}" DIRECTORY) @@ -254,6 +393,23 @@ function(qtConfCommandlineAppendInput name val) qtConfCommandlineSetInput(${name} "${val}") endfunction() +function(qtConfCommandlineSetInputType input_name type_name) + set_property(GLOBAL PROPERTY INPUTTYPE_${input_name} "${type_name}") +endfunction() + +function(qtConfCommandlineSetBooleanInput name val) + qtConfCommandlineSetInput(${name} ${val}) + qtConfCommandlineSetInputType(${name} boolean) +endfunction() + +function(qtConfCommandlineEnableFeature name) + qtConfCommandlineSetBooleanInput(${name} yes) +endfunction() + +function(qtConfCommandlineDisableFeature name) + qtConfCommandlineSetBooleanInput(${name} no) +endfunction() + function(qtConfValidateValue opt val out_var) set(${out_var} TRUE PARENT_SCOPE) @@ -270,7 +426,9 @@ function(qtConfValidateValue opt val out_var) endforeach() set(${out_var} FALSE PARENT_SCOPE) - qtConfAddError("Invalid value '${val}' supplied to command line option '${opt}'.") + list(JOIN valid_values " " valid_values_str) + qtConfAddError("Invalid value '${val}' supplied to command line option '${opt}'." + "\nAllowed values: ${valid_values_str}\n") endfunction() function(qt_commandline_mapped_enum_value opt key out_var) @@ -361,7 +519,7 @@ function(qt_commandline_addString arg val nextok) qtConfValidateValue("${arg}" "${val}" success) if(success) if(DEFINED command_line_option_${arg}_variable) - set(opt ${command_line_option_${arg}_variable) + set(arg ${command_line_option_${arg}_variable}) endif() set_property(GLOBAL APPEND PROPERTY "INPUT_${arg}" "${val}") set_property(GLOBAL APPEND PROPERTY CONFIG_INPUTS ${arg}) @@ -417,6 +575,26 @@ function(qt_call_function func) endif() endfunction() +if(display_module_help) + message([[ +Options: + -help, -h ............ Display this help screen + + -feature-<feature> ... Enable <feature> + -no-feature-<feature> Disable <feature> [none] + -list-features ....... List available features. Note that some features + have dedicated command line options as well. +]]) + + set(help_file "${MODULE_ROOT}/config_help.txt") + if(EXISTS "${help_file}") + file(READ "${help_file}" content) + message("${content}") + endif() + + return() +endif() + if(list_features) unset(lines) foreach(feature ${commandline_known_features}) @@ -437,6 +615,78 @@ if(list_features) return() endif() +function(write_options_json_file) + if(qtbase_or_top_level_build) + # Add options that are handled directly by this script. + qt_commandline_option(qt-host-path TYPE string) + qt_commandline_option(no-guess-compiler TYPE void) + endif() + + set(indent " ") + set(content + "{" + "${indent}\"options\": {") + string(APPEND indent " ") + list(LENGTH commandline_known_options commandline_known_options_length) + set(i 1) + foreach(opt ${commandline_known_options}) + list(APPEND content "${indent}\"${opt}\": {") + string(APPEND indent " ") + list(APPEND content "${indent}\"type\": \"${commandline_option_${opt}}\",") + if(NOT "${commandline_option_${opt}_values}" STREQUAL "") + set(values "${commandline_option_${opt}_values}") + list(TRANSFORM values PREPEND "\"") + list(TRANSFORM values APPEND "\"") + list(JOIN values ", " values) + list(APPEND content "${indent}\"values\": [${values}]") + elseif(NOT "${commandline_option_${opt}_mapping}" STREQUAL "") + list(LENGTH commandline_option_${opt}_mapping last) + math(EXPR last "${last} - 1") + set(values "") + list(APPEND content "${indent}\"values\": [") + foreach(k RANGE 0 "${last}" 2) + list(GET commandline_option_${opt}_mapping ${k} value) + list(APPEND values ${value}) + endforeach() + list(TRANSFORM values PREPEND "\"") + list(TRANSFORM values APPEND "\"") + list(JOIN values ", " values) + list(APPEND content + "${indent} ${values}" + "${indent}]") + else() + list(APPEND content "${indent}\"values\": []") + endif() + string(SUBSTRING "${indent}" 4 -1 indent) + math(EXPR i "${i} + 1") + if(i LESS commandline_known_options_length) + list(APPEND content "${indent}},") + else() + list(APPEND content "${indent}}") + endif() + endforeach() + string(SUBSTRING "${indent}" 4 -1 indent) + + set(features ${commandline_known_features}) + list(TRANSFORM features PREPEND "\"") + list(TRANSFORM features APPEND "\"") + list(JOIN features ", " features) + + list(APPEND content + "${indent}}," + "${indent}\"features\": [${features}]" + "}") + string(REPLACE ";" "\n" content "${content}") + file(WRITE "${options_json_file}" "${content}") +endfunction() + +if(options_json_file) + write_options_json_file() + return() +endif() + +set(cmake_var_assignments) + while(1) qtConfHasNextCommandlineArg(has_next) if(NOT has_next) @@ -455,24 +705,9 @@ while(1) continue() endif() - if(arg MATCHES "^([A-Z0-9_]+)=(.*)") - set(lhs "${CMAKE_MATCH_1}") - set(rhs "${CMAKE_MATCH_2}") - math(EXPR n "${commandline_nr_of_assignments} - 1") - foreach(i RANGE ${n}) - list(GET commandline_assignment_${i} 0 var) - list(GET commandline_assignment_${i} 1 internal_var) - if(lhs STREQUAL var) - set(handled TRUE) - qtConfCommandlineSetInput("${internal_var}" "${rhs}") - break() - endif() - endforeach() - if(NOT handled) - message(FATAL_ERROR "Assigning unknown variable '${lhs}' on command line.") - endif() - endif() - if(handled) + # Handle variable assignments + if(arg MATCHES "^([a-zA-Z0-9_][a-zA-Z0-9_-]*)=(.*)") + list(APPEND cmake_var_assignments "${arg}") continue() endif() @@ -481,6 +716,20 @@ while(1) if(arg MATCHES "^--?enable-(.*)") set(opt "${CMAKE_MATCH_1}") set(val "yes") + # Handle builtin [-no]-feature-xxx + elseif(arg MATCHES "^--?(no-)?feature-(.*)") + set(opt "${CMAKE_MATCH_2}") + if(NOT opt IN_LIST commandline_known_features) + qtConfAddError("Enabling/Disabling unknown feature '${opt}'.") + endif() + if("${CMAKE_MATCH_1}" STREQUAL "") + set(val "ON") + else() + set(val "OFF") + endif() + qt_feature_normalize_name("${opt}" normalized_feature_name) + push(-DFEATURE_${normalized_feature_name}=${val}) + continue() elseif(arg MATCHES "^--?(disable|no)-(.*)") set(opt "${CMAKE_MATCH_2}") set(val "no") @@ -497,7 +746,6 @@ while(1) if(NOT DEFINED commandline_option_${opt} AND opt MATCHES "(qt|system)-(.*)") set(opt "${CMAKE_MATCH_2}") set(val "${CMAKE_MATCH_1}") - message("opt: ${opt} val: ${val}") endif() else() qtConfAddError("Invalid command line parameter '${arg}'.") @@ -518,15 +766,6 @@ while(1) endforeach() endif() - # Handle builtin [-no]-feature-xxx - if("${type}" STREQUAL "" AND opt MATCHES "^feature-(.*)") - set(opt "${CMAKE_MATCH_1}") - if(NOT opt IN_LIST commandline_known_features) - qtConfAddError("Enabling/Disabling unknown feature '${opt}'.") - endif() - set(type boolean) - endif() - if("${type}" STREQUAL "") qtConfAddError("Unknown command line option '${arg}'.") endif() @@ -546,6 +785,9 @@ get_property(config_inputs GLOBAL PROPERTY CONFIG_INPUTS) list(REMOVE_DUPLICATES config_inputs) foreach(var ${config_inputs}) get_property(INPUT_${var} GLOBAL PROPERTY INPUT_${var}) + if("${commandline_input_type}" STREQUAL "") + get_property(commandline_input_${var}_type GLOBAL PROPERTY INPUTTYPE_${var}) + endif() endforeach() macro(drop_input name) @@ -581,45 +823,117 @@ endmacro() macro(translate_list_input name cmake_var) if(DEFINED INPUT_${name}) - list(JOIN INPUT_${name} "\\;" value) + list(JOIN INPUT_${name} "[[;]]" value) list(APPEND cmake_args "-D${cmake_var}=${value}") drop_input(${name}) endif() endmacro() +# Check whether to guess the compiler for the given language. +# +# Sets ${out_var} to FALSE if one of the following holds: +# - the environment variable ${env_var} is non-empty +# - the CMake variable ${cmake_var} is set on the command line +# +# Otherwise, ${out_var} is set to TRUE. +function(check_whether_to_guess_compiler out_var env_var cmake_var) + set(result TRUE) + if(NOT "$ENV{${env_var}}" STREQUAL "") + set(result FALSE) + else() + set(filtered_args ${cmake_args}) + list(FILTER filtered_args INCLUDE REGEX "^(-D)?${cmake_var}=") + if(NOT "${filtered_args}" STREQUAL "") + set(result FALSE) + endif() + endif() + set(${out_var} ${result} PARENT_SCOPE) +endfunction() + +# Try to guess the mkspec from the -platform configure argument. function(guess_compiler_from_mkspec) if(NOT auto_detect_compiler) return() endif() + + check_whether_to_guess_compiler(guess_c_compiler CC CMAKE_C_COMPILER) + check_whether_to_guess_compiler(guess_cxx_compiler CXX CMAKE_CXX_COMPILER) + if(NOT guess_c_compiler AND NOT guess_cxx_compiler) + return() + endif() + string(REGEX MATCH "(^|;)-DQT_QMAKE_TARGET_MKSPEC=\([^;]+\)" m "${cmake_args}") set(mkspec ${CMAKE_MATCH_2}) - if(mkspec MATCHES "-clang(-|$)" AND NOT mkspec MATCHES "android") - push("-DCMAKE_C_COMPILER=clang") - push("-DCMAKE_CXX_COMPILER=clang++") - elseif(mkspec MATCHES "-icc(-|$)") - push("-DCMAKE_C_COMPILER=icc") - push("-DCMAKE_CXX_COMPILER=icpc") + set(c_compiler "") + set(cxx_compiler "") + if(mkspec MATCHES "-clang-msvc$") + set(c_compiler "clang-cl") + set(cxx_compiler "clang-cl") + elseif(mkspec MATCHES "-clang(-|$)" AND NOT mkspec MATCHES "android") + set(c_compiler "clang") + set(cxx_compiler "clang++") + elseif(mkspec MATCHES "-msvc(-|$)") + set(c_compiler "cl") + set(cxx_compiler "cl") + endif() + if(guess_c_compiler AND NOT c_compiler STREQUAL "") + push("-DCMAKE_C_COMPILER=${c_compiler}") + endif() + if(guess_cxx_compiler AND NOT cxx_compiler STREQUAL "") + push("-DCMAKE_CXX_COMPILER=${cxx_compiler}") + endif() + if(mkspec MATCHES "-libc\\+\\+$") + push("-DFEATURE_stdlib_libcpp=ON") endif() set(cmake_args "${cmake_args}" PARENT_SCOPE) endfunction() +function(check_qt_build_parts type) + set(input "INPUT_${type}") + set(buildFlag "TRUE") + if("${type}" STREQUAL "nomake") + set(buildFlag "FALSE") + endif() + + list(APPEND knownParts "tests" "examples" "benchmarks" "manual-tests" "minimal-static-tests") + + foreach(part ${${input}}) + if(part IN_LIST knownParts) + qt_feature_normalize_name("${part}" partUpperCase) + string(TOUPPER "${partUpperCase}" partUpperCase) + push("-DQT_BUILD_${partUpperCase}=${buildFlag}") + continue() + elseif("${part}" STREQUAL "tools" AND "${type}" STREQUAL "make") + # default true ignored + continue() + endif() + qtConfAddWarning("'-${type} ${part}' is not implemented yet.") + endforeach() + set(cmake_args "${cmake_args}" PARENT_SCOPE) +endfunction() + drop_input(commercial) drop_input(confirm-license) translate_boolean_input(precompile_header BUILD_WITH_PCH) +translate_boolean_input(unity_build QT_UNITY_BUILD) +translate_string_input(unity_build_batch_size QT_UNITY_BUILD_BATCH_SIZE) translate_boolean_input(ccache QT_USE_CCACHE) +translate_boolean_input(vcpkg QT_USE_VCPKG) translate_boolean_input(shared BUILD_SHARED_LIBS) translate_boolean_input(warnings_are_errors WARNINGS_ARE_ERRORS) +translate_boolean_input(qtinlinenamespace QT_INLINE_NAMESPACE) translate_string_input(qt_namespace QT_NAMESPACE) translate_string_input(qt_libinfix QT_LIBINFIX) translate_string_input(qreal QT_COORD_TYPE) translate_path_input(prefix CMAKE_INSTALL_PREFIX) translate_path_input(extprefix CMAKE_STAGING_PREFIX) -foreach(kind bin lib archdata libexec qml data doc translation sysconf examples tests) +foreach(kind bin lib archdata libexec qml data doc sysconf examples tests) string(TOUPPER ${kind} uc_kind) translate_path_input(${kind}dir INSTALL_${uc_kind}DIR) endforeach() translate_path_input(headerdir INSTALL_INCLUDEDIR) translate_path_input(plugindir INSTALL_PLUGINSDIR) +translate_path_input(translationdir INSTALL_TRANSLATIONSDIR) if(NOT "${INPUT_device}" STREQUAL "") push("-DQT_QMAKE_TARGET_MKSPEC=devices/${INPUT_device}") @@ -629,20 +943,12 @@ translate_string_input(platform QT_QMAKE_TARGET_MKSPEC) translate_string_input(xplatform QT_QMAKE_TARGET_MKSPEC) guess_compiler_from_mkspec() translate_string_input(qpa_default_platform QT_QPA_DEFAULT_PLATFORM) -translate_list_input(sanitize ECM_ENABLE_SANITIZERS) translate_path_input(android-sdk ANDROID_SDK_ROOT) translate_path_input(android-ndk ANDROID_NDK_ROOT) -if(DEFINED INPUT_android-ndk-host) - drop_input(android-ndk-host) - qtConfAddWarning("The -android-ndk-host option is not supported with the CMake build. " - "Determining the right host platform is handled by the CMake toolchain file that is " - "located in your NDK.") -endif() if(DEFINED INPUT_android-ndk-platform) drop_input(android-ndk-platform) - string(REGEX REPLACE "^android-" "" INPUT_android-ndk-platform "${INPUT_android-ndk-platform}") - push("-DANDROID_NATIVE_API_LEVEL=${INPUT_android-ndk-platform}") + push("-DANDROID_PLATFORM=${INPUT_android-ndk-platform}") endif() if(DEFINED INPUT_android-abis) if(INPUT_android-abis MATCHES ",") @@ -654,41 +960,14 @@ endif() translate_string_input(android-javac-source QT_ANDROID_JAVAC_SOURCE) translate_string_input(android-javac-target QT_ANDROID_JAVAC_TARGET) -translate_string_input(sdk QT_UIKIT_SDK) -if(DEFINED INPUT_sdk OR (DEFINED INPUT_xplatform AND INPUT_xplatform STREQUAL "macx-ios-clang")) - push("-DCMAKE_SYSTEM_NAME=iOS") -endif() +translate_string_input(sdk QT_APPLE_SDK) drop_input(make) drop_input(nomake) +translate_boolean_input(install-examples-sources QT_INSTALL_EXAMPLES_SOURCES) -foreach(part ${INPUT_nomake}) - if("${part}" STREQUAL "tests") - push("-DQT_BUILD_TESTS=OFF") - continue() - endif() - if("${part}" STREQUAL "examples") - push("-DQT_BUILD_EXAMPLES=OFF") - continue() - endif() - qtConfAddWarning("'-nomake ${part}' is not implemented yet.") -endforeach() - -foreach(part ${INPUT_make}) - if("${part}" STREQUAL "tests") - push("-DQT_BUILD_TESTS=ON") - continue() - endif() - if("${part}" STREQUAL "examples") - push("-DQT_BUILD_EXAMPLES=ON") - continue() - endif() - if("${part}" STREQUAL "tools") - # default - continue() - endif() - qtConfAddWarning("'-make ${part}' is not implemented yet.") -endforeach() +check_qt_build_parts(nomake) +check_qt_build_parts(make) drop_input(debug) drop_input(release) @@ -706,12 +985,35 @@ if(INPUT_force_debug_info) list(TRANSFORM build_configs REPLACE "^Release$" "RelWithDebInfo") endif() +# Code coverage handling +drop_input(gcov) +if(INPUT_gcov) + if(NOT "${INPUT_coverage}" STREQUAL "") + if(NOT "${INPUT_coverage}" STREQUAL "gcov") + qtConfAddError("The -gcov argument is provided, but -coverage is set" + " to ${INPUT_coverage}") + endif() + else() + set(INPUT_coverage "gcov") + list(APPEND config_inputs coverage) + endif() +endif() +if(NOT "${INPUT_coverage}" STREQUAL "") + if(build_configs) + if(NOT "Debug" IN_LIST build_configs) + qtConfAddError("The -coverage argument requires Qt configured with 'Debug' config.") + endif() + else() + set(build_configs "Debug") + endif() +endif() + list(LENGTH build_configs nr_of_build_configs) -if(nr_of_build_configs EQUAL 1) +if(nr_of_build_configs EQUAL 1 AND NOT multi_config) push("-DCMAKE_BUILD_TYPE=${build_configs}") -elseif(nr_of_build_configs GREATER 1) +elseif(nr_of_build_configs GREATER 1 OR multi_config) set(multi_config ON) - string(REPLACE ";" "\\;" escaped_build_configs "${build_configs}") + string(REPLACE ";" "[[;]]" escaped_build_configs "${build_configs}") # We must not use the push macro here to avoid variable expansion. # That would destroy our escaping. list(APPEND cmake_args "-DCMAKE_CONFIGURATION_TYPES=${escaped_build_configs}") @@ -727,11 +1029,6 @@ if("${INPUT_ltcg}" STREQUAL "yes") endforeach() endif() -if(NOT "${INPUT_opengl}" STREQUAL "") - drop_input(opengl) - push("-DINPUT_opengl=${INPUT_opengl}") -endif() - translate_list_input(device-option QT_QMAKE_DEVICE_OPTIONS) translate_list_input(defines QT_EXTRA_DEFINES) translate_list_input(fpaths QT_EXTRA_FRAMEWORKPATHS) @@ -739,18 +1036,29 @@ translate_list_input(includes QT_EXTRA_INCLUDEPATHS) translate_list_input(lpaths QT_EXTRA_LIBDIRS) translate_list_input(rpaths QT_EXTRA_RPATHS) -foreach(feature ${commandline_known_features}) - qt_feature_normalize_name("${feature}" cmake_feature) - if(${feature} IN_LIST config_inputs) - translate_boolean_input(${feature} INPUT_${cmake_feature}) - endif() -endforeach() +if(cmake_file_api OR (developer_build AND NOT DEFINED cmake_file_api)) + foreach(file cache-v2 cmakeFiles-v1 codemodel-v2 toolchains-v1) + file(WRITE "${CMAKE_BINARY_DIR}/.cmake/api/v1/query/${file}" "") + endforeach() +endif() +# Translate unhandled input variables to either -DINPUT_foo=value or -DFEATURE_foo=ON/OFF. If the +# input's name matches a feature name and the corresponding command-line option's type is boolean +# then we assume it's controlling a feature. foreach(input ${config_inputs}) qt_feature_normalize_name("${input}" cmake_input) - push("-DINPUT_${cmake_input}=${INPUT_${input}}") + if("${commandline_input_${input}_type}" STREQUAL "boolean" + AND input IN_LIST commandline_known_features) + translate_boolean_input("${input}" "FEATURE_${cmake_input}") + else() + push("-DINPUT_${cmake_input}=${INPUT_${input}}") + endif() endforeach() +if(no_prefix_option AND DEFINED INPUT_prefix) + qtConfAddError("Can't specify both -prefix and -no-prefix options at the same time.") +endif() + if(NOT generator AND auto_detect_generator) find_program(ninja ninja) if(ninja) @@ -775,12 +1083,38 @@ if(NOT generator AND auto_detect_generator) endif() endif() endif() + +if(multi_config + AND NOT "${generator}" STREQUAL "Xcode" + AND NOT "${generator}" STREQUAL "Ninja Multi-Config" + AND NOT "${generator}" MATCHES "^Visual Studio") + message(FATAL_ERROR "Multi-config build is only supported by Xcode, Ninja Multi-Config and \ +Visual Studio generators. Current generator is \"${generator}\". +Note: Use '-cmake-generator <generator name>' option to specify the generator manually.") +endif() + if(generator) push(-G "${generator}") endif() +# Add CMake variable assignments near the end to allow users to overwrite what configure sets. +foreach(arg IN LISTS cmake_var_assignments) + push("-D${arg}") +endforeach() + push("${MODULE_ROOT}") +if(INPUT_sysroot) + qtConfAddWarning("The -sysroot option is deprecated and no longer has any effect. " + "It is recommended to use a toolchain file instead, i.e., " + "-DCMAKE_TOOLCHAIN_FILE=<filename>. " + "Alternatively, you may use -DCMAKE_SYSROOT option " + "to pass the sysroot to CMake.\n") +endif() + +# Restore the escaped semicolons in arguments that are lists +list(TRANSFORM cmake_args REPLACE "\\[\\[;\\]\\]" "\\\\;") + execute_process(COMMAND "${CMAKE_COMMAND}" ${cmake_args} COMMAND_ECHO STDOUT RESULT_VARIABLE exit_code) |