首页 存档 技术 查看内容

通俗易懂理解GNULibtool

2018-3-30 13:00 |来自: 互联网 311 0

摘要: 来源:garfileo原文地址:https://segmentfault.com/a/1190000004000043 这篇文章与『理解 GLib 的单元测试框架(http://segmentfault.com/a/1190000003996312)』一文有些渊源,因为后者在几个示例中使用了 libtool ...

来源:garfileo
原文地址:https://segmentfault.com/a/1190000004000043
这篇文章与『理解 GLib 的单元测试框架(http://segmentfault.com/a/1190000003996312)』一文有些渊源,因为后者在几个示例中使用了 libtool 产生库文件与应用程序文件。
田园时代

我要写一个叫做 foo 的库,它提供一个什么也不做的函数。这个库的头文件为 foo.h:


#ifndef FOO_H #define FOO_H void foo(void); #endif

foo.c 是这个库的实现:


#include "foo.h" void foo(void) { }

用 gcc 编译生成共享库文件 libfoo.so:


$ gcc -shared -fPIC foo.c -o libfoo.so

如果用 clang,可以这样:


$ clang -shared -fPIC foo.c -o libfoo.so

如果是在 Windows 环境中(例如 mingw 或 cygwin 之类的环境),可以这样:


$ gcc -shared -fPIC foo.c -o libfoo.dll

于是,问题就出现了……如果我想让 foo 库能够跨平台运行,那么我就不得不为每一个特定的平台提供相应的编译命令或脚本。这意味着,你必须知道各个平台在共享库支持方面的差异及处理方式。这通常是很烦琐很无趣的事,何况我还没说构建静态库的事。

这时候,一个 10000 多行的 Bash Shell 脚本 libtool 站了出来,这些破事,我来做!

消除环境差异的方法

要有效的消除各个环境差异性,往往有三种办法。

第一种办法是**……不要害怕,不是革程序猿的命,而是革环境的命。譬如 Windows(我更愿意是 Linux)扫清寰宇,一统天下,那么环境的差异性也就不存在了。但是,人类的历史已经证明了这条路是走不通的。因为,一旦某个环境绝对的统治了一切,那么它下一步要面对的问题就是自身的**……整部中国历史记录的都是这种事!

第二种办法是改良……有一批人仁志士成立了某个团体,颁布了一些标准,并号召大家都遵守这个标准,别再自行其是。C 语言标准,C 标准,scheme 标准……都挺成功的。现在似乎还没有共享库或动态链接库标准。

第三种办法是和谐不要害怕,这里没有 GFW就是承认现实就是这么个狗血的现实,然后追求和而不同

libtool 选择了第三种办法。

libtool 的『和』

gcc 编译生成共享库的命令可以粗略的拆分为两步编译与连接:


$ gcc -fPIC foo.c -o libfoo.o #编译 $ gcc -shared libfoo.o -o libfoo.so #连接

与之相应,libtool 说,如果你要用 gcc 编译生成一个共享库,不管它是在 Linux 里,还是在 Solaris,还是在 Mac OS X 里,或者是在 Windows 里(Cygwin 或 MinGW),可以使用同样的命令:


$ libtool --tag=CC --mode=compile gcc -c foo.c -o libfoo.lo # 编译 $ libtool --tag=CC --mode=link gcc libfoo.lo -rpath /usr/local/lib -o libfoo.la # 连接

似乎 libtool 把问题弄得更复杂了!不过,仔细观察一下,可以发现一些规律。比如这两个命令的前面一半都是:


$ libtool --tag=CC --mode=

--tag 选项用于告诉 libtool 要编译的库是用什么语言写的,CC 表示 C 语言。libtool 目前支持以下语言:


语言 Tag 名称 --------------------------- C CC C CXX Java GCJ Fortran 77 F77 Fortran FC Go GO Windows Resource RC ---------------------------

--mode 选项用于设定 libtool 的工作模式。上面的例子中,--mode=compile 就是告诉 libtool 要做的工作是编译,而 --mode=link 就是连接。

libtool 支持 7 种模式,除了上述两种模式之外,还有执行、安装、完成、卸载、清理等模式。每个模式都对应于库的某个开发阶段。这 7 种模式抽象了大部分平台上的库的开发过程。这是 libtool 和而不同的第一步:库开发过程的抽象

下面来看编译过程,当 libtool 的 --mode 选项设为 compile 时,那么随后便是具体的编译命令,本例中是 gcc -c foo.c -o libfoo.lo。这条 gcc 编译命令,会被 libtool --tag=CC --mode=compile 变换为:


$ gcc -c foo.c -fPIC -DPIC -o .libs/libfoo.o $ gcc -c foo.c -o libfoo.o

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部