CMake заставляет dyld находить библиотеки в каталоге /usr/local/lib вместо фактического пути во время выполнения.

ПРОБЛЕМА

Я пытаюсь использовать irrKlang для воспроизведения музыки. Файлы irrKlang находятся в каталоге моего проекта. Сборка прошла нормально, но когда я ее запускаю, она сообщает dyld: Library not loaded: /usr/local/lib/libikpFLAC.dylib (библиотека, которая должна была быть в каталоге моего проекта) и причину: image not found.
Я не понимаю, почему она ищет dylibs под /usr/local/lib/ и как я могу изменить что в CMake (без использования otool и install_name_tool)

КОДЫ
Вот простой проект, позволяющий это сделать:

main.cpp:

#include <iostream>
#include "irrKlang.h"

int main() {
    std::cout << "Hello, World!" << std::endl;
    irrklang::ISoundEngine* engine = irrklang::createIrrKlangDevice();

    if (!engine)
        std::cout << "Failed to initialize the engine" << std::endl; // error starting up the engine
    engine->play2D("irrKlang/media/ophelia.mp3", true); // Path referencing error, but this is not the issue here, as the program didn't even make it to Hello World
    return 0;
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)
project(Program)

set(CMAKE_CXX_STANDARD 17)

message("${PROJECT_SOURCE_DIR}")
file(GLOB IRRKLANG_LIBS "irrKlang/bin/macosx-gcc/*.dylib")
link_directories("${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} irrKlang/bin/macosx-gcc)
set(IRRKLANG_INCLUDE irrKlang/include)
file(GLOB IRRKLANG_INCLUDE_FILES "${IRRKLANG_INCLUDE}/*.h")
include_directories(${IRRKLANG_INCLUDE})

add_executable(Program main.cpp "${IRRKLANG_INCLUDE_FILES}")
target_link_libraries(Program ${IRRKLANG_LIBS})
target_link_directories(Program PUBLIC "${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")

В моем проекте есть каталог irrKlang с деревом каталогов:

irrKlang
├── bin
│   ├── dotnet-4-64
│   ├── linux-gcc-64
│   ├── macosx-gcc (with .dylib files in it)
│   └── winx64-visualStudio
├── doc (...)
├── examples (...)
├── examples.net (...)
├── include
├── lib
│   └── Winx64-visualStudio
├── media (with some audio files in it)
└── plugins
    └── ikpMP3
        └── decoder

Ошибка:

dyld: Library not loaded: /usr/local/lib/libikpFLAC.dylib
  Referenced from: /Users/mac/Documents/VSCProjects/untitled/cmake-build-debug/Program
  Reason: image not found

OTool (библиотеки должны были быть в каталоге моего проекта и не иметь префикса lib):

/usr/local/lib/libikpFLAC.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/lib/libikpMP3.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/local/lib/libirrklang.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 904.4.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1292.0.0)

Эта проблема отличается от этой. Решение состояло в том, чтобы использовать otool и install_name_tool, но тогда мне приходится использовать его каждый раз, когда я его создаю. Мне интересно, есть ли способ использовать CorrectDirectory/foo.dylib вместо /usr/local/lib/foo.dylib внутри CMake.

Я также пробовал обработку RPath, но это не работает, и мне нужно заставить его работать, не устанавливая, а собирая и запуская его.
CMakeLists.txt:

cmake_minimum_required(VERSION 3.17)
project(Program)

set(CMAKE_CXX_STANDARD 17)
# use, i.e. don't skip the full RPATH for the build tree
set(CMAKE_SKIP_BUILD_RPATH FALSE)

# when building, don't use the install RPATH already
# (but later on when installing)
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)

# the RPATH to be used when installing
set(CMAKE_INSTALL_RPATH "${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")

set(CMAKE_MACOSX_RPATH "${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")

# don't add the automatically determined parts of the RPATH
# which point to directories outside the build tree to the install RPATH
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)

message("${PROJECT_SOURCE_DIR}")
file(GLOB IRRKLANG_LIBS "irrKlang/bin/macosx-gcc/*.dylib")
message("${IRRKLANG_LIBS}")
link_directories("${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} irrKlang/bin/macosx-gcc)
set(IRRKLANG_INCLUDE irrKlang/include)
file(GLOB IRRKLANG_INCLUDE_FILES "${IRRKLANG_INCLUDE}/*.h")
include_directories("${IRRKLANG_INCLUDE}")

add_executable(Program main.cpp "${IRRKLANG_INCLUDE_FILES}")
target_link_libraries(Program "${IRRKLANG_LIBS}")
target_link_directories(Program PUBLIC "${PROJECT_SOURCE_DIR}/irrKlang/bin/macosx-gcc")

ОБНОВЛЕНИЕ

Сейчас я использую для решения этой проблемы добавление следующих строк в CMakeLists.txt из здесь:

add_custom_command(TARGET Program POST_BUILD
        COMMAND install_name_tool -change /usr/local/lib/libikpFLAC.dylib ${IRRKLANG_LIBDIR}/ikpFLAC.dylib cmake-build-debug/Program
        COMMAND install_name_tool -change /usr/local/lib/libikpMP3.dylib ${IRRKLANG_LIBDIR}/ikpMP3.dylib cmake-build-debug/Program
        COMMAND install_name_tool -change /usr/local/lib/libirrklang.dylib ${IRRKLANG_LIBDIR}/libirrklang.dylib cmake-build-debug/Program
        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
        COMMENT "Changing lib paths"
        )

Но все же мне интересно, могу ли я систематически решить это, не повторяя их, поскольку может быть разница между именем lib, на которое ссылается исполняемый файл, и именем, где оно находится на самом деле (например, .../libikpMP3.dylib до .../ikpMP3.dylib, но .../libirrklang.dylib остается тем же именем .


person Qiufeng54321    schedule 20.05.2021    source источник