OS X(MACOS) C/C++ 程序链接静态库限制。
在OSX上面C/C++程序不被允许完全静态链接,当然无论是 Windows 还是 Linux 上面也没有办法真正做到完全的静态链接。
OSX上面C/C++程序静态链接也有一些麻烦跟坑点,我们都知道在OSX上面是使用 brew 工具链来安装程序跟依赖的,它会自动下载目标程序代码跟依赖库代码,在OSX本地编译之后在部署到系统环境之中。
这就导致一个问题,比如我们要静态链接 jemalloc,已经在 Makefile 或者 CMakeFiles 工程内指定了使用 jemalloc 那么就一定会链接到 libjemalloc.dylib
有人可能就会说,那么改成链接 libjemalloc.a 就好了?我只能说你想太多,也太天真了,不行的,即便我们写成链接 libjemalloc.a,它还是会链接成 libjemalloc.dylib,神奇把,它就是不会给你链接静态库。
这个时候你就需要看看 Apple 发布的这篇关于静态编译链接的FAQ文章了:
Technical Q&A QA1118: Statically linked binaries on Mac OS X (apple.com)
又有人说,如果我自己手动去编译 jemalloc,出来了静态库、动态库,我指定自己编译出来的目录行不行呢?
答案是不行,即便你把你自己编译出来的dylib动态库全删了,就留下静态库a文件也是会连接到系统编译的libjemalloc.dylib的,这根本不是你删不删文件的问题。
如果你想要解决就只有两个办法能够让我们连接上指定的静态库。
1、把安装到系统的库直接全部卸载删除干净
2、写静态库的绝对路径,不要用任何相对路径,否则写 XX.a 都是链接到对应动态库,除非OSX系统中没有安装这个库的情况下。
我本人推荐用第二方法,写静态库的绝对路径,记住是绝对路径不是相对路径,就是要从根目录 "/" 开始到这个A静态库文件的完整路径。
这个时候在编译就连接上了,用 otool -L 你的程序,就可以看到是不是完全静态编译进去了,如果是静态编译进去的。
你会看不到有什么输出,没有的都会输出,有一种@开头就是相对路径加载dylib(动态库),还有一种是绝对路径就是/xx/xxxx/xxx/???.dylib这种。
苹果是推荐开发人员用动态库dylib,而不是静态库链接的,它也是这么推崇实行的,所以,system.b、crt.0 这两个库,我们都链接不上(但是系统都自带,所以不能静态连接也可以),它就是逼大家尽量用动态库,点都不自由,但是用动态库很麻烦一点就是说,程序不好复制分发。