CMake 使 dyld 在 /usr/local/lib 下查找库而不是运行时的实际路径

问题描述

问题

我正在尝试使用 irrklang 播放音乐。 irrklang 文件在我的项目目录中。构建很好,但是当我运行它时,它会报告 dyld: Library not loaded: /usr/local/lib/libikpFLAC.dylib一个应该在我的项目目录中的库)和原因:image not found
我不明白为什么它会在 /usr/local/lib/ 下寻找 dylib 以及如何在 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(Libs 应该在我的项目目录中并且没有 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)

这个问题不同于this。那里的解决方案是使用 otool 和 install_name_tool,但是我每次构建它时都必须使用它。我想知道是否有办法在 CMake 中使用 CorrectDirectory/foo.dylib 而不是 /usr/local/lib/foo.dylib

我也试过 RPath handling 但这不起作用,我需要通过不安装而是构建和运行它来使其工作。
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")

更新

现在我用来解决这个问题的方法是将以下几行附加到 hereCMakeLists.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 保持相同的名称

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)