问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

dylib能够动态加载吗

发布网友 发布时间:2022-05-30 16:44

我来回答

1个回答

热心网友 时间:2023-10-20 05:31

所谓dylib,就是bsd风格的动态库。基本可以认为等价于windows的dll和linux的so。mac基于bsd,所以也使用的是dylib。
如果你需要引用一个第三方的dylib,在xcode下编译出cocoa程序,在本机上运行是不会出问题的。但是发布出来,给其他用户用,就可能出问题。因为用户不一定有这个库。
这个问题给我造成了相当的困扰,我到现在也没找到正规的方法。但是我确实解决了这个问题,虽然方法不一定正宗。不管怎么说,写下来,如果暂时没有更好的办法,那么先这样做。如果谁有更好的办法,也请一定不吝留言或邮件给我。
我的办法是这样的:

1 otool -L yourapp.app/Contents/MacOS/yourapp
这一步的意思是对你编译出的app使用otool命令,以便获得依赖哪些dylib的信息。注意这个路径。cocoa的app在命令行下表现为目录。所有相关的东西都在里面。
结果如下所示:
yourapp.app/Contents/MacOS/yourapp:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
/usr/local/lib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意我标红的地方。假如lib01,lib02,lib03是本程序引用的第三方库,那么在这个程序里面,他们的引用地址是位于/usr/local/lib上的。这是开发机上的安装情况。而使用这个程序的客户机未必安装这些东西,所以程序就要出错。
显然,我们需要做2件事。a 把这些库附带在app上 b 把他们的引用地址修改到正确的位置。
2 mkdir yourapp.app/Contents/dylib
在编译出来的app中,创建dylib目录
然后把所有需要的库复制过去
cp /usr/local/lib/lib01.dylib yourapp.app/Contents/dylib/
cp /usr/local/lib/lib02.dylib yourapp.app/Contents/dylib/
cp /usr/local/lib/lib03.dylib yourapp.app/Contents/dylib/
3 install_name_tool -change /usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib "yourapp.app/Contents/MacOS/yourapp"

install_name_tool 是苹果提供的用来修改dylib安装名称的命令。这个命令执行之后,再用otool -L 就可以看到变化了
yourapp.app/Contents/MacOS/yourapp:
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 12.0.0)
@loader_path/../dylib/lib01.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib02.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/local/lib/lib03.dylib (compatibility version 0.0.0, current version 0.1.0)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 476.0.0)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 949.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 677.12.0)
注意标红的位置。已经变化了。@loader_path 指的是应用程序运行的位置,也就是yourapp.app/Contents/MacOS/yourapp,所以要用一个..,以便定位到第2步创建的dylib目录。
重复这个命令,修改lib02,lib03

4 otool -L yourapp.app/Contents/dylib/*.dylib
继续用otool 来检查dylib下面使用的第三方库是否还有其他依赖,install_name是否正确,重复1,2,3的步骤,把所需要的dylib复制过来,修改install_name。
如果都改对了,那么这个app就附带上了dylib,可以在其他机器上正确运行了,不用非要寻找/usr/local/lib下面的库了。

刚才我们修改的结果是一个build的结果。当然,每次build都这么折腾一下很麻烦。所以继续这样做:
1 前面的步骤得到了一个完整的dylib目录。把这个dylib复制一份备用。比如放在你的xcode项目下面。
2 编写一个脚本:
mkdir "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/dylib"
cp -f /your/path/to/xcode_project_name/dylib/*.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/dylib/"
install_name_tool -change /usr/local/lib/lib01.dylib @loader_path/../dylib/lib01.dylib "$TARGET_BUILD_DIR/$PRODUCT_NAME.app/Contents/MacOS/$PRODUCT_NAME"
(用这个格式重复前面对app使用过的dylib)
3 在xcode中,展开targets节点,右键点工程名称,在菜单中选Add->New Build Phasa->New Run Script Build Phasa,在打开的对话框里面,把刚才的脚本贴进去。如图所示。
这个脚本会在build之后自动运行。不过我这里有个奇怪的问题,如果Shell里面写了/bin/sh,会报告找不到这个文件(实际上存在),而让shell为空,反而可以正确的运行shell命令。

经过这些处理,每次编译出来的app就可以拿到其他机器上运行了。可真够麻烦的...
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
找专业防水队做完还漏水怎么维权 法院会受理房屋漏水造成的纠纷吗? 巴西龟最长活多久,家养!!! 养胃的药最好的是什么啊 婴儿积食发烧不愿吃药怎么办 板门穴位在哪个部位 手机设置放偷看的方法? 凝结水回收器生产厂家? 个人账户养老金预测公式:现有5万元,缴费20年,能领多少钱? 临沂比较有名的男装品牌 新天堂2好玩吗?什么职业好?我喜欢拿单手剑的 攻击力高点的 技能好看的话就更好了 如果没有的话 新天堂2各种职业的特点 mac python导入MySQLdb报错Symbol not found: _mysql_affected_rows 新天堂2什么职业好玩 我喜欢法师 我应该选什么职业 什么种族 XCode 怎么链接so动态库 新天堂2什么职业受欢迎 求新天堂2里所有辅助职业的名称和特性。。谢谢 extern 外部变量可以在动态链接库之间起作用吗? 天堂2职业介绍 《新天堂2》什么职业厉害 古法银是什么银 要开学了准备从北京飞回伦敦,求现在的出国航班攻略。 新移民美国行李打包攻略 公司外派到国外工作,准备从成都飞多伦多有什么好的攻略吗? 古法银和普通银的区别是什么? 热爱声乐的多吗 巫漪丽三个字怎么读? 巫漪丽三个字拼音怎么读? 肯尼迪机场国泰航空登机攻略,老人回国不会英文 家里的浴霸灯泡和家用小太阳取暖气哪个更费电 新天堂2种族和职业问题 求助:dylib加载问题:no suitable image found 直流电机的功率越大马力越大,做的功越多吗 一加手机质量如何? 营业执照办理完没有发下来可以营业吗? 营业执照没办好可以试营业吗 申请了营业执照,但是还没办理下来,可不可以先开店 有营业执照,卫生许可证还没办下来可以先试营业吗 如果营业执照还没发到经营者手里,饭店能先开张吗? 我营业执照还没办下来,请问能试营业吗 cad编号速写插件全是0? 男朋友玩到半夜三更,回去睡不着,找别的女生聊天。。算不算出轨?虽然没有暧昧 总是深夜找女生聊人生,这是什么心理? 一流鼻血就流这么多怎么回事。 一滴接着一滴往下流 流汗这么多怎么办??? 每次流鼻血都流这么多, 一滴接着一滴 还会流到嘴里。 怎么回事 为什么经期流那么多的血不死人呢 女人每个月流那么多血,为什么不死? 第一次ML到第三次都在流血,第四次没有流了,为什么流这么多次? 好友发咱大过年的流这么多血,还叫我去奔波,幽默回答 怎么回?