<转>

在 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. jquery-menu-aim插件实现二级导航

    jquery-menu-aim插件是实现二级导航亚马逊式三角滑动的强力工具,它在性能上极佳,快速滑动,基本无延迟效果,源码位置见对应作者的github,接下来附上样例代码: $(function () ...

  2. SQL 用到的操作符

    1.LIKE 操作符用于在 WHERE 子句中搜索列中的指定模式. SELECT column_name(s) FROM table_name WHERE column_name LIKE patte ...

  3. Maven仓库—Nexus环境搭建及使用

    使用Sonatype Nexus搭建Maven私服后如何添加第三方JAR包 http://blog.csdn.net/yanjun008/article/details/42084109 Nexus介 ...

  4. Nginx缓存配置以及nginx ngx_cache_purge模块的使用

    web缓存位于内容源Web服务器和客户端之间,当用户访问一个URL时,Web缓存服务器会去后端Web源服务器取回要输出的内容,然后,当下一个请求到来时,如果访问的是相同的URL,Web缓存服务器直接输 ...

  5. 设置git的http代理

    如果git仓库不和本地代码之间不可以直达,这个时候就可以考虑使用git 代理的方式提交代码到git仓库了; git http代理或者https代理,配置在~/.gitconfig 文件下,可以直接编辑 ...

  6. ArcGIS案例学习笔记2_1_山顶点提取最大值提取

    ArcGIS案例学习笔记2_1_山顶点提取最大值提取 计划时间:第二天上午 目的:最大值提取 教程:Pdf page=343 数据:chap8/ex5/dem.tif 背景知识:等高线种类 基本等高线 ...

  7. MySQL动态开启general_log

    mysql下用以下命令查看general_log的开启状态. show global variables like '%general%'; 调整general_log位置,linux下一般是/tmp ...

  8. Socket通讯-Netty框架实现Java通讯

    Netty简介 Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序. 也就是说,Netty ...

  9. burpsuite的使用(一)

    安装证书: 打开burpsuite,设置好代理.端口8080,但是打开https的网站却因为证书问题无法访问. 这需要我们为浏览器手动安装CA证书, 安装CA证书有两种方式: 1. 在burpsuit ...

  10. sql 允许远程登录

    grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option; flush privileges ...