Don't rely on the module.pri for the entrypoint linking to the library

Depending on the presence and behavior of HEADER_MODULE/header_module
in CMake and qmake land, the module.pri might end up with an empty
module line, which means adding the module via QT_PRIVATE += entrypoint
will not link to the static library.

To avoid this problem we write an explicit module entry (QT.foo.bar)
into the same module.pri file as the one generated by qt_module,
where the auto-generated one has header_module enabled, and hence
no link behavior, while the manually written entry has a module
component, and will ensure linkage to the static library.

Change-Id: Ib98484f74410fab45c4d109f3610028200fba0c5
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
This commit is contained in:
Tor Arne Vestbø 2020-11-03 17:00:11 +01:00
parent c2e1a773e0
commit ff170962d4
6 changed files with 94 additions and 51 deletions

View File

@ -57,9 +57,9 @@ ucmodule = $$upper($$MODULE)
isEmpty(MODULE_INCNAME): MODULE_INCNAME = $$TARGET isEmpty(MODULE_INCNAME): MODULE_INCNAME = $$TARGET
internal_module: \ internal_module: \
MODULE_DEPENDS = $$replace(QT, -private$, _private) MODULE_DEPENDS += $$replace(QT, -private$, _private)
else: \ else: \
MODULE_DEPENDS = $$replace(QT, -private$, ) MODULE_DEPENDS += $$replace(QT, -private$, )
MODULE_DEPENDS = $$unique(MODULE_DEPENDS) MODULE_DEPENDS = $$unique(MODULE_DEPENDS)
contains(MODULE_DEPENDS, $$MODULE): \ contains(MODULE_DEPENDS, $$MODULE): \
error("$$TARGET depends on itself.") error("$$TARGET depends on itself.")

View File

