c++ - CMake 使 dyld 在 /usr/local/lib 下查找库,而不是运行时的实际路径
问题描述
问题
我正在尝试使用 irrKlang 播放音乐。irrKlang 文件位于我的项目目录中。构建很好,但是当我运行它时它会报告dyld: Library not loaded: /usr/local/lib/libikpFLAC.dylib
(应该在我的项目目录中的库)和原因:image not found
.
我不明白为什么它会在下查找 dylib/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
(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)
这个问题与此不同。解决方案是使用 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
保持相同的名称。
解决方案
推荐阅读
- sql - T-SQL 以表格格式解析 XML 响应
- aws-step-functions - 如何使用 CDK 为 AWS Step Functions 创建 VPC 终端节点?
- java - 我只想要一个用于所有活动的自定义工具栏我尝试了许多解决方案,但没有一个有效
- python - 通过浏览器向后移动时,即使在刷新后也会出现过时的元素引用异常
- sql - 在特定条件下加入表
- firebase - 无法访问 Cloud Firestore 后端
- javascript - TwoSum - Integers and Arrays
- azure - 运行 ASR 健康状态报告 Kusto 查询时出错
- python - 在分配错误之前引用的局部变量
- c++ - 1>链接:致命错误LNK1104:无法打开文件'MSCOREE.lib'`