From 8fa646dbe2eba9674809042ff15e98f0eb1018d5 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 29 May 2019 16:56:49 +0200 Subject: [PATCH] Add basic support for compiling applications with qmake * Generate module .pri files * Generate qconfig.pri * Propagate MODULE_CONFIG from the .pro files This enables the basic use-case of simple application builds that for example use the moc. Omitted from the patch is support for private module configurations, prl files (should we do this?) and possibly more hidden gems that need to be implemented to for example support building Qt modules with qmake. Task-number: QTBUG-75666 Change-Id: Icbf0d9ccea4cd683e4c38340b9a2320bf7951d0d Reviewed-by: Qt CMake Build Bot Reviewed-by: Tobias Hunger --- cmake/QtBaseGlobalTargets.cmake | 2 + cmake/QtBuild.cmake | 94 +++++++++++++++++++++++++++++++- src/corelib/.prev_CMakeLists.txt | 1 + src/corelib/CMakeLists.txt | 1 + src/dbus/.prev_CMakeLists.txt | 1 + src/dbus/CMakeLists.txt | 1 + src/widgets/.prev_CMakeLists.txt | 1 + src/widgets/CMakeLists.txt | 1 + util/cmake/pro2cmake.py | 4 ++ 9 files changed, 105 insertions(+), 1 deletion(-) diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 7bb55ba3d9c..82fd4ed2daf 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -70,6 +70,8 @@ qt_feature_module_begin(NO_MODULE include("${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake") qt_feature_module_end(GlobalConfig OUT_VAR_PREFIX "__GlobalConfig_") +qt_generate_global_config_pri_file() + add_library(Qt::GlobalConfig ALIAS GlobalConfig) add_library(GlobalConfigPrivate INTERFACE) diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 924a6fa78f9..80b7a32fb7c 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -281,6 +281,91 @@ function(qt_set_up_developer_build) endif() endfunction() +# Generates module .pri files for consumption by qmake +function(qt_generate_module_pri_file target target_path pri_file_name_var) + set(flags) + set(options) + set(multiopts QMAKE_MODULE_CONFIG) + cmake_parse_arguments(arg "${flags}" "${options}" "${multiopts}" ${ARGN}) + + qt_internal_module_info(module "${target}") + qt_path_join(pri_file_name "${target_path}" "qt_lib_${module_lower}.pri") + set("${pri_file_name_var}" "${pri_file_name}" PARENT_SCOPE) + + get_target_property(enabled_features "${target}" QT_ENABLED_PUBLIC_FEATURES) + get_target_property(disabled_features "${target}" QT_DISABLED_PUBLIC_FEATURES) + string (REPLACE ";" " " enabled_features "${enabled_features}") + string (REPLACE ";" " " disabled_features "${disabled_features}") + + if(arg_QMAKE_MODULE_CONFIG) + string(REPLACE ";" " " module_config "${arg_QMAKE_MODULE_CONFIG}") + set(module_config "\nQT.${module_lower}.CONFIG = ${module_config}") + else() + set(module_config "") + endif() + + file(GENERATE + OUTPUT "${pri_file_name}" + CONTENT + "QT.${module_lower}.VERSION = ${PROJECT_VERSION} +QT.${module_lower}.name = ${module} +QT.${module_lower}.module = ${module_versioned} +QT.${module_lower}.libs = $$QT_MODULE_LIB_BASE +QT.${module_lower}.includes = $$QT_MODULE_INCLUDE_BASE $$QT_MODULE_INCLUDE_BASE/${module} +QT.${module_lower}.frameworks = +QT.${module_lower}.bins = $$QT_MODULE_BIN_BASE +QT.${module_lower}.depends = +QT.${module_lower}.uses = +QT.${module_lower}.module_config = v2 +QT.${module_lower}.DEFINES = QT_${module_upper}_LIB +QT.${module_lower}.enabled_features = ${enabled_features} +QT.${module_lower}.disabled_features = ${disabled_features}${module_config} +QT_MODULES += ${module_lower} +" + ) +endfunction() + +function(qt_generate_global_config_pri_file) + qt_path_join(qconfig_pri_target_path ${PROJECT_BINARY_DIR} mkspecs) + qt_path_join(qconfig_pri_target_path "${qconfig_pri_target_path}" "qconfig.pri") + + get_target_property(enabled_features GlobalConfig INTERFACE_QT_ENABLED_PUBLIC_FEATURES) + get_target_property(disabled_features GlobalConfig INTERFACE_QT_DISABLED_PUBLIC_FEATURES) + + # configure2cmake skips the "static" feature, so emulate it here for qmake support: + if(${QT_BUILD_SHARED_LIBS}) + list(APPEND enabled_features shared) + list(APPEND disabled_features static) + else() + list(APPEND enabled_features static) + list(APPEND disabled_features shared) + endif() + + # configure2cmake skips the "rpath" feature, so emulate it here for qmake support: + if(CMAKE_SKIP_RPATH) + list(APPEND disabled_features rpath) + elseif(LINUX OR APPLE) + list(APPEND enabled_features rpath) + endif() + + string (REPLACE ";" " " enabled_features "${enabled_features}") + string (REPLACE ";" " " disabled_features "${disabled_features}") + + file(GENERATE + OUTPUT "${qconfig_pri_target_path}" + CONTENT + "QT.global.enabled_features = ${enabled_features} +QT.global.disabled_features = ${disabled_features} +QT_VERSION = ${PROJECT_VERSION} +QT_MAJOR_VERSION = ${PROJECT_VERSION_MAJOR} +QT_MINOR_VERSION = ${PROJECT_VERSION_MINOR} +QT_PATCH_VERSION = ${PROJECT_VERSION_PATCH} +CONFIG -= link_prl # we do not create prl files right now +" + ) + qt_install(FILES "${qconfig_pri_target_path}" DESTINATION mkspecs) +endfunction() + # Takes a list of path components and joins them into one path separated by forward slashes "/", # and saves the path in out_var. function(qt_path_join out_var) @@ -845,7 +930,7 @@ function(add_qt_module target) qt_parse_all_arguments(arg "add_qt_module" "NO_MODULE_HEADERS;STATIC;DISABLE_TOOLS_EXPORT" "CONFIG_MODULE_NAME" - "${__default_private_args};${__default_public_args}" ${ARGN}) + "${__default_private_args};${__default_public_args};QMAKE_MODULE_CONFIG" ${ARGN}) if(NOT DEFINED arg_CONFIG_MODULE_NAME) set(arg_CONFIG_MODULE_NAME "${module_lower}") @@ -1055,6 +1140,13 @@ set(QT_CMAKE_EXPORT_NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE})") EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target} CONFIG_INSTALL_DIR "${config_install_dir}") + qt_path_join(pri_target_path ${PROJECT_BINARY_DIR} mkspecs/modules) + qt_generate_module_pri_file("${target}" "${pri_target_path}" module_pri_file_name + QMAKE_MODULE_CONFIG + ${arg_QMAKE_MODULE_CONFIG} + ) + qt_install(FILES "${module_pri_file_name}" DESTINATION mkspecs/modules) + ### fixme: cmake is missing a built-in variable for this. We want to apply it only to modules and plugins # that belong to Qt. qt_internal_add_link_flags_no_undefined("${target}") diff --git a/src/corelib/.prev_CMakeLists.txt b/src/corelib/.prev_CMakeLists.txt index 1e459bb7341..13b2a444570 100644 --- a/src/corelib/.prev_CMakeLists.txt +++ b/src/corelib/.prev_CMakeLists.txt @@ -5,6 +5,7 @@ ##################################################################### add_qt_module(Core + QMAKE_MODULE_CONFIG moc resources SOURCES ../3rdparty/harfbuzz/src/harfbuzz.h ../3rdparty/harfbuzz/src/harfbuzz-buffer.c diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index bd1aad0406e..f4d5329ee66 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -17,6 +17,7 @@ endif() ##################################################################### add_qt_module(Core + QMAKE_MODULE_CONFIG moc resources SOURCES # special case: remove ../3rdparty/harfbuzz codecs/qtextcodec_p.h diff --git a/src/dbus/.prev_CMakeLists.txt b/src/dbus/.prev_CMakeLists.txt index 0e0ae9351d5..852ba7b03f5 100644 --- a/src/dbus/.prev_CMakeLists.txt +++ b/src/dbus/.prev_CMakeLists.txt @@ -5,6 +5,7 @@ ##################################################################### add_qt_module(DBus + QMAKE_MODULE_CONFIG dbusadaptors dbusinterfaces SOURCES dbus_minimal_p.h qdbus_symbols.cpp qdbus_symbols_p.h diff --git a/src/dbus/CMakeLists.txt b/src/dbus/CMakeLists.txt index 4768460e05e..9810167bca8 100644 --- a/src/dbus/CMakeLists.txt +++ b/src/dbus/CMakeLists.txt @@ -5,6 +5,7 @@ ##################################################################### add_qt_module(DBus + QMAKE_MODULE_CONFIG dbusadaptors dbusinterfaces SOURCES dbus_minimal_p.h qdbus_symbols.cpp qdbus_symbols_p.h diff --git a/src/widgets/.prev_CMakeLists.txt b/src/widgets/.prev_CMakeLists.txt index bd1f19fb0e2..44f4d5de104 100644 --- a/src/widgets/.prev_CMakeLists.txt +++ b/src/widgets/.prev_CMakeLists.txt @@ -5,6 +5,7 @@ ##################################################################### add_qt_module(Widgets + QMAKE_MODULE_CONFIG uic SOURCES itemviews/qfileiconprovider.cpp itemviews/qfileiconprovider.h itemviews/qfileiconprovider_p.h kernel/qaction.cpp kernel/qaction.h kernel/qaction_p.h diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index d946bc8e1d2..95ee3bed651 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -5,6 +5,7 @@ ##################################################################### add_qt_module(Widgets + QMAKE_MODULE_CONFIG uic SOURCES itemviews/qfileiconprovider.cpp itemviews/qfileiconprovider.h itemviews/qfileiconprovider_p.h kernel/qaction.cpp kernel/qaction.h kernel/qaction_p.h diff --git a/util/cmake/pro2cmake.py b/util/cmake/pro2cmake.py index 89bc8442617..e2625af2661 100755 --- a/util/cmake/pro2cmake.py +++ b/util/cmake/pro2cmake.py @@ -1575,6 +1575,10 @@ def write_module(cm_fh: typing.IO[str], scope: Scope, *, if 'no_module_headers' in scope.get('CONFIG'): extra.append('NO_MODULE_HEADERS') + module_config = scope.get("MODULE_CONFIG") + if len(module_config): + extra.append('QMAKE_MODULE_CONFIG {}'.format(" ".join(module_config))) + write_main_part(cm_fh, module_name[2:], 'Module', 'add_qt_module', scope, extra_lines=extra, indent=indent, known_libraries={}, extra_keys=[])