qt5base-lts/cmake/QtFinishPrlFile.cmake
Li Xinwei 2c49f85380 CMake: Fix generated prl and pri files for MSVC
In MSVC static build, if we build Qt with 3rdparty library (e.g. zstd),
cmake will add"zstd" (without "-l" prefix) to Qt6Core.prl. Then we
use this Qt to build a qmake project, compilation will fail due to
missing zstd.obj. Without "-l" prefix, qmake will treat "zstd" as an
object file instead of a library.

Library names in qt_module.pri and qt_lib_*_private.pri are also
missing "-l" prefix.

This is because on most compilers, CMAKE_LINK_LIBRARY_FLAG equals
"-l". But on MSVC, it is an empty string. So we should pass
"-DLINK_LIBRARY_FLAG=-l" for MSVC.

Also add "-L/path/to/library" if the library path is not in default
linker search directories. This will write un-relocatable paths to prl
files only when using 3rdparty libraries to build Qt statically. Usually
it's not a problem.

In addition, CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES is also empty on
MSVC. So The third argument of "$<FILTER>" is empty, it is an invalid
generator expression. This means no include dir will be written to
qt_module.pri and qt_lib_*_private.pri on MSVC. So only use "$<FILTER>"
when CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES is not empty.

Pick-to: 6.1
Change-Id: Ib66f95dc09cf920363a4b9338fb97747dd2f8ab7
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
2021-06-02 13:32:06 +08:00

101 lines
4.7 KiB
CMake

# Finish a preliminary .prl file.
#
# - Replaces occurrences of the build libdir with $$[QT_INSTALL_LIBDIR].
# - Strips version number suffixes from absolute paths, because qmake's lflag
# merging does not handle them correctly.
# - Transforms absolute library paths into link flags
# aka from "/usr/lib/x86_64-linux-gnu/libcups.so" to "-lcups"
# - Replaces Qt absolute framework paths into a combination of -F$$[QT_INSTALL_LIBS] and
# -framework QtFoo
# - 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 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
include("${CMAKE_CURRENT_LIST_DIR}/QtGenerateLibHelpers.cmake")
file(STRINGS "${IN_FILE}" lines)
set(content "")
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_LIBS_FOR_CMAKE = (.*)")
unset(adjusted_libs)
foreach(lib ${CMAKE_MATCH_1})
if("${lib}" STREQUAL "")
continue()
endif()
# Check if the absolute path represents a Qt module located either in Qt's
# $prefix/lib dir, or in the build dir of the repo.
if(IS_ABSOLUTE "${lib}")
qt_internal_path_is_relative_to_qt_lib_path(
"${lib}" "${QT_LIB_DIRS}" lib_is_a_qt_module relative_lib)
if(NOT lib_is_a_qt_module)
# It's not a Qt module, extract the library name and prepend an -l to make
# it relocatable.
qt_transform_absolute_library_paths_to_link_flags(lib_with_link_flag "${lib}")
list(APPEND adjusted_libs "${lib_with_link_flag}")
else()
# Is a Qt module.
# Transform Qt framework paths into -framework flags.
if(relative_lib MATCHES "^(Qt(.+))\\.framework/")
if(NOT qt_framework_search_path_inserted)
set(qt_framework_search_path_inserted TRUE)
list(APPEND adjusted_libs "-F$$[QT_INSTALL_LIBS]")
endif()
list(APPEND adjusted_libs "-framework" "${CMAKE_MATCH_1}")
else()
# Not a framework, transform the Qt module into relocatable relative path.
qt_strip_library_version_suffix(relative_lib "${relative_lib}")
list(APPEND adjusted_libs "$$[QT_INSTALL_LIBS]/${relative_lib}")
endif()
endif()
else()
# Not absolute path, most likely a library name or a linker flag.
# If linker flag (like -framework, -lfoo, -pthread, keep it as-is).
if(NOT lib MATCHES "^-")
string(PREPEND lib "-l")
endif()
list(APPEND adjusted_libs "${lib}")
endif()
endforeach()
if(rcc_objects)
list(APPEND adjusted_libs ${rcc_objects})
endif()
list(JOIN adjusted_libs " " adjusted_libs_for_qmake)
string(APPEND content "QMAKE_PRL_LIBS = ${adjusted_libs_for_qmake}\n")
string(APPEND content "QMAKE_PRL_LIBS_FOR_CMAKE = ${adjusted_libs}\n")
else()
string(APPEND content "${line}\n")
endif()
endforeach()
file(WRITE "${OUT_FILE}" "${content}")
# Read the prl meta file to find out where should the final prl file be placed,
# Copy it there, if the contents hasn't changed.
file(STRINGS "${IN_META_FILE}" lines)
foreach(line ${lines})
if(line MATCHES "^FINAL_PRL_FILE_PATH = (.*)")
set(final_prl_file_path "${CMAKE_MATCH_1}")
configure_file(
"${OUT_FILE}"
"${final_prl_file_path}"
COPYONLY
)
endif()
endforeach()