@ -154,8 +154,8 @@ defineReplace(qtExportLibsForModule) {
$$qtGetExportsForModule($$MODULE_ID) \ $$qtGetExportsForModule($$MODULE_ID) \
"QT_CONFIG +=$$join(QT.$${MODULE_ID}.QT_CONFIG, " ", " ")" \ "QT_CONFIG +=$$join(QT.$${MODULE_ID}.QT_CONFIG, " ", " ")" \
"" \ "" \
"QT_MODULES += $$MODULE" \ "QT_MODULES += $$MODULE"
"$$MODULE_PRI_EXTRA_CONTENT" MODULE_PRI_CONT += $$MODULE_PRI_EXTRA_CONTENT
write_file($$MODULE_PRI, MODULE_PRI_CONT)|error() write_file($$MODULE_PRI, MODULE_PRI_CONT)|error()
!internal_module:!no_private_module { !internal_module:!no_private_module {
module_build_type += internal_module module_build_type += internal_module

View File

@ -25,16 +25,6 @@ set_target_properties(EntryPoint PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "" INTERFACE_COMPILE_DEFINITIONS ""
) )
# And since this module is the one producing the module pri,
# we need to manually tell it that what we're actually doing
# is producing a module that has a static library.
set_target_properties(EntryPoint PROPERTIES
INTERFACE_QT_MODULE_INTERNAL_CONFIG "staticlib"
)
set(module_pri_entrypoint_ldflags "")
# ---- While the static library target does the work ---- # ---- While the static library target does the work ----
qt_internal_add_cmake_library(EntryPointImplementation STATIC qt_internal_add_cmake_library(EntryPointImplementation STATIC
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES
@ -69,7 +59,7 @@ if(WIN32)
# linker line, so that the static linker will pick up the WinMain symbol # linker line, so that the static linker will pick up the WinMain symbol
# from the entry-point library. # from the entry-point library.
target_link_libraries(EntryPoint INTERFACE mingw32) target_link_libraries(EntryPoint INTERFACE mingw32)
list(APPEND module_pri_entrypoint_ldflags "-lmingw32") set_property(TARGET EntryPoint APPEND PROPERTY INTERFACE_QT_MODULE_LDFLAGS "-lmingw32")
target_compile_definitions(EntryPoint INTERFACE QT_NEEDS_QMAIN) target_compile_definitions(EntryPoint INTERFACE QT_NEEDS_QMAIN)
qt_internal_extend_target(EntryPointImplementation DEFINES QT_NEEDS_QMAIN) qt_internal_extend_target(EntryPointImplementation DEFINES QT_NEEDS_QMAIN)
@ -78,14 +68,22 @@ endif()
# ---- Finally, make sure the static library can be consumed by clients ----- # ---- Finally, make sure the static library can be consumed by clients -----
set_target_properties(EntryPoint PROPERTIES
INTERFACE_QT_MODULE_LDFLAGS "${module_pri_entrypoint_ldflags}"
)
# Must be added last, so that any library dependencies added above will
# precede the entrypoint library at link time.
target_link_libraries(EntryPoint INTERFACE EntryPointImplementation) target_link_libraries(EntryPoint INTERFACE EntryPointImplementation)
qt_internal_get_target_property(entrypoint_implementation_ldflags
EntryPointImplementation QT_MODULE_LDFLAGS)
set_target_properties(EntryPoint PROPERTIES
INTERFACE_QT_MODULE_PRI_EXTRA_CONTENT "
QT.entrypoint_implementation.name = QtEntryPointImplementation
QT.entrypoint_implementation.module = Qt6EntryPoint
QT.entrypoint_implementation.ldflags = ${entrypoint_implementation_ldflags}
QT.entrypoint_implementation.libs = $$QT_MODULE_LIB_BASE
QT.entrypoint_implementation.module_config = staticlib v2 internal_module
"
INTERFACE_QT_MODULE_DEPENDS "entrypoint_implementation"
)
set(export_name "${INSTALL_CMAKE_NAMESPACE}EntryPointTargets") set(export_name "${INSTALL_CMAKE_NAMESPACE}EntryPointTargets")
qt_install(TARGETS EntryPointImplementation EXPORT ${export_name}) qt_install(TARGETS EntryPointImplementation EXPORT ${export_name})
qt_generate_prl_file(EntryPointImplementation "${INSTALL_LIBDIR}") qt_generate_prl_file(EntryPointImplementation "${INSTALL_LIBDIR}")

View File

@ -1,34 +1,8 @@
# Additional Qt project file for QtEntryPoint lib # Additional Qt project file for QtEntryPoint lib
!win32:error("$$_FILE_ is intended only for Windows!") !win32:error("$$_FILE_ is intended only for Windows!")
TARGET = QtEntryPoint TEMPLATE = subdirs
CONFIG += ordered
CONFIG += static no_module_headers internal_module SUBDIRS += entrypoint_module.pro
QT = core SUBDIRS += entrypoint_implementation.pro
DEFINES += QT_NO_FOREACH
win32 {
SOURCES = qtentrypoint_win.cpp
CONFIG -= qt
QMAKE_USE_PRIVATE += shell32
msvc {
QMAKE_CFLAGS_DEBUG -= -Zi
QMAKE_CXXFLAGS_DEBUG -= -Zi
QMAKE_CFLAGS_DEBUG *= -Z7
QMAKE_CXXFLAGS_DEBUG *= -Z7
}
mingw {
DEFINES += QT_NEEDS_QMAIN
MODULE_DEFINES += QT_NEEDS_QMAIN
# This library needs to come before the entry-point library in the
# linker line, so that the static linker will pick up the WinMain
# symbol from the entry-point library.
MODULE_LDFLAGS += -lmingw32
}
}
load(qt_module)

View File

@ -0,0 +1,61 @@
TEMPLATE = lib
TARGET = QtEntryPoint
CONFIG += static no_module_headers internal_module
QT = core
DEFINES += QT_NO_FOREACH
win32 {
SOURCES = qtentrypoint_win.cpp
CONFIG -= qt
QMAKE_USE_PRIVATE += shell32
msvc {
QMAKE_CFLAGS_DEBUG -= -Zi
QMAKE_CXXFLAGS_DEBUG -= -Zi
QMAKE_CFLAGS_DEBUG *= -Z7
QMAKE_CXXFLAGS_DEBUG *= -Z7
}
mingw {
DEFINES += QT_NEEDS_QMAIN
MODULE_DEFINES += QT_NEEDS_QMAIN
# This library needs to come before the entry-point library in the
# linker line, so that the static linker will pick up the WinMain
# symbol from the entry-point library.
MODULE_LDFLAGS += -lmingw32
}
}
# Minimal qt_helper_lib
load(qt_build_paths)
load(qt_common)
!build_pass {
MODULE_PRI_CONTENT = \
"QT.entrypoint_implementation.name = QtEntryPointImplementation" \
"QT.entrypoint_implementation.module = Qt6EntryPoint" \
"QT.entrypoint_implementation.ldflags = $$MODULE_LDFLAGS" \
"QT.entrypoint_implementation.libs = \$\$QT_MODULE_LIB_BASE" \
"QT.entrypoint_implementation.DEFINES = $$MODULE_DEFINES" \
"QT.entrypoint_implementation.module_config = staticlib v2 internal_module"
module_path = $$MODULE_QMAKE_OUTDIR/mkspecs/modules
force_independent|split_incpath: module_path = "$${module_path}-inst"
MODULE_PRI = $$module_path/qt_lib_entrypoint_private.pri
write_file($$MODULE_PRI, MODULE_PRI_CONTENT, append)|error()
}
qtConfig(debug_and_release): CONFIG += debug_and_release
qtConfig(build_all): CONFIG += build_all
DESTDIR = $$MODULE_BASE_OUTDIR/lib
TARGET = $$qt5LibraryTarget($$TARGET)
load(qt_installs)

View File

@ -0,0 +1,10 @@
TARGET = QtEntryPoint
MODULE = entrypoint
CONFIG += header_module no_module_headers internal_module
MODULE_DEPENDS = entrypoint_implementation
QT =
load(qt_module)