diff options
Diffstat (limited to 'cmake/QtFinishPrlFile.cmake')
-rw-r--r-- | cmake/QtFinishPrlFile.cmake | 57 |
1 files changed, 54 insertions, 3 deletions
diff --git a/cmake/QtFinishPrlFile.cmake b/cmake/QtFinishPrlFile.cmake index 7de3bd48f3..1cf9377e6c 100644 --- a/cmake/QtFinishPrlFile.cmake +++ b/cmake/QtFinishPrlFile.cmake @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + # Finish a preliminary .prl file. # # - Replaces occurrences of the build libdir with $$[QT_INSTALL_LIBDIR]. @@ -10,16 +13,20 @@ # - Prepends '-l' to values that are not absolute paths, and don't start with a dash # aka, '-lfoo', '-framework', '-pthread'. # +# The path to the final .prl file is stored in the input file as assignment to FINAL_PRL_FILE_PATH. +# # This file is to be used in CMake script mode with the following variables set: -# IN_FILE: path to the preliminary .prl file -# OUT_FILE: path to the final .prl file that's going to be installed +# IN_FILE: path to the step 1 preliminary .prl file +# OUT_FILE: path to the step 2 preliminary .prl file that is going to be created # QT_LIB_DIRS: list of paths where Qt libraries are located. # This includes the install prefix and the current repo build dir. # These paths get replaced with relocatable paths or linker / framework flags. # LIBRARY_SUFFIXES: list of known library extensions, e.g. .so;.a on Linux # LIBRARY_PREFIXES: list of known library prefies, e.g. the "lib" in "libz" on on Linux # LINK_LIBRARY_FLAG: flag used to link a shared library to an executable, e.g. -l on UNIX +# IMPLICIT_LINK_DIRECTORIES: list of implicit linker search paths +cmake_policy(SET CMP0007 NEW) include("${CMAKE_CURRENT_LIST_DIR}/QtGenerateLibHelpers.cmake") file(STRINGS "${IN_FILE}" lines) @@ -28,6 +35,8 @@ set(qt_framework_search_path_inserted FALSE) foreach(line ${lines}) if(line MATCHES "^RCC_OBJECTS = (.*)") set(rcc_objects ${CMAKE_MATCH_1}) + elseif(line MATCHES "^QMAKE_PRL_TARGET_PATH_FOR_CMAKE = (.*)") + set(target_library_path "${CMAKE_MATCH_1}") elseif(line MATCHES "^QMAKE_PRL_LIBS_FOR_CMAKE = (.*)") unset(adjusted_libs) foreach(lib ${CMAKE_MATCH_1}) @@ -70,7 +79,49 @@ foreach(line ${lines}) endif() endforeach() if(rcc_objects) - list(APPEND adjusted_libs ${rcc_objects}) + set(libs_to_prepend ${rcc_objects}) + + # By default, when qmake processes prl files, it first puts the processed library + # on the link line, followed by all values specified in QMAKE_PRL_LIBS. + # Because we add the resource object files into QMAKE_PRL_LIBS, this means they will + # also appear on the link line after the library. + # This causes issues on Linux because the linker may discard unreferenced symbols from + # the library, which are referenced by the resource object files. + # We can't control the placement of the library in relation to QMAKE_PRL_LIBS, but we + # can add the library one more time in QMAKE_PRL_LIBS, after the object files. + # qmake's UnixMakefileGenerator::findLibraries then takes care of deduplication, which + # keeps the last occurrence of the library on the link line, the one after the object + # files. + qt_internal_path_is_relative_to_qt_lib_path( + "${target_library_path}" "${QT_LIB_DIRS}" lib_is_a_qt_module relative_lib) + if(NOT lib_is_a_qt_module) + qt_internal_path_is_relative_to_qt_lib_path( + "${target_library_path}" "${QT_PLUGIN_DIRS}" lib_is_a_qt_plugin relative_lib) + endif() + if(NOT lib_is_a_qt_module AND NOT lib_is_a_qt_plugin) + qt_internal_path_is_relative_to_qt_lib_path( + "${target_library_path}" "${QT_QML_DIRS}" lib_is_a_qt_qml_plugin relative_lib) + endif() + if(NOT lib_is_a_qt_module AND NOT lib_is_a_qt_plugin AND NOT lib_is_a_qt_qml_plugin) + message(AUTHOR_WARNING + "Could not determine relative path for library ${target_library_path} when " + "generating prl file contents. An absolute path will be embedded, which " + "will cause issues if the Qt installation is relocated.") + list(APPEND libs_to_prepend "${target_library_path}") + else() + set(qmake_lib_path_prefix "$$[QT_PRL_INVALID_QMAKE_VARIABLE]") + if(lib_is_a_qt_module) + set(qmake_lib_path_prefix "$$[QT_INSTALL_LIBS]") + elseif(lib_is_a_qt_plugin) + set(qmake_lib_path_prefix "$$[QT_INSTALL_PLUGINS]") + elseif(lib_is_a_qt_qml_plugin) + set(qmake_lib_path_prefix "$$[QT_INSTALL_QML]") + endif() + qt_strip_library_version_suffix(relative_lib "${relative_lib}") + list(APPEND libs_to_prepend "${qmake_lib_path_prefix}/${relative_lib}") + endif() + + list(PREPEND adjusted_libs ${libs_to_prepend}) endif() list(JOIN adjusted_libs " " adjusted_libs_for_qmake) string(APPEND content "QMAKE_PRL_LIBS = ${adjusted_libs_for_qmake}\n") |