<转>

在 OSX 上初次接触到这些变量,  做一个总结.
在编译一个动态库比如 libfoo.dylib 的时候, 你需要指定 INSTALL_PATH. 也就是它的安装路径.
一个可执行程序比如 bar.app 使用 libfoo.dylib, 那么在编译 bar.app 的时候, libfoo.dylib 的 INSTALL_PATH 会被记录到 bar.app 中, 用来定位这个 dylib. 用如下命令可以查看:

$ otool -L bar.app/Contents/MacOS/bar
      bar.app/Contents/MacOS/bar:
     /usr/local/lib/libfoo.dylib (compatibility version 1.0.0, current version 1.0.0)
     /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)
     /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.0.0)
     …
这里的 /usr/local/lib 就是默认的 INSTALL_PATH. 要 bar.app 能正常运行, 必须先把 libfoo.dylib 拷贝到这个目录. 如果 libfoo.dylib 只是被 bar.app 使用, 那么拷贝到系统目录可能是不合适的. 一个解决问题的办法就是修改 libfoo.dylib 的 INSTALL_PATH, 使用相对路径. 因而就需要用到下面这三个变量.

看 dyld 的 manual, 有这三个变量的解释.

@executable_path 这个变量表示可执行程序所在的目录. 比如 /path/bar.app/Contents/MacOS/ .

@loader_path 这个变量表示每一个被加载的 binary (包括可执行程序, dylib, framework 等) 所在的目录. 在一个进程中, 对于每一个模块, @loader_path 会解析成不用的路径, 而 @executable_path 总是被解析为同一个路径(可执行程序所在目录). 比如一个会被多个程序调用的 plugin, 位于 /path/Myfilter.plugin/Contents/MacOS/Myfilter, 依赖 /path/Myfilter.plugin/Contents/dylib/libfoo.dylib. 那么 libfoo.dylib 的 INSTALL_PATH 可以设置为 @loader_path/../dylib, 这样设置的话, 不论 Myfilter.plugin 目录放到什么位置, libfoo.dylib 都能正确的被加载.

@rpath 和前面两个不同, 它只是一个保存着一个或多个路径的变量. 比如 libfoo.dylib 被两个 .app 使用, 且被包含的路径不同, 如下:

bar.app/
                       Contents/
                                          MacOS/
                                                            bar
                                                                         libfoo.dylib

baz.app
                    Contents/
                                         MacOS/
                                                           baz
                                                                      dylibs/
                                                                                      libfoo.dylib
将 libfoo.dylib 的 INSTALL_PATH 设置成 @loader_path/.. 或 @loader_path/../dylibs 都只能满足其中一个 .app 的需求. 要解决这个问题, 就可以用 @rpath. 将 libfoo.dylib 的 INSTALL_PATH 设置成 @rpath, 然后在编译 bar.app, baz.app 时分别指定 @rpath 为 @loader_path/.., @loader_path/../dylibs, 问题得到了解决. @rpath 的另一个优点是可以设置多个路径. 如果 bar.app 还需要使用另一个 .framework (假设它的 INSTALL_PATH 也设置成了 @rpath), 位于 @loader_path/../frameworks, 把这个路径加到 @rpath 即可.

iOS 编译部署路径的更多相关文章

  1. 随手写的自动批量编译部署NativeAndroid程序Python脚本

    背景 有一堆工程NativeAndroid程序,要一一编译部署编译测试,手头只有AndroidManifest和Makefile,需要一个个Update,Ndk-build,和发包安装测试,很是头疼, ...

  2. iOS编译FFmpeg、kxmovie实现视频播放 (转载)

    由于FFmpeg开源框架的功能非常强大,可以播放的视频种类很多,同时添加第三方库kxmovie,实现视频播放,真的是爽爆了,因此今天来说一下关于FFmpeg在iOS手机上的一些配置过程,配置工具,还有 ...

  3. iOS动态部署方案

    转载: iOS动态部署方案 前言 这里讨论的动态部署方案,就是指通过不发版的方式,将新的内容.新的业务流程部署进已发布的App.因为苹果的审核周期比较长,而且苹果的限制比较多,业界在这里也没有特别多的 ...

  4. jenkins+gitlab自动化编译部署方案探索及服务端编译webpack实战

    一. 背景 之前我们的开发流程为在本地进行webpack打包编译,然后svn提交源代码和编译后的代码.同时每次提交前也会从svn更新源代码和编译后的代码.这样做有几个缺点: 1. svn 更新和提交编 ...

  5. 如何编译部署 UIKit 离线文档?

    如何编译部署 UIKit 离线文档? Whis is UIKit? Note:部署在 Windows 系统会出现路径错误情况,这里采用在 Debian 系统上进行编译和部署. 1. 安装一些前置工具 ...

  6. Spark Tachyon编译部署(含单机和集群模式安装)

    Tachyon编译部署 编译Tachyon 单机部署Tachyon 集群模式部署Tachyon 1.Tachyon编译部署 Tachyon目前的最新发布版为0.7.1,其官方网址为http://tac ...

  7. iOS 编译过程原理(2)

    一.前言 <iOS编译过程的原理和应用>文章介绍了 iOS 编译相关基础知识和简单应用,但也很有多问题都没有解释清楚: Clang 和 LLVM 究竟是什么 源文件到机器码的细节 Link ...

  8. iOS 编译过程原理(1)

    一.前言 一般可以将编程语言分为两种,编译语言和直译式语言. 像 C++.Objective-C 都是编译语言.编译语言在执行的时候,必须先通过编译器生成机器码,机器码可以直接在 CPU 上执行,所以 ...

  9. 为iOS编译FFmpeg静态库

    为iOS编译FFmpeg静态库 
 环境:OS X Yosemite (版本10.10.5) Xcode (Version 7.1.1 (7B1005)) 
 
 一.资料准备: (1)ffmpeg源 ...

随机推荐

  1. Hive安装 和管理

  2. Oracle 学习总结 - 问题诊断

    搜集常用诊断sql https://blog.csdn.net/yangshangwei/article/details/52449489 lock相关: 1. 查看lock, 打开两个事物,事物1更 ...

  3. 【x】 PAT/BasicLevel_C++/1002. 写出这个数 (20).cpp

    C++中的to_string()函数[C++11支持] - Bravo Yeung-羊较瘦之自留地 - CSDN博客https://blog.csdn.net/lzuacm/article/detai ...

  4. RabbitMQ系列教程之四:路由(Routing)(转载)

    RabbitMQ系列教程之四:路由(Routing) (使用Net客户端) 在上一个教程中,我们构建了一个简单的日志系统,我们能够向许多消息接受者广播发送日志消息. 在本教程中,我们将为其添加一项功能 ...

  5. wx小程序自定义组件与页面之间参数传递

    在开发中,很多页面中会使用相同的组件,这时可以将具有相同信息的部分封装成一个组件,方便开发中调用.在调用中可能会涉及到数据的传递问题,例如页面与组件,组件与组件直接的数据传递. 首先看看页面与组件直接 ...

  6. 计算机网络协议包头赏析-IP

    上次和大家聊了聊以太网的帧格式,本文会讲解IP数据报格式的定义. == 开门见山,先上图: 任何一个IP数据报都是由首部和数据两部分组成,而且首部基本是固定长度的,长度为20字节.这一点很重要,其他都 ...

  7. asp.net中的reportview报错跟预编有关系

    当报表控件出现: 报表定义无效.详细信息:根级别上的数据无效.行1,位置1. 先检查一下,你的aspx文件是不是变成了这样一句话 这是预编译工具生成的标记文件,不应被删除! 如果这样的话,报表控件是不 ...

  8. TensorFlow 语法

    dataset = tf.data.TextLineDataset(file_path) 生成一个dataset,dataset中的每一个元素就对应了文件中的一行

  9. 什么是webFlux

    什么是webFlux 左侧是传统的基于Servlet的Spring Web MVC框架,右侧是5.0版本新引入的基于Reactive Streams的Spring WebFlux框架,从上到下依次是R ...

  10. 关于Android file.createNewFile() 失败的问题

    [关于Android file.createNewFile() 失败的问题] 需要注意的是:要先对设计的文件路径创建文件夹 , 然后在对文件进行创建. 参考:http://blog.csdn.net/ ...