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 <alexandru.croitor@qt.io>
(cherry picked from commit e154da485e83d2867da391088ea4acb31eef6293)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Li Xinwei 2024-06-30 13:22:32 +08:00 committed by Qt Cherry-pick Bot
parent 7ad780e6f5
commit 7150ad74e1
3 changed files with 30 additions and 15 deletions

View File

@ -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.

View File

@ -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,12 +77,15 @@ 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)
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)
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()
list(APPEND out_list "${library_path}")

View File

@ -57,7 +57,7 @@ function(qt_generate_qmake_libraries_pri_content module_name output_root_dir out
list(APPEND lib_defines "$<TARGET_PROPERTY:${lib_target},INTERFACE_COMPILE_DEFINITIONS>")
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()