diff options
author | Joerg Bornemann <joerg.bornemann@qt.io> | 2021-10-28 12:19:15 +0200 |
---|---|---|
committer | Joerg Bornemann <joerg.bornemann@qt.io> | 2021-10-28 22:15:46 +0200 |
commit | 753199437943e2a89e458136fd11a5a43443b280 (patch) | |
tree | 53ded3aee4e97f84b4d50cf59c5784015964de9b /src/entrypoint | |
parent | 825505c4398983deb279b9fc2655ab5b6d44fb9a (diff) | |
download | qtbase-753199437943e2a89e458136fd11a5a43443b280.tar.gz |
CMake: Fix undefined reference to WinMain errors with MinGW
When linking against Qt with MinGW, libmingw32.a must come before
libQt6EntryPointImplementation.a on the linker command line. Otherwise
the linker cannot find the WinMain symbol that's defined in the
EntryPointImplementation library.
Under certain circumstances, mingw32 was linked after
EntryPointImplementation. To reliably ensure the order of said
libraries, we introduce the imported library EntryPointMinGW32. This
target represents libmingw32.a and links against EntryPointImplementation.
The link dependencies look like this:
EntryPointPrivate -> EntryPointMinGW32 -> EntryPointImplementation
The imported library EntryPointMinGW32 is defined in a separate .cmake
file which is included by both src/entrypoint/CMakeLists.txt and
Qt6EntryPointConfig.cmake. This is needed, because the consumer outside
of Qt must access this imported library, and we cannot export imported
libraries.
Pick-to: 6.2
Fixes: QTBUG-93671
Change-Id: Ib3c5e80cbcc9c793d000e5ad637325bcf735a1ec
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/entrypoint')
-rw-r--r-- | src/entrypoint/CMakeLists.txt | 30 | ||||
-rw-r--r-- | src/entrypoint/EntryPointMinGW32Target.cmake.in | 7 |
2 files changed, 31 insertions, 6 deletions
diff --git a/src/entrypoint/CMakeLists.txt b/src/entrypoint/CMakeLists.txt index c173870e92..19c64cc34f 100644 --- a/src/entrypoint/CMakeLists.txt +++ b/src/entrypoint/CMakeLists.txt @@ -10,6 +10,27 @@ endif() # dependencies that need to go _before_ the static library, to work around # CMake's lack of whole archive. +# ---- Set up an intermediate imported library for libmingw32.a ---- + +set(export_name_prefix "${INSTALL_CMAKE_NAMESPACE}EntryPointPrivate") +qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${export_name_prefix}) + +set(extra_cmake_includes_arg) +if(MINGW) + # The mingw32 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. In order to + # achieve that reliably, we create an imported library EntryPointMinGW32 that represents + # libmingw32.a and add a link dependency to EntryPointImplementation. The resulting dependency + # chain looks like this: EntryPointPrivate -> EntryPointMinGW32 -> EntryPointImplementation + + set(mingw32target_config_file "${INSTALL_CMAKE_NAMESPACE}EntryPointMinGW32Target.cmake") + configure_file("EntryPointMinGW32Target.cmake.in" "${mingw32target_config_file}" @ONLY) + qt_copy_or_install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${mingw32target_config_file}" + DESTINATION "${config_install_dir}") + include("${CMAKE_CURRENT_BINARY_DIR}/${mingw32target_config_file}") + set(extra_cmake_includes_arg EXTRA_CMAKE_INCLUDES "${mingw32target_config_file}") +endif() + # ---- The header-only target produces the actual module ---- qt_internal_add_module(EntryPointPrivate HEADER_MODULE @@ -18,6 +39,7 @@ qt_internal_add_module(EntryPointPrivate NO_MODULE_HEADERS NO_PRIVATE_MODULE NO_ADDITIONAL_TARGET_INFO + ${extra_cmake_includes_arg} ) set(export_targets EntryPointPrivate) @@ -67,10 +89,8 @@ if(WIN32) endif() if(MINGW) - # The mingw32 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. - target_link_libraries(EntryPointPrivate INTERFACE mingw32) + # Link against EntryPointImplementation via EntryPointMinGW32 + target_link_libraries(EntryPointPrivate INTERFACE EntryPointMinGW32) set_property(TARGET EntryPointPrivate APPEND PROPERTY INTERFACE_QT_MODULE_LDFLAGS "-lmingw32" ) @@ -113,8 +133,6 @@ QT.entrypoint_implementation.module_config = staticlib v2 internal_module qt_generate_prl_file(EntryPointImplementation "${INSTALL_LIBDIR}") endif() -set(export_name_prefix "${INSTALL_CMAKE_NAMESPACE}EntryPointPrivate") -qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${export_name_prefix}) qt_internal_export_additional_targets_file( TARGETS ${export_targets} EXPORT_NAME_PREFIX ${export_name_prefix} diff --git a/src/entrypoint/EntryPointMinGW32Target.cmake.in b/src/entrypoint/EntryPointMinGW32Target.cmake.in new file mode 100644 index 0000000000..81ee970d6c --- /dev/null +++ b/src/entrypoint/EntryPointMinGW32Target.cmake.in @@ -0,0 +1,7 @@ +# Add EntryPointMinGW32, an imported library that ensures that -lmingw32 comes before +# EntryPointImplementation on the linker command line. +include_guard() +add_library(EntryPointMinGW32 INTERFACE IMPORTED) +set_property(TARGET EntryPointMinGW32 PROPERTY IMPORTED_LIBNAME mingw32) +target_link_libraries(EntryPointMinGW32 + INTERFACE @INSTALL_CMAKE_NAMESPACE@::EntryPointImplementation) |