【问题标题】:Application linking 2 versions of same library due to dependencies由于依赖关系,应用程序链接了同一库的 2 个版本
【发布时间】:2019-06-14 08:41:22
【问题描述】:

我的应用程序在 Linux 上动态链接的库 (libpng) 出现问题。

我使用的 libpng 版本是 libpng15。由于我的应用程序还链接了链接 libpng3 的 DI-GUY,因此这两个版本发生冲突。 “冲突”是指链接器 (ldd) 选择 libpng3 而不是 libpng15。

如果我查看 ldd 输出,则会列出 libpng15 和 libpng3。顺序如下:

    libpng.so.3 => ../lib/libpng.so.3 (0x00007f4bccdff000)
    libpng15.so.15 => ../lib/libpng15.so.15 (0x00007f4bc5d1b000)

在 CMake 中,我确保我专门针对 15 进行链接:

add_library(PNG::Shared SHARED IMPORTED)
    set_target_properties(PNG::Shared PROPERTIES
    IMPORTED_LOCATION ${_IMPORT_PREFIX}/lib/libpng15.so.15.4.0
    INTERFACE_INCLUDE_DIRECTORIES ${_IMPORT_PREFIX}/include
    INTERFACE_LINK_LIBRARIES z
)

据我了解,应用程序应该采用 libpng15,但由于 libpng.so.3 在 ldd 中比 15 版本更高级,因此链接器选择 libpng.so.3。

如何强制我的应用程序使用 libpng15.so.15,而 DI-GUY 库将使用 libpng.so.3。因为我无法重新编译 DI-GUY,所以我坚持 libpng.so.3 也被链接,但它不应该与 15 版本混淆......

我不明白为什么甚至考虑 libpng.so.3,因为我明确链接到 libpng15.so.15.4.0

【问题讨论】:

  • With "clash" I mean that the linker (ldd) picks the libpng3 instead of libpng15. - 不,即使libpng.so.3libpng15.so.15 链接到同一个可执行文件,链接器也会正确分离它们。问题是这两个库版本可能会有相同的符号(函数、变量),因此在运行时可能会选择错误的符号。这就是为什么应不惜一切代价避免与同一库的两个版本链接的原因。否则你可能会突然崩溃。
  • 我的应用程序一开始就抱怨,我用 libpng15.so.15 编译但用 libpng.so.3 运行,所以它知道它应该使用 libpng15.so.15。您是否建议如果首先链接一个完全不同的lib“X”,并且具有与libpng相同的符号,那么将采用X而不是libpng?在我看来,这将是一场灾难,还是仅针对具有不同版本的相同库?如果是,链接器如何知道 2 个库是相同的,只是版本不同,而不是偶然有相同的符号?
  • “我的应用程序一开始就抱怨,我使用 libpng15.so.15 编译但使用 libpng.so.3 运行,所以它确实知道应该使用 libpng15.so.15。” - 您的应用程序似乎使用了一些请求库版本的 libpng 函数。但是链接器将 libpng3 函数解析为 libpng15(反之亦然)。 “链接器如何知道 2 个库相同只是版本不同” - 链接器看到 libpng.so.3libpng15.so.15:不同的名称 - 不同的库。它不会将它们视为相同的库,而是具有不同的版本。

标签: cmake libpng ldd


【解决方案1】:

正确的解决方案是使链接 libpng3 的库以私有模式链接:

target_link_libraries(${TARGET} PUBLIC 
    VigFramework
    PedestriansBDI_Base
    DIGUY::GraphicsApi
    DIGUY::Main
    DIGUYDevil::Main
    TBB::Main2
    Qt4::QtCore
    Qt4::QtSql
    Qt4::QtGui
    Qt4::QtXml
    Qt4::QtNetwork
    Tiff::Main
)

target_link_libraries(${TARGET} PRIVATE 
    PNG3::Shared #required for DIGUY
)

这将保证主应用程序与 libpng15 链接,并且不会被其他库的 libpng3 污染。

【讨论】:

    猜你喜欢
    • 2019-02-25
    • 1970-01-01
    • 2019-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多