From 622894f96e93d62147a28a6f37b7ee6a90d74042 Mon Sep 17 00:00:00 2001 From: Alexandru Croitor Date: Thu, 26 Mar 2020 17:42:48 +0100 Subject: [PATCH] CMake: Allow excluding tools and apps from the default 'all' target Qt uses the qtNomakeTools() function to mark a directory which will not be built as part of the default target. This is especially important when cross-compiling (to iOS for example) because the build process might fail. The condition for not building these "GUI tool sub-directory projects" is the absence of the "tools" value in qmake's QT_BUILD_PARTS variable. Introduce a QT_NO_MAKE_TOOLS CMake variable. If the value is true, it's equivalent to "tools" not being present in QT_BUILD_PARTS. Introduce qt_exclude_tool_directories_from_default_target(). It's the qmake counter part to qtNomakeTools(). Teach pro2cmake to generate it where appropriate. Change-Id: If2e5958d91847ab139af0e452608510286e73fa0 Reviewed-by: Leander Beernaert Reviewed-by: Alexandru Croitor --- cmake/QtBuild.cmake | 23 +++++++++++++++++++++++ cmake/QtSetup.cmake | 6 ++++++ util/cmake/pro2cmake.py | 17 +++++++++++++++++ util/cmake/qmake_parser.py | 9 +++++++++ 4 files changed, 55 insertions(+) diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 6c5abb6bc4..26bee09564 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -4124,6 +4124,29 @@ function(qt_enable_msvc_cplusplus_define target visibility) endif() endfunction() +# Equivalent of qmake's qtNomakeTools(directory1 directory2). +# If QT_NO_MAKE_TOOLS is true, then the given directories will be excluded from the +# default 'all' target. +function(qt_exclude_tool_directories_from_default_target) + if(QT_NO_MAKE_TOOLS) + set(absolute_path_directories "") + foreach(directory ${ARGV}) + list(APPEND absolute_path_directories "${CMAKE_CURRENT_SOURCE_DIR}/${directory}") + endforeach() + + # Properties can only be set on processed directories (some might not be processed due to + # disabled features). So we need to exclude only processed directories. + get_directory_property(subdirectories SUBDIRECTORIES) + + # Poor man's set intersection. + foreach(directory ${absolute_path_directories}) + if(directory IN_LIST subdirectories) + set_property(DIRECTORY "${directory}" PROPERTY EXCLUDE_FROM_ALL TRUE) + endif() + endforeach() + endif() +endfunction() + # Compatibility macros that should be removed once all their usages are removed. function(extend_target) qt_extend_target(${ARGV}) diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index 3b43f44bdd..9e50787e72 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -122,6 +122,12 @@ if(QT_BUILD_STANDALONE_TESTS) endif() option(QT_NO_MAKE_TESTS "Should tests be built as part of the default 'all' target." OFF) +# When cross-building, we don't build tools by default. Sometimes this also covers Qt apps as well. +# Like in qttools/assistant/assistant.pro, load(qt_app), which is guarded by a qtNomakeTools() call. + +option(QT_NO_MAKE_TOOLS "Should tools be built as part of the default 'all' target." + "${CMAKE_CROSSCOMPILING}") + include(CTest) enable_testing() diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py index d4bcf81063..e496a2448d 100755 --- a/util/cmake/pro2cmake.py +++ b/util/cmake/pro2cmake.py @@ -1064,6 +1064,13 @@ class Scope(object): if project_required_condition: scope._append_operation("_REQUIREMENTS", AddOperation(project_required_condition)) + qt_no_make_tools = statement.get("qt_no_make_tools_arguments") + if qt_no_make_tools: + qt_no_make_tools = qt_no_make_tools.strip("()").strip() + qt_no_make_tools = qt_no_make_tools.split() + for entry in qt_no_make_tools: + scope._append_operation("_QT_NO_MAKE_TOOLS", AddOperation(entry)) + scope.settle_condition() if scope.scope_debug: @@ -1783,6 +1790,16 @@ def handle_subdir( ) group_and_print_sub_dirs(scope, indent=indent) + qt_no_make_tools = scope.get("_QT_NO_MAKE_TOOLS") + if qt_no_make_tools: + ind = spaces(indent + 1) + directories_string = "" + for directory in qt_no_make_tools: + directories_string += f"{ind}{directory}\n" + cm_fh.write( + f"\nqt_exclude_tool_directories_from_default_target(\n{directories_string})\n\n" + ) + def sort_sources(sources: List[str]) -> List[str]: to_sort = {} # type: Dict[str, List[str]] diff --git a/util/cmake/qmake_parser.py b/util/cmake/qmake_parser.py index 5cb629a495..2fabfe3f01 100644 --- a/util/cmake/qmake_parser.py +++ b/util/cmake/qmake_parser.py @@ -243,6 +243,14 @@ class QmakeParser: "Requires", pp.Keyword("requires") + RequiresCondition("project_required_condition") ) + FunctionArgumentsAsString = add_element( + "FunctionArgumentsAsString", pp.originalTextFor(pp.nestedExpr()) + ) + QtNoMakeTools = add_element( + "QtNoMakeTools", + pp.Keyword("qtNomakeTools") + FunctionArgumentsAsString("qt_no_make_tools_arguments"), + ) + # ignore the whole thing... DefineTestDefinition = add_element( "DefineTestDefinition", @@ -281,6 +289,7 @@ class QmakeParser: | Include | Option | Requires + | QtNoMakeTools | ForLoop | ForLoopSingleLine | DefineTestDefinition