From 7150ad74e16aa2a0cfdcc36a8c4604700619aa05 Mon Sep 17 00:00:00 2001 From: Li Xinwei <1326710505@qq.com> Date: Sun, 30 Jun 2024 13:22:32 +0800 Subject: [PATCH] CMake: fix FFmpeg's linker flags in generated pri and prl files FFmpeg records its library dir in INTERFACE_LINK_DIRECTORIES, its INTERFACE_LINK_LIBRARIES are library names without directories. Currently FFmpeg's linker flags in pri and prl files is broken, such as "-llibavcodec.a" in QMAKE_PRL_LIBS (should be "-lavcodec"), and "libavformat.a ws2_32" in QMAKE_LIBS_FFMPEG (should be "-lavformat -lws2_32"). Fix this by enabling qt_get_library_name_without_prefix_and_suffix() and qt_get_library_with_link_flag() to handle args like "libavformat.a" and "ws2_32", to produce correct -l flags. Also avoid adding duplicate "-L" flags in pri and prl files, since all FFmpeg libraries are installed in the same location. (Amends 2c49f85380d7ad79d9473e0f42e7afaa36d31af9 and 2915921ad2a79a4ce1651dc7297f6571788d1413) On a Mingw static build with static FFmpeg, and FFmpeg libraries isn't installed in compiler's implicit link directories. Before this change: // mkspecs/modules/qt_lib_multimedia_private.pri QMAKE_LIBS_FFMPEG = libswscale.a libswscale.a libswresample.a libswresample.a libavutil.a bcrypt libavutil.a libavformat.a ws2_32 secur32 libavformat.a libavcodec.a ole32 strmiids ole32 mfuuid libavcodec.a // plugins/multimedia/ffmpegmediaplugin.prl QMAKE_PRL_LIBS = ... -llibavformat.a -lmfuuid -lstrmiids -lole32 -llibavcodec.a -llibswresample.a -llibswscale.a -lbcrypt -llibavutil.a After this change: // mkspecs/modules/qt_lib_multimedia_private.pri QMAKE_LIBS_FFMPEG = -lswscale -lswscale -lswresample -lswresample -lavutil -lbcrypt -lavutil -lavformat -lws2_32 -lsecur32 -lavformat -lavcodec -lole32 -lstrmiids -lole32 -lmfuuid -lavcodec // plugins/multimedia/ffmpegmediaplugin.prl QMAKE_PRL_LIBS = ... -lavformat -lmfuuid -lstrmiids -lole32 -lavcodec -lswresample -lswscale -lbcrypt -lavutil Fixes: QTBUG-126773 Pick-to: 6.7 Change-Id: I71a06c960a4f9b6010fc2847cc08833d58b74e1c Reviewed-by: Alexandru Croitor (cherry picked from commit e154da485e83d2867da391088ea4acb31eef6293) Reviewed-by: Qt Cherry-pick Bot --- cmake/QtFinishPrlFile.cmake | 11 ++++++++--- cmake/QtGenerateLibHelpers.cmake | 32 +++++++++++++++++++++----------- cmake/QtPriHelpers.cmake | 2 +- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/cmake/QtFinishPrlFile.cmake b/cmake/QtFinishPrlFile.cmake index 1cf9377e6ce..0cef22617cb 100644 --- a/cmake/QtFinishPrlFile.cmake +++ b/cmake/QtFinishPrlFile.cmake @@ -27,6 +27,7 @@ # IMPLICIT_LINK_DIRECTORIES: list of implicit linker search paths cmake_policy(SET CMP0007 NEW) +cmake_policy(SET CMP0057 NEW) include("${CMAKE_CURRENT_LIST_DIR}/QtGenerateLibHelpers.cmake") file(STRINGS "${IN_FILE}" lines) @@ -50,10 +51,14 @@ foreach(line ${lines}) 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. + # It's not a Qt module, extract linker flags from the library path. qt_transform_absolute_library_paths_to_link_flags(lib_with_link_flag "${lib}") - list(APPEND adjusted_libs "${lib_with_link_flag}") + foreach(flag ${lib_with_link_flag}) + # Linker flags started with "-L" shouldn't be added duplicately. + if(NOT flag MATCHES "^-L" OR NOT flag IN_LIST adjusted_libs) + list(APPEND adjusted_libs "${flag}") + endif() + endforeach() else() # Is a Qt module. # Transform Qt framework paths into -framework flags. diff --git a/cmake/QtGenerateLibHelpers.cmake b/cmake/QtGenerateLibHelpers.cmake index 3ffe354fd8d..96675267d23 100644 --- a/cmake/QtGenerateLibHelpers.cmake +++ b/cmake/QtGenerateLibHelpers.cmake @@ -1,14 +1,19 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -# Given "/usr/lib/x86_64-linux-gnu/libcups.so" -# Returns "cups" or an empty string if the file is not an absolute library path. -# Aka it strips the "lib" prefix, the .so extension and the base path. +# Given "/usr/lib/x86_64-linux-gnu/libcups.so", returns "cups". +# Given "libavcodec.a", returns "avcodec". +# Given "ws2_32", returns "ws2_32". +# Returns an empty string if not given a linkable library (most likely a linker flag). function(qt_get_library_name_without_prefix_and_suffix out_var file_path) set(out_value "") - if(IS_ABSOLUTE "${file_path}") + if(NOT file_path MATCHES "^-") # not a linker flag get_filename_component(basename "${file_path}" NAME_WE) get_filename_component(ext "${file_path}" EXT) + if(NOT ext) # seems like a library name without prefix and suffix + set(${out_var} "${file_path}" PARENT_SCOPE) + return() + endif() string(TOLOWER "${ext}" ext_lower) foreach(libsuffix ${LIBRARY_SUFFIXES}) # Handle weird prefix extensions like in the case of @@ -45,8 +50,10 @@ function(qt_get_library_name_without_prefix_and_suffix out_var file_path) set(${out_var} "${out_value}" PARENT_SCOPE) endfunction() -# Given "/usr/lib/x86_64-linux-gnu/libcups.so" -# Returns "-lcups" or an empty string if the file is not an absolute library path. +# Given "/usr/lib/x86_64-linux-gnu/libcups.so", returns "-lcups". +# Given "libavcodec.a", returns "-lavcodec". +# Given "ws2_32", returns "-lws2_32". +# Returns an empty string if not given a linkable library (most likely a linker flag). function(qt_get_library_with_link_flag out_var file_path) qt_get_library_name_without_prefix_and_suffix(lib_name "${file_path}") @@ -70,11 +77,14 @@ function(qt_transform_absolute_library_paths_to_link_flags out_var library_path_ if(lib_name_with_link_flag) string(TOLOWER "${IMPLICIT_LINK_DIRECTORIES}" IMPLICIT_LINK_DIRECTORIES_LOWER) get_filename_component(dir "${library_path}" DIRECTORY) - string(TOLOWER "${dir}" dir_lower) - # If library_path isn't in default link directories, we should add it to link flags. - list(FIND IMPLICIT_LINK_DIRECTORIES_LOWER "${dir_lower}" index) - if(${index} EQUAL -1) - list(APPEND out_list "-L\"${dir}\"") + if(dir) + string(TOLOWER "${dir}" dir_lower) + # If library_path isn't in default link directories, we should add it to link flags. + # But we shouldn't add it duplicately. + list(FIND IMPLICIT_LINK_DIRECTORIES_LOWER "${dir_lower}" index) + if(index EQUAL -1 AND NOT "-L\"${dir}\"" IN_LIST out_list) + list(APPEND out_list "-L\"${dir}\"") + endif() endif() list(APPEND out_list "${lib_name_with_link_flag}") else() diff --git a/cmake/QtPriHelpers.cmake b/cmake/QtPriHelpers.cmake index f29b55b3491..5deeba343de 100644 --- a/cmake/QtPriHelpers.cmake +++ b/cmake/QtPriHelpers.cmake @@ -57,7 +57,7 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out list(APPEND lib_defines "$") else() if(lib_target MATCHES "/([^/]+).framework$") - list(APPEND lib_libs "-framework" "${CMAKE_MATCH_1}") + list(APPEND lib_libs "-framework ${CMAKE_MATCH_1}") else() list(APPEND lib_libs "${lib_target}") endif()