用objective-c开发的第一个mac程序(3)——动态库与静态库的问题

在Objective-C开发的Mac程序中遇到动态库找不到的错误。尝试将动态库拷贝到执行文件目录和系统目录,使用otool查看依赖库情况,修改LC_RPATH,但问题未解决。最终通过将动态库静态化链接到程序中,解决了依赖问题。在打包和测试过程中,确保动态库位于正确位置,成功创建安装包并测试通过。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

打包之后,在测试电脑安装后,程序需无法运行,错误信息为:找不到依赖的动态链接库

试想动态链接库的问题,我们在 Windows 是怎么处理的呢?拷贝到执行文件相同目录或系统 system32 目录即可。苹果的 app 与 Windows 的可执行文件有一定的区别,Mac 下的 app 不是一个可执行文件,而是一个目录,而真正的可执行文件是在 xxx.app/Contents/MacOS/ 目录下;

于是我将动态库做了如下的操作:

  1. 拷贝到 app 的可执行文件相同的目录下,即 xxx.app/Contents/MacOS/ 目录下;
  2. 拷贝到 xxx.app/Contents/Frameworks/ 目录下,而我检查 Xcode 工程目录的 Runpath Search Paths 的属性,默认的就是 $(inherited) @executable_path/../Frameworks

以上的操作均不能解决问题,于是我就使用 otool -L xxx.dylib 命令来查看依赖库的情况,如下:

libtimelink-tuio.dylib:
	/usr/local/lib/libtinyxml.dylib (compatibility version 1.0.0, current version 1.0.0)
	libboost_thread.dylib (compatibility version 0.0.0, current version 0.0.0)
	libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

/usr/local/lib/libtimelink-tuio.dylib 是绝对目录,其他库/可执行文件调用他时需在 /usr/local/lib/ 下找到 libtimelink-tuio.dylib 这个依赖库
libboost_thread.dyliblibboost_system.dylib 是相对路径,xxxx.dylib在当前目录调用它;
/usr/lib/libc++.1.dylib/usr/lib/libSystem.B.dylib 是依赖的系统库;

而每个动态库或可执行文件都有个 install_name 的属性,可使用 install_name_tool 命令修改,如下:

install_name_tool -id “@executable_path/../Frameworks/libtimelink-tuio.dylib” libtimelink-tuio.dylib

然后执行 otool -L libtimelink-tuio.dylib 查看修改后的状态:

libtimelink-tuio.dylib:
	@executable_path/../Frameworks/libtinyxml.dylib (compatibility version 1.0.0, current version 1.0.0)
	libboost_thread.dylib (compatibility version 0.0.0, current version 0.0.0)
	libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

修改 install_name 之后,重新生成可执行文件,还是出错了,因为 MacApp.app/Contents/Frameworks 默认不存在,需手动创建该目录并拷贝依赖库到该目录下;
再重新生成可执行文件,OK,但是无论是打包或者直接拷贝到测试的电脑,都是原来的错误;

另外还有一个经常出现的 bug,Xcode 中丢失 mainmenu.xib 找不到,把工程文件拷贝一份,在拷贝的那个工程打开再重新编译又OK了。

难道它依赖的其他的库 boost_system boost_threadinstall_name 有问题?但不管换成相对路径还是绝对路径都不行;

然后想到将 boosttinyxml 以静态库的形式链接到 libtimelink-tuio.dylib 中,减化库与库之间的依赖:

  • 重新编译 boostlibboost_thread & libboost_system 静态库(因为之前没有编译静态库)
  • 重新编译 tinyxml 静态库
  • 重新编译 libtimelink-tuio 静态库

此时 objective-cMacApp 工程重新链接这个头文件库文件,编译通过了,但链接时出现问题 apple mach-o linker error

我已经看不下去了,当初为啥那么傻 —— 来自2019年的自己

如下是一个很傻B的试验,我不打算整理这一段 -_-!

--> 用xcode建个c++的工程,然后链接xxxx.a静态库(直接将xxxx.a拖到左边目录,就路径等就自动配置了),然后一大坨相同的错误;

--> 使用动态库的时候都能链接成功的,究竟是什么原因呢?

分析了这样的情况,比如有一下目录:
|-- main.cpp 
|-- a.cpp inc1.h inc2.h
|-- b.cpp inc2.h inc3.h

用g++编译程序的时候应该是这样的:
gcc -c a.cpp 生成 a.o #编译
gcc -c b.cpp 生成 b.o #编译
gcc -static -o ab.a a.o b.o # 静态库
gcc -o test1 main.cpp ab.a # 链接

gcc -shared -o ab.dylib a.o b.o # 动态库
gcc -o test2 main.cpp -L ./ -lab  #链接

使用命令:otool -L ab.a,看到的依赖的库是:a.o b.o,
原来静态库是不做链接对,只是将一个一个的.o集在一起,做成一个.a,
也就是.a是只编译但没有链接的,
难怪编译依赖库的静态库时基本不会出问题,而动态库却经常链接出错,因为静态库不做链接(这就意味着生成可执行文件(调用这个静态库的)时就需要链接了);
所以也不难解释,现在加到项目工程中,编译、生成可执行文件时,链接静态库的时候还是出一大堆的问题;

但是我将所有依赖的库的静态库都加进工程里,还是出现这样的错误,奇怪了;

最后不用 libtimelink-tuio.a 静态库了,重新编译一个 libtimelink-tuio.dylib(不依赖于boost库)
libtimelink-tuio.dylibinstall_name 改成 /Users/Shared/timelink-tuio/libtimelink-tuio.dylib

libtimelink-tuio.dylib:
	/Users/Shared/timelink-tuio/libtimelink-tuio.dylib (compatibility version 1.0.0, current version 1.0.0
	/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1213.0.0)

libtimelink-tuio.dylib 放到 /Users/Shared/timelink-tuio/ 目录下
objective-c 工程的库目录改成 /Users/Shared/timelink-tuio/,OK
打包,将依赖的动态库放在打包的 Packages 工程的 payload 的 content 列表的 Users-Shared-timelink-tuio 下,然后生成 mpkg 安装包,拿去测试的电脑,测试通过了!!!

注:以上是测试安装包;

总结:对编译原理没完全懂,有些方法还没有试就已经不淡定了;
这个解决方法算是用了旁门左道的,xxxx.app/Contents/Frameworks/这个东西还没解决;
这东西又催的急,感觉快撑不住了!还好算是好了!

有点傻,有很多步骤其实没有必要!可能这就是成长的历练吧! —— 来自2019的自己

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值