这是由Dynamic Linker引起的运行时错误
dyld: Library not loaded: @rpath/<some_path>
Referenced from: <some_path>
Reason: image not found
错误Library not loaded 和@rpath 表示Dynamic Linker 找不到二进制文件。
-
检查动态框架是否添加到front目标General -> Frameworks, Libraries, and Embedded Content (Embedded Binaries)。使用Copy items if needed[About] 拖放框架以进行投影非常简单,并且错过了将框架添加为隐式依赖项
Frameworks, Libraries, and Embedded Content(或签入Add to targets)。在这种情况下,在编译时 Xcode 将其构建为成功,但是当您运行它时会出现运行时错误
-
检查消费者(应用程序)和生产者(动态框架)之间的@rpath 设置:
- 动态框架:
Build Settings -> Dynamic Library Install Name
- 应用:
Build Settings -> Runpath Search Paths
Build Phases -> Embed Frameworks -> Destination, Subpath
- 框架的
Mach-O file[About] - 动态库和应用程序的Frameworks, Libraries, and Embedded Content[About] - 不要嵌入。
动态链接器
Dynamic Library Install Name(LD_DYLIB_INSTALL_NAME) 被 loadable bundle(Dynamic framework 用作派生词)在其中 dyld 发挥作用
Dynamic Library Install Name - 二进制文件的路径(不是 .framework )。是的,它们具有相同的名称,但MyFramework.framework 是一个packaged bundle,其中包含MyFramework 二进制文件和资源。
此目录路径可以是绝对路径或相对路径(例如 @executable_path、@loader_path、@rpath)。相对路径更可取,因为它与锚点一起更改,当您将捆绑包作为单个目录分发时很有用
绝对路径 - Framework1 示例
//Framework1 Dynamic Library Install Name
/some_path/Framework1.framework/subfolder1
Relative path 允许您以动态方式定义路径。
@executable_path
@executable_path - 相对于加载框架的 executable 二进制文件
用例:Dynamic framework 内 Application(应用程序二进制路径
是@executable_path) 或更复杂的例子,App Extension[About] 是Containing App 的一部分,里面有Dynamic Framework。有 2 个 @executable_path 用于 Application 目标(应用程序二进制路径是 @executable_path)和 App Extension 目标(应用程序扩展二进制路径是 @executable_path)) - Framework2 示例
//Application bundle(`.app` package) absolute path
/some_path/Application.аpp
//Application binary absolute path
/some_path/Application.аpp/subfolder1
//Framework2 binary absolute path
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
//Framework2 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework2 Dynamic Library Install Name
@executable_path/../Frameworks/Framework2.framework/subfolder1
//Framework2 binary resolved absolute path by dyld
/some_path/Application.аpp/subfolder1/../Frameworks/Framework2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
@loader_path
@loader_path - 相对于导致框架被加载的包。如果它是一个应用程序,它将与@executable_path 相同
用例:带有嵌入式框架的框架 - Framework3_1 和 Framework3_2 内部
//Framework3_1 binary absolute path
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1
//Framework3_2 binary absolute path
/some_path/Application.аpp/Frameworks/Framework3_1.framework/Frameworks/Framework3_2.framework/subfolder1
//Framework3_1 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework3_1 @loader_path == Framework3_1 @executable_path <-
/some_path/Application.аpp/subfolder1
//Framework3_2 @executable_path == Application binary absolute path <-
/some_path/Application.аpp/subfolder1
//Framework3_2 @loader_path == Framework3_1 binary absolute path <-
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1
//Framework3_2 Dynamic Library Install Name
@loader_path/../Frameworks/Framework3_2.framework/subfolder1
//Framework3_2 binary resolved absolute path by dyld
/some_path/Application.аpp/Frameworks/Framework3_1.framework/subfolder1/../Frameworks/Framework3_2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework3_1.framework/Frameworks/Framework3_2.framework/subfolder1
@rpath - 运行路径搜索路径
Framework2示例
以前我们必须设置一个框架来使用 dyld。这不方便,因为相同的框架不能用于不同的配置。由于此设置是在框架目标端进行的,因此无法为不同的消费者(应用程序)配置相同的框架
@rpath 是一个复合概念,依赖于外部(应用程序)和嵌套(动态框架)部分:
-
应用:
-
Runpath Search Paths(LD_RUNPATH_SEARCH_PATHS) - @rpath - 定义将替换为 @rpath 的模板列表。消费者使用@rpath这个词指向这个列表
@executable_path/../Frameworks
-
查看Build Phases -> Embed Frameworks -> Destination, Subpath 以确定嵌入框架的确切位置
-
动态框架:
//Application Runpath Search Paths
@executable_path/../Frameworks
//Framework2 Dynamic Library Install Name
@rpath/Framework2.framework/subfolder1
//Framework2 binary resolved absolute path by dyld
//Framework2 @rpath is replaced by each element of Application Runpath Search Paths
@executable_path/../Frameworks/Framework2.framework/subfolder1
/some_path/Application.аpp/Frameworks/Framework2.framework/subfolder1
*../ - 转到当前目录的父目录
otool - 目标文件显示工具
//-L print shared libraries used
//Application otool -L
@rpath/Framework2.framework/subfolder1/Framework2
//Framework2 otool -L
@rpath/Framework2.framework/subfolder1/Framework2
//-l print the load commands
//Application otool -l
LC_LOAD_DYLIB
@rpath/Framework2.framework/subfolder1/Framework2
LC_RPATH
@executable_path/../Frameworks
//Framework2 otool -l
LC_ID_DYLIB
@rpath/Framework2.framework/subfolder1/Framework2
install_name_tool 使用 -rpath 更改动态共享库安装名称
CocoaPods 使用use_frameworks![About] 调节Dynamic Linker
[Vocabulary]
[Java ClassLoader]