2aef845c03
The failure mode of this behavior is worse than the surprises that the non-explicit library dependency chain has, so it should be opt-in. This reverts back to the behavior in Qt 5.11, but lets our tests opt in to the feature. Fixes: QTBUG-71724 Change-Id: Iede11f02d978b637324ddf71d29e7c99fe3ee99f Reviewed-by: Simon Hausmann <simon.hausmann@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Eike Ziller <eike.ziller@qt.io>
356 lines
14 KiB
Plaintext
356 lines
14 KiB
Plaintext
# This avoids spurious errors when a project is explicitly disabled
|
|
# due to required Qt modules being missing.
|
|
!isEmpty(QMAKE_FAILED_REQUIREMENTS): return()
|
|
|
|
CONFIG *= thread
|
|
|
|
#handle defines
|
|
win32 {
|
|
qtConfig(shared) {
|
|
# this variable is read by qmake in qmake/generators/win32/msvc_vcproj.cpp
|
|
# function VcprojGenerator::initDeploymentTool()
|
|
QMAKE_DLL_PATHS += $$[QT_INSTALL_BINS/get]
|
|
}
|
|
}
|
|
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG
|
|
qtConfig(force_asserts): DEFINES += QT_FORCE_ASSERTS
|
|
no_keywords:DEFINES += QT_NO_KEYWORDS
|
|
plugin { #Qt plugins
|
|
static:DEFINES += QT_STATICPLUGIN
|
|
DEFINES += QT_PLUGIN
|
|
}
|
|
|
|
qtestlib {
|
|
warning("CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.")
|
|
QT += testlib
|
|
}
|
|
qdbus {
|
|
warning("CONFIG+=qdbus is deprecated. Use QT+=dbus instead.")
|
|
QT += dbus
|
|
}
|
|
help {
|
|
warning("CONFIG+=help is deprecated. Use QT+=help instead.")
|
|
QT += help-private # sic!
|
|
}
|
|
designer {
|
|
warning("CONFIG+=designer is deprecated. Use QT+=designer instead.")
|
|
QT += designer
|
|
}
|
|
uitools {
|
|
warning("CONFIG+=uitools is deprecated. Use QT+=uitools instead.")
|
|
QT += uitools
|
|
}
|
|
qaxcontainer {
|
|
warning("CONFIG+=qaxcontainer is deprecated. Use QT+=axcontainer instead.")
|
|
QT += axcontainer
|
|
}
|
|
qaxserver {
|
|
warning("CONFIG+=qaxserver is deprecated. Use QT+=axserver instead.")
|
|
QT += axserver
|
|
}
|
|
|
|
!import_qpa_plugin {
|
|
warning("CONFIG-=import_qpa_plugin is deprecated. Use QTPLUGIN.platforms=- instead.")
|
|
QTPLUGIN.platforms = -
|
|
} else: qpa_minimal_plugin {
|
|
warning("CONFIG+=qpa_minimal_plugin is deprecated. Use QTPLUGIN.platforms=qminimal instead.")
|
|
QTPLUGIN.platforms = qminimal
|
|
}
|
|
|
|
!force_import_plugins:!contains(TEMPLATE, ".*app"):!if(contains(TEMPLATE, ".*lib"):dll): \
|
|
CONFIG -= import_plugins
|
|
|
|
# qmake variables cannot contain dashes, so normalize the names first
|
|
CLEAN_QT = $$replace(QT, -private$, _private)
|
|
CLEAN_QT_PRIVATE = $$replace(QT_PRIVATE, -private$, _private)
|
|
|
|
qt_module_deps = $$CLEAN_QT $$CLEAN_QT_PRIVATE
|
|
all_qt_module_deps = $$resolve_depends(qt_module_deps, "QT.", ".depends" ".run_depends")
|
|
|
|
QTPLUGIN = $$unique($$list($$lower($$QTPLUGIN)))
|
|
|
|
import_plugins:qtConfig(static) {
|
|
manualplugs = $$QTPLUGIN # User may specify plugins. Mostly legacy.
|
|
autoplugs = # Auto-added plugins.
|
|
# First round: explicitly specified modules.
|
|
plugin_deps = $$all_qt_module_deps
|
|
for(ever) {
|
|
# Automatically link the default plugins for the linked Qt modules.
|
|
for (qtmod, plugin_deps) {
|
|
for (ptype, QT.$${qtmod}.plugin_types) {
|
|
nptype = $$replace(ptype, [-/], _)
|
|
isEmpty(QTPLUGIN.$$nptype) {
|
|
for (plug, QT_PLUGINS) {
|
|
equals(QT_PLUGIN.$${plug}.TYPE, $$ptype) {
|
|
for (dep, QT_PLUGIN.$${plug}.EXTENDS) {
|
|
!contains(all_qt_module_deps, $$dep) {
|
|
plug =
|
|
break()
|
|
}
|
|
}
|
|
autoplugs += $$plug
|
|
}
|
|
}
|
|
} else {
|
|
plug = $$eval(QTPLUGIN.$$nptype)
|
|
!equals(plug, -): \
|
|
autoplugs += $$plug
|
|
}
|
|
}
|
|
}
|
|
QTPLUGIN = $$manualplugs $$autoplugs
|
|
QTPLUGIN = $$unique(QTPLUGIN)
|
|
|
|
# Obtain the plugins' Qt dependencies ...
|
|
plugin_deps =
|
|
for (plug, QTPLUGIN): \
|
|
plugin_deps += $$eval(QT_PLUGIN.$${plug}.DEPENDS)
|
|
plugin_deps = $$resolve_depends(plugin_deps, "QT.", ".depends" ".run_depends")
|
|
plugin_deps -= $$all_qt_module_deps
|
|
isEmpty(plugin_deps): \
|
|
break()
|
|
# ... and start over if any new Qt modules appeared,
|
|
# as these may want to load plugins in turn.
|
|
all_qt_module_deps += $$plugin_deps
|
|
}
|
|
extraplugs = $$manualplugs
|
|
manualplugs -= $$autoplugs
|
|
extraplugs -= $$manualplugs
|
|
!isEmpty(extraplugs): \
|
|
warning("Redundant entries in QTPLUGIN: $$extraplugs")
|
|
|
|
!isEmpty(QTPLUGIN) {
|
|
IMPORT_FILE_CONT = \
|
|
"// This file is autogenerated by qmake. It imports static plugin classes for" \
|
|
"// static plugins specified using QTPLUGIN and QT_PLUGIN_CLASS.<plugin> variables." \
|
|
"$${LITERAL_HASH}include <QtPlugin>"
|
|
for (plug, QTPLUGIN) {
|
|
plug_class = $$eval(QT_PLUGIN.$${plug}.CLASS_NAME)
|
|
!isEmpty(plug_class): \
|
|
IMPORT_FILE_CONT += "Q_IMPORT_PLUGIN($$plug_class)"
|
|
else: \
|
|
warning("Plugin class name could not be determined for plugin '$$plug'.")
|
|
}
|
|
IMPORT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_plugin_import.cpp
|
|
write_file($$IMPORT_CPP, IMPORT_FILE_CONT)|error()
|
|
GENERATED_SOURCES += $$IMPORT_CPP
|
|
QMAKE_DISTCLEAN += $$IMPORT_CPP
|
|
}
|
|
}
|
|
|
|
# Only link against plugins in static builds
|
|
!isEmpty(QTPLUGIN):qtConfig(static) {
|
|
for (plug, QTPLUGIN) {
|
|
# Check if the plugin is known to Qt. We can use this to determine
|
|
# the plugin path. Unknown plugins must rely on the default link path.
|
|
plug_type = $$eval(QT_PLUGIN.$${plug}.TYPE)
|
|
!isEmpty(plug_type) {
|
|
plug_path = $$eval(QT_PLUGIN.$${plug}.PATH)
|
|
isEmpty(plug_path): \
|
|
plug_path = $$[QT_INSTALL_PLUGINS/get]
|
|
LIBS += -L$$plug_path/$$plug_type
|
|
}
|
|
LIBS += -l$${plug}$$qtPlatformTargetSuffix()
|
|
}
|
|
}
|
|
|
|
# target variable, flag source variable
|
|
defineTest(qtProcessModuleFlags) {
|
|
for(flag, $$2) {
|
|
contains(flag, ^-.*): \
|
|
$$1 -= $$replace(flag, ^-, )
|
|
else: \
|
|
$$1 += $$flag
|
|
}
|
|
export($$1)
|
|
}
|
|
|
|
unset(using_privates)
|
|
var_sfx =
|
|
for(ever) {
|
|
# Topological resolution of modules based on their QT.<module>.depends variable
|
|
FULL_QT$$var_sfx = $$resolve_depends(CLEAN_QT$$var_sfx, "QT.")
|
|
# Finally actually add the modules
|
|
unset(BAD_QT)
|
|
for(QTLIB, FULL_QT$$var_sfx) {
|
|
MODULE_NAME = $$eval(QT.$${QTLIB}.name)
|
|
MODULE_MODULE = $$eval(QT.$${QTLIB}.module)
|
|
MODULE_INCLUDES = $$eval(QT.$${QTLIB}.includes)
|
|
MODULE_LIBS = $$eval(QT.$${QTLIB}.libs)
|
|
MODULE_FRAMEWORKS = $$eval(QT.$${QTLIB}.frameworks)
|
|
MODULE_USES = $$eval(QT.$${QTLIB}.uses)
|
|
MODULE_CONFIG = $$eval(QT.$${QTLIB}.module_config)
|
|
|
|
isEmpty(MODULE_NAME) {
|
|
BAD_QT += $$QTLIB
|
|
next()
|
|
}
|
|
|
|
contains(MODULE_CONFIG, internal_module): \
|
|
using_privates = true
|
|
contains(MODULE_CONFIG, ltcg): \
|
|
CONFIG += link_ltcg
|
|
|
|
qtProcessModuleFlags(CONFIG, QT.$${QTLIB}.CONFIG)
|
|
qtProcessModuleFlags(DEFINES, QT.$${QTLIB}.DEFINES)
|
|
|
|
MODULE_INCLUDES -= $$QMAKE_DEFAULT_INCDIRS
|
|
MODULE_LIBS_ADD = $$MODULE_LIBS
|
|
MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS
|
|
|
|
!contains(MODULE_CONFIG, v2) {
|
|
# Backwards compatibility with pre-5.6 module .pri files
|
|
|
|
contains(MODULE_CONFIG, lib_bundle) {
|
|
MODULE_FRAMEWORKS = $$MODULE_LIBS
|
|
inc = $$MODULE_LIBS/$${MODULE_NAME}.framework/Headers
|
|
MODULE_INCLUDES = $$inc
|
|
contains(MODULE_CONFIG, internal_module): \
|
|
MODULE_INCLUDES += \
|
|
$$inc/$$eval(QT.$${QTLIB}.VERSION) \
|
|
$$inc/$$eval(QT.$${QTLIB}.VERSION)/$$MODULE_NAME
|
|
} else {
|
|
# Re-insert the major version in the library name (cf qt5LibraryTarget above)
|
|
MODULE_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION,
|
|
}
|
|
|
|
# Only link to this module if a libs directory is set, else this is just a module
|
|
# to give access to sources or include files, and not for linking.
|
|
!isEmpty(MODULE_LIBS):!contains(MODULE_CONFIG, no_link): \
|
|
MODULE_MODULE = $${MODULE_NAME}$${QT_LIBINFIX}
|
|
}
|
|
|
|
# Frameworks shouldn't need include paths, but much code does not use
|
|
# module-qualified #includes, so by default we add paths which point
|
|
# directly into the frameworks. Private modules have somewhat convoluted
|
|
# header paths, so adding them is necessary in every case.
|
|
!if(contains(MODULE_CONFIG, lib_bundle):qt_no_framework_direct_includes) \
|
|
|contains(MODULE_CONFIG, internal_module): \
|
|
INCLUDEPATH *= $$MODULE_INCLUDES
|
|
QMAKE_FRAMEWORKPATH *= $$MODULE_FRAMEWORKS
|
|
!isEmpty(MODULE_MODULE) {
|
|
contains(MODULE_CONFIG, lib_bundle) {
|
|
framework = $$MODULE_MODULE
|
|
qtConfig(debug_and_release):qt_link_suffixed_framework:!macx-xcode {
|
|
platform_target_suffix = $$qtPlatformTargetSuffix()
|
|
!isEmpty(platform_target_suffix): \
|
|
# The -framework linker argument supports a name[,suffix] version,
|
|
# where if the suffix is specified the framework is first searched
|
|
# for the library with the suffix and then without.
|
|
framework = $$framework,$$platform_target_suffix
|
|
}
|
|
LIBS$$var_sfx += -framework $$framework
|
|
} else {
|
|
!isEmpty(MODULE_LIBS_ADD): \
|
|
LIBS$$var_sfx += -L$$MODULE_LIBS_ADD
|
|
|
|
lib = $$MODULE_MODULE$$qtPlatformTargetSuffix()
|
|
LIBS$$var_sfx += -l$$lib
|
|
|
|
contains(MODULE_CONFIG, staticlib): \
|
|
PRE_TARGETDEPS *= $$MODULE_LIBS/$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB}
|
|
|
|
!isEmpty(QMAKE_LSB) {
|
|
!isEmpty(MODULE_LIBS_ADD): \
|
|
QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD
|
|
QMAKE_LFLAGS *= --lsb-shared-libs=$$lib
|
|
QMAKE_LIBDIR *= /opt/lsb/lib
|
|
}
|
|
}
|
|
}
|
|
QMAKE_USE$$var_sfx += $$MODULE_USES
|
|
# Add capabilities as defined by modules used in the project
|
|
winrt {
|
|
MODULE_WINRT_CAPABILITIES = $$eval(QT.$${QTLIB}.winrt_capabilities)
|
|
!isEmpty(MODULE_WINRT_CAPABILITIES): \
|
|
WINRT_MANIFEST.capabilities_default += $$MODULE_WINRT_CAPABILITIES
|
|
MODULE_WINRT_CAPABILITIES_DEVICE = $$eval(QT.$${QTLIB}.winrt_capabilities_device)
|
|
!isEmpty(MODULE_WINRT_CAPABILITIES_DEVICE): \
|
|
WINRT_MANIFEST.capabilities_device_default += $$MODULE_WINRT_CAPABILITIES_DEVICE
|
|
}
|
|
}
|
|
!isEmpty(BAD_QT):error("Unknown module(s) in QT$$var_sfx: $$replace(BAD_QT, _private$, -private)")
|
|
|
|
!isEmpty(var_sfx): break()
|
|
var_sfx = _PRIVATE
|
|
}
|
|
!isEmpty(using_privates):!no_private_qt_headers_warning:!build_pass {
|
|
message("This project is using private headers and will therefore be tied to this specific Qt module build version.")
|
|
message("Running this project against other versions of the Qt modules may crash at any arbitrary point.")
|
|
message("This is not a bug, but a result of using Qt internals. You have been warned!")
|
|
}
|
|
|
|
!no_qt_rpath:!static:qtConfig(rpath):!qtConfig(static):\
|
|
contains(all_qt_module_deps, core) {
|
|
relative_qt_rpath:!isEmpty(QMAKE_REL_RPATH_BASE):contains(INSTALLS, target):\
|
|
isEmpty(target.files):isEmpty(target.commands):isEmpty(target.extra) {
|
|
# NOT the /dev property, as INSTALLS use host paths
|
|
QMAKE_RPATHDIR += $$relative_path($$[QT_INSTALL_LIBS], $$qtRelativeRPathBase())
|
|
} else {
|
|
QMAKE_RPATHDIR += $$[QT_INSTALL_LIBS/dev]
|
|
}
|
|
}
|
|
|
|
!isEmpty(QMAKE_LFLAGS_RPATHLINK):!qtConfig(static) {
|
|
# -rpath-link is used by the linker to find dependencies of dynamic
|
|
# libraries which were NOT specified on the command line.
|
|
# This means that paths of direct dependencies (QT & QT_PRIVATE)
|
|
# don't need to be listed, unlike their private dependencies' paths.
|
|
privdep = $$all_qt_module_deps
|
|
privdep -= $$resolve_depends(qt_module_deps, "QT.")
|
|
rpaths =
|
|
for(dep, privdep): \
|
|
rpaths += $$eval(QT.$${dep}.libs)
|
|
QMAKE_RPATHLINKDIR *= $$unique(rpaths)
|
|
}
|
|
|
|
# static builds: link qml import plugins into the target.
|
|
contains(all_qt_module_deps, qml): \
|
|
qtConfig(static):import_plugins:!host_build:!no_import_scan {
|
|
exists($$[QT_INSTALL_QML/get]): \
|
|
QMLPATHS *= $$[QT_INSTALL_QML/get]
|
|
|
|
# run qmlimportscanner
|
|
qtPrepareTool(QMLIMPORTSCANNER, qmlimportscanner, , system)
|
|
for (QMLPATH, QMLPATHS): \
|
|
IMPORTPATHS += -importPath $$system_quote($$QMLPATH)
|
|
|
|
#message(run $$QMLIMPORTSCANNER $$_PRO_FILE_PWD_ $$IMPORTPATHS)
|
|
JSON = $$system($$QMLIMPORTSCANNER $$system_quote($$_PRO_FILE_PWD_) $$IMPORTPATHS)
|
|
|
|
parseJson(JSON, IMPORTS)| error("Failed to parse qmlimportscanner output.")
|
|
|
|
!isEmpty(IMPORTS._KEYS_) {
|
|
# add import plugins to LIBS line
|
|
for (key, IMPORTS._KEYS_) {
|
|
PATH = $$eval(IMPORTS.$${key}.path)
|
|
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
|
|
!isEmpty(PATH):!isEmpty(PLUGIN): LIBS *= -L$$PATH -l$${PLUGIN}$$qtPlatformTargetSuffix()
|
|
}
|
|
|
|
# create qml_plugin_import.cpp
|
|
IMPORT_FILE_CONT = \
|
|
"// This file is autogenerated by qmake. It imports static plugin classes for" \
|
|
"// static plugins used by QML imports." \
|
|
"$${LITERAL_HASH}include <QtPlugin>"
|
|
for (key, IMPORTS._KEYS_) {
|
|
PLUGIN = $$eval(IMPORTS.$${key}.plugin)
|
|
CLASSNAME = $$eval(IMPORTS.$${key}.classname)
|
|
!isEmpty(PLUGIN) {
|
|
!isEmpty(CLASSNAME) {
|
|
!contains(ADDED_IMPORTS, $$PLUGIN) {
|
|
ADDED_IMPORTS += $$PLUGIN
|
|
IMPORT_FILE_CONT += "Q_IMPORT_PLUGIN($$CLASSNAME)"
|
|
}
|
|
} else {
|
|
error("Plugin $$PLUGIN is missing a classname entry, please add one to the qmldir file.")
|
|
}
|
|
}
|
|
}
|
|
QML_IMPORT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_qml_plugin_import.cpp
|
|
write_file($$QML_IMPORT_CPP, IMPORT_FILE_CONT)|error()
|
|
GENERATED_SOURCES += $$QML_IMPORT_CPP
|
|
QMAKE_DISTCLEAN += $$QML_IMPORT_CPP
|
|
}
|
|
}
|