При 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 шт):
Это работает с 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)