我终于用一种稍微不同的方法完成了这项工作。这可能不是完美的解决方案并且在所有情况下都有效,但希望这能帮助遇到与我类似问题的人。
我试图链接到的 dylib 是libSDL2-2.0.0
如果我导航到该文件所在的位置并运行:
otool -L libSDL2-2.0.0.dylib
我在输出中得到的第一行是:
/usr/local/lib/libSDL2-2.0.0.dylib
如果我然后导航到我构建的可执行文件并运行相同的命令,我会看到同样的事情:
/usr/local/lib/libSDL2-2.0.0.dylib
(我的可执行文件链接到 SDL)
我的问题libSDL2-2.0.0.dylib
实际上并不在那里,它在我的项目结构中的 libs 文件夹中。为了让链接器在运行时找到库,我不得不在 dylib 上运行这个命令
install_name_tool -id "@executable_path/../path/to/lib/<lib_name>" <lib_name>
要运行的应用程序的位置在哪里@executable_path
- 在我的情况下,这是在 -build/debug
项目结构:
root/
CMakeLists.txt
project/
lib/
libSDL2-2.0.0.dylib
build/
debug/
my_app
为了清楚起见,这是一个精确的映射:
install_name_tool -id "@executable_path/../../project/lib/libSDL2-2.0.0.dylib" libSDL2-2.0.0.dylib
如果我跑步,otool -L libSDL2-2.0.0.dylib
我现在看到:
@executable_path/../../sdl-test/lib/libSDL2-2.0.0.dylib
在输出的第一行。
如果我现在再次构建我的项目(我只是在 Xcode 中构建),这将使用 dylib 的新相对路径更新我的应用程序。你只需要install_name_tool
在库上运行,你也不必在你的可执行文件上运行它,它会在你构建它时更新。
如果我运行,otool -L myapp
我现在会看到相同的相对路径libSDL2-2.0.0.dylib
这样,在启动应用程序时,它就能够成功找到 dylib!
我的理解是,这是在 OSX 上实现这一目标的方法,并且没有一个很好的选择(除了DYLD_FALLBACK_LIBRARY_PATH
我在问题中提到的搞乱)
我希望这对与我有类似困难的人有所帮助!
我发现有用的资源:
http://osiris.laya.com/coding/dylib_linking.html
https://www.fmod.org/questions/question/forum-23398/
https://blogs.oracle.com/dipol/entry/dynamic_libraries_rpath_and_mac
更新:
实际上,我找到了使用 rpaths 执行此操作的更好方法,并认为我会写下如何执行此操作以供将来参考:
在我的 CMakeLists.txt 文件中,我在最后添加了这些行(在ADD_EXECUTABLE
和之后TARGET_LINK_LIBRARIES
:
# set @rpaths for libraries to link against
SET(CMAKE_SKIP_BUILD_RPATH FALSE)
SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
SET(CMAKE_INSTALL_RPATH "${PROJ_LIB_DIR}")
SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
(有关更多信息,请参阅https://cmake.org/Wiki/CMake_RPATH_handling )
${PROJ_LIB_DIR}
我的dylib在哪里:
SET(PROJ_LIB_DIR ${CMAKE_CURRENT_LIST_DIR}/lib)
然后我跑了:
例子:
install_name_tool -id "@rpath/<my-dylib>.dylib" <my-dylib>.dylib
实际的:
install_name_tool -id "@rpath/libSDL2-2.0.0.dylib" libSDL2-2.0.0.dylib
在我的 dylib 所在的目录中(在我的情况下为 libSDL2-2.0.0.dylib)
现在,当我运行 cmake 然后构建我的项目时,我的新可执行文件将在运行时在 CMakeLists.txt 文件中设置的位置搜索库。@rpath
将替换为 CMakeLists.txt 文件中指定的路径,一切正常,无需显式设置@executable_path
或@loader_path