При cmake --install динамическая библиотека теряет символьную ссылку на другую

Имеется проект, внутри которого собираются 2 библиотеки TinyEXIF и tinyxml2, причем TinyEXIF требует tinyxml2. CMakeLists.txt:

option(BUILD_TINYEXIF "Build 3rdparty library TinyEXIF with tinyxml2" OFF)

if(BUILD_TINYEXIF)
    file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/tinyxml2)
    execute_process(
        COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/tinyxml2
                                 -DCMAKE_INSTALL_PREFIX=tinyxml2_install
                                 -DBUILD_SHARED_LIBS=ON
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tinyxml2
    )

    execute_process(
        COMMAND ${CMAKE_COMMAND} --build .
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tinyxml2
    )

    execute_process(
        COMMAND ${CMAKE_COMMAND} --install .
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/tinyxml2
    )

    file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/TinyEXIF)
    execute_process(
        COMMAND ${CMAKE_COMMAND} ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/TinyEXIF
                                -DCMAKE_INSTALL_PREFIX=TinyEXIF_install
                                -DBUILD_SHARED_LIBS=ON -DBUILD_STATIC_LIBS=OFF
                                -Dtinyxml2_DIR=${CMAKE_BINARY_DIR}/tinyxml2/tinyxml2_install/lib/cmake/tinyxml2
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/TinyEXIF
    )
    
    execute_process(
        COMMAND ${CMAKE_COMMAND} --build .
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/TinyEXIF
    )
    
    execute_process(
        COMMAND ${CMAKE_COMMAND} --install .
        WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/TinyEXIF
    )
    set(tinyxml2_DIR "${CMAKE_BINARY_DIR}/tinyxml2/tinyxml2_install/lib/cmake/tinyxml2")
    set(TinyEXIF_DIR "${CMAKE_BINARY_DIR}/TinyEXIF/TinyEXIF_install/lib/cmake/TinyEXIF")

    #list(APPEND CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/TinyEXIF/TinyEXIF_install/lib")
    #list(APPEND CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/tinyxml2/tinyxml2_install/lib")

endif()

find_package(tinyxml2 CONFIG REQUIRED)

find_package(TinyEXIF CONFIG REQUIRED)

file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*")

file(GLOB_RECURSE HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*")

add_executable(Geotags ${SOURCES} ${HEADERS})

include_directories("${CMAKE_BINARY_DIR}/TinyEXIF/TinyEXIF_install/include")

include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
target_link_libraries(Geotags
    TinyEXIF
)

После конфигурации появляются необходимые библиотеки в папке build, а также папки установки этой библиотеки, структура следующая:

build ->
    TinyEXIF ->
       libTinyEXIF.so
       libTinyEXIF.so.1
       libTinyEXIF.so.1.0.3
       TinyEXIF_install ->
           lib ->
               libTinyEXIF.so
               libTinyEXIF.so.1
               libTinyEXIF.so.1.0.3
           ....
     tinyxml2 ->
       libtinyxml2.so
       libtinyxml2.so.10
       libtinyxml2.so.10.0.0
       tinyxml2_install ->
           lib ->
               libtinyxml2.so
               libtinyxml2.so.10
               libtinyxml2.so.10.0.0

При запуске выскакивает это:

./Geotags: error while loading shared libraries: libtinyxml2.so.10: cannot open shared object file: No such file or directory

Вывод команды ldd для файла по пути build/TinyEXIF/TinyEXIF_install/libTinyEXIF.so:

        linux-vdso.so.1 (0x00007ffd8979b000)
        libtinyxml2.so.10 => not found
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa640735000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa64064c000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa64061e000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa64040c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa6409d5000)

Вывод команды ldd для файла по пути build/TinyEXIF/libTinyEXIF.so:

        linux-vdso.so.1 (0x00007ffd6d9db000)
        libtinyxml2.so.10 => build/tinyxml2/tinyxml2_install/lib/libtinyxml2.so.10 (0x00007f4ad3c46000)
        libstdc++.so.6 => /lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f4ad39bd000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4ad38d4000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f4ad38a6000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4ad3694000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f4ad3c7e000)

То есть, после install библиотека теряет связь со своей зависимостью. Однако если насильно подсунуть либу по пути build/TinyEXIF/libTinyEXIF.so, то всё работает. Также если собирать через clang, то вывод ldd идентичный, но программа запускается и работает. А вот в случае gcc происходит такая ошибка. С чем это может быть связано? Читал документацию про RPATH, но потыкав соответствующие переменные, мне это не помогло.


Ответы (1 шт):

Автор решения: Intelligent Shade of Blue

Это работает с gcc и строится в один проход вместо execute_process() хак. Можно использовать система-обеспеченный пакет или свой местный (bundled) пакет.

Вы использователь FetchContent_Declare() с опцией OVERRIDE_FIND_PACKAGE которая добавлена в CMake 3.24. Эта опция переезжает последующий вызовы к find_package() чтобы использовать местный пакет.

Испытано на Ubuntu 24.04.

cmake_minimum_required(VERSION 3.24)
project(geotags)

option(USE_BUNDLED "" ON)

if(USE_BUNDLED)
    set(CMAKE_POSITION_INDEPENDENT_CODE ON)

    include(FetchContent)
    FetchContent_Declare(tinyxml2
        SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/tinyxml2
        OVERRIDE_FIND_PACKAGE
    )

    # unfortunate hack to make TinyEXIF happy
    function(export)
    endfunction()

    FetchContent_Declare(TinyEXIF
        SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/TinyEXIF
        OVERRIDE_FIND_PACKAGE
    )
endif()

find_package(tinyxml2 REQUIRED)
find_package(TinyEXIF REQUIRED)

add_executable(geotags main.cpp)
target_link_libraries(geotags tinyxml2::tinyxml2 TinyEXIF)
→ Ссылка