Save&Load

Save The World, Load The Game

0%

在Mac上折腾ELF

之前的文章里有说,要在Mac下面测试一个C++的项目,结果安装好gtest之后,把开发的工程拿过来编译了一下,结果就报错了,报错部分内容如下:

ld: warning: ignoring file ../libs/libeasy.a, file was built for archive which is not the architecture being linked (x86_64): ../libs/libeasy.a
Undefined symbols for architecture x86_64:

看到这个错误,首先想到的是难道是因为我是64位的机器而lib是32位的?然后google了一下,貌似确实有这种可能,那既然不支持就在编译的时候加上-arch i386,咱在32位编译不就好了。结果问题依旧。。。没办法问了一下开发,开发说引用的lib就是64位的,好吧,看来是方向找错了。
这时候先用objdump确认一下文件的格式,

>gobjdump -f libeasy.a
In archive libeasy.a:

easy_buf.o:     file format elf64-x86-64-nacl
architecture: i386:x86-64:nacl, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

可以看到文件格式是ELF64-x86-64-nacl,看来确实是64位的没跑了,那为什么会报这样的错呢?继续google之,翻了几页之后,看到有一种就是文件的格式问题。好了,继续验证一下是不是这个问题,手动在Mac下编译出一个lib看看:

>g++ -c main.cpp
>ar rvs main.a main.o
>gobjdump -f main.a
In archive main.a:

main.o:     file format mach-o-x86-64
architecture: i386:x86-64, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x0000000000000000

可以看到文件格式是Mach-O-x86-64,查了一下这个是mac自家使用的文件格式,也就是说和ELF是不兼容的。进一步查了一下,在Mac OS X for Unix Geeks中有这么一段话:

The Executable and Linking Format (ELF), developed by the Unix System Laboratories, is common in the Unix world. On ELF systems, there is no distinction between shared libraries and loadable modules; shared code can be used as a library for dynamic loading. ELF is the default binary format on Linux, Solaris 2.x, and SVR4. Since these systems cover a large share of the Unix base, most Unix developers have experience on ELF systems. Thus, it may come as a surprise to experienced Unix developers that shared libraries and loadable modules are not the same on Mac OS X. This is because the binary format used in Mac OS X is Mach-O, which is different from ELF.
意思就是Mach-O和ELF这俩东西不是一回事,然后又查了下如果想要在Mac下使用ELF的lib的话,几乎是不可能的。为啥说几乎不可能呢,因为还是有几种办法的:
1.使用xBinary,它可以扩展Mac支持的文件格式,但是这个工具是2009年开发的,后续维护也不是很多仅供科研使用,而且用起来也很麻烦。
2.使用objconv,这是个文件格式转换工具,不过转换出来的稳不稳定这个就不好说了。
3.修改Mac内核,添加支持,这个难度太大了。。。
所以说几乎不可能了。最好的解决办法是拿到lib的源代码,然后在本机编译一下,但是有些lib文件拿不到源代码,这时候只能用不是办法的办法了,使用虚拟机安装一个Ubuntu或者SSH登录到远程linux服务器上写代码。总之,这是个不大不小的坑吧,也算是对Mac系统了解了一下。