<转>

在 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. ssm框架使用jsp提交表单到controller

    jsp代码: controller代码:

  2. CSS 的 ID 和 Class 有什么区别,如何正确使用它们。

    css只用class来写并有专门的class通用和私有模块命名, id具有唯一性且优先级太高只作为js操作dom的挂钩全部不添加样式, 如果使用jq或zepto的话,操作的class类名一般也不加样式 ...

  3. 飞利浦 PHILIPS 电动牙刷HX6730 拆解

    今日,一直比较喜欢用的电动牙刷,飞利浦HX6730坏掉了,初步感觉考虑飞利浦的保修,但是发现发票找不到了.飞利浦的客服也说,电动牙刷的两年保修依据分别是:1.发票开据日期:2.在无发票的情况下,看底部 ...

  4. The Google File System——论文详解(转)

    “Google文件存储系统(GFS)是构建在廉价服务器之上的大型分布式系统.它将服务器故障视为正常现象,通过软件方式自动容错,在保证系统可用性和可靠性同时,大大降低系统成本. GFS是Google整个 ...

  5. JSFL 禁止脚本运行时间太长的警告

    fl.showIdleMessage(false);

  6. Delphi 透明窗体显示文字

    设置窗体属性:BorderStyle 属性设置为 bsNoneColor 属性设置为 clWhite(白色:窗体背景色)TransparentColor 属性设置为 trueTransparentCo ...

  7. 中文转码器的工作原理_delphi教程

    最近在做Delphi下的简体与繁体转换, 发现Windows2000自带的工具"中文转码器"很好用, 不仅可以转内码(BIG5-->GBK), 还可以将繁体字转为简体字(如: ...

  8. RabbitMQ、Memcached、SQLAlchemy

    一.RabbitMQ 1.基础概念 rabbitMQ说白了就是一个消息队列,类似于Queue,也是生产者与消费者模型.只不过做了扩展,所不同的是Queue在内存中的消息队列,而RabbitMQ是部署在 ...

  9. C# Liseview的使用方法之一:滚动到选中的行

    listview.items[i].EnsureVisible();//滚动到你想要显示出来的行上. 其中,listview.items[i]就是你想要显示的行.

  10. Microsoft® SQL Server® 2012 功能包

    Microsoft® SQL Server® 2012 功能包 http://www.microsoft.com/zh-cn/download/details.aspx?id=29065 Micros ...