gnutool2. GNU Package 的典型安装 FAQ 0039 @ smth 下载源代码包 foo-1.0.tar.gz tar xvzf foo-1.0.tar.gz cd foo-1.0 ./configure make (su) make install 问题 1 :配置脚本 configure 是怎么生成的? 问题 2 : configure 脚本怎么知道该如何生成 Makefile 幕后英雄—— GNU Auto Tools : autoconf, automake, libtool, autoscan, autoheader…… 3. Makefile’s way to develop 三元组 (Target, Dependency, Command) Target : Dep1 Dep2 <TAB>Cmd1 <TAB>Cmd2 [Blank Line] .s1 .s2 : <TAB>Cmd1 $(var), $<, $@ …… 4. Makefile’s Big Trouble? GNU 的 Makefile 规范相当复杂,随着项目复杂性的增加,要写出一个正确而高效的 Makefile 相当困难,对新手而言更是如此。 越是复杂的软件越有可能有自己独特的 build 方法,怎么办?每次都重新学习?! 不同的类 Unix 操作系统之间存在着差异,移植性如何保证?需要大量手工编写的脚本和条件编译。 5. All in One Solution? GNU Auto Tools 是上个世纪 90 年代开始发展起来的一系列辅助开发、打安装包的自动化工具。 各种工具分别开发,但是协同工作的很好。比如 autoconf, automake, libtool 等等。 但是,连开发者自己也承认,这套工具虽然好用,但是学习曲线很陡峭。 困难在于:一套新的思路和习惯,一套自定义的宏和规则,使用者的交流 ? 6. Hello World – Step by Step 1. hello.c #include <stdio.h> int main() { printf(“Hello World!”); return 0; } 2. Makefile.am bin_PROGRAMS = hello hello_SOURCES = hello.c 3. configure.in AC_INIT(hello.c) AM_INIT_AUTOMAKE(hello, 0.1) AC_PROG_CC AC_OUTPUT(Makefile) 4. aclocal 5. autoconf 6. automake --add-missing --foreign 7. ./configure 8. make (make install 安装, make dist 产生安装包 ) 9. configure.in(1) 是 configure 脚本的输入文件,为了解决在不同 unix 变种之间移植程序的问题:库名可能不同,应用程序名可能不同,结构和常量的定义可能不同…… configure 脚本完成 autoconf 与 automake 的初始化工作,为不同的平台定义相应的宏,检测并指定适当的程序名、库名、结构和常量名等等,指定要为哪些目录输出 Makefile 文件。总之,为编译程序做好一切准备工作。 11. configure.in(3) 检查某些头文件是否存在。 检查 Typedefs and structures 。 检查 Functions 。 指定在哪些目录输出 Makefile 。 Seems troublesome, mmm? Don’t worry, autoscan will do most of the work for you. 12. Makefile.am(1) 一种比 Makefile 更高层次的规则。只指定要生成什么目标,它由什么源文件生成,要安装到什么目录。 Just simple and stupid! ? 可执行文件: bin_PROGRAMS = foo foo_SOURCES = foo1.c foo1.h foo2.c foo_LDADD = foo3.o -lm foo4.a foo_LDFLAGS = -L<lib_path> foo_DEPENDENCIES = 13. Makefile.am(2) 对静态库: lib_LIBRARIES = libfoo.a foo_a_SOURCES = foo_a_LDADD = foo_a_LIBADD = foo_a_LDFLAGS = 只在 make 时做静态连接用,不安装的库: noinst_LIBRARIES = libfoo.a …… 对头文件: include_HEADERS = foo.h 对数据文件: data_DATA = data1 data2 14. Makefile.am(3) 全局变量 ( 对所有目标都适用 ) INCLUDES = -I/dir1 -I/dir2 LDFLAGS = -L/dir1 -L/dir2 LDADD = foo.o foo.a -lfoo EXTRA_DIST = file1 file2 源程序和一些默认的文件自动打入 .tar.gz 包,其它文件若要进入 .tar.gz 包可以用这种办法,比如配置文件 , 数据文件等等 。 SUBDIRS = dir1 dir2 在处理本目录之前要递归处理哪些子目录 15. Makefile.am(4) 标准安装路径 $(prefix) = /usr/local 是所有安装目录的默认前缀,可以通过 ./configure --prefix=<new_prefix> 的方法覆盖。 其它的预定义目录如: bindir = $(prefix)/bin, libdir = $(prefix)/lib, datadir = $(prefix)/share, sysconfdir = $(prefix)/etc, … 想定义一个新的安装路径?比如 config, 可定义 confdir = $(prefix)/config, 然后 conf_DATA = file1 file2 ,则 file1, file2 会作为数据文件安装到 $(prefix)/config 目录下。 17. configure’s Gifts configure 脚本生成的 Makefile 中已经带了很多常用的目标如: check, all, install, uninstall, clean, dist, distcheck, distclean, tags, maintainerclean. If configure or make did it, make distclean undoes it. If make did it, make clean undoes it. If make install did it, make uninstall undoes it. If you did it, make maintainer-clean undoes it. 19. libtool 介绍 生成各种程序库的方便工具。 提供一个统一的接口,程序员不用关心各种烦人的底层细节:不同的平台的库可能要求不同的后缀,不同平台对库的安装方法不同,有些平台不支持动态库等等。 生成高层次的库,称为 libtool library ,后缀是 .la 。用它连接时,默认产生动态连接库,也可以用 -static 参数指定生成静态连接库。 既可单独使用又可与 automake 和 autoconf 一起使用更加强大、方便。 20. 使用 libtool 在 configure.in 文件中加上 AC_PROG_LIBTOOL 宏,如果原来有 AC_PROG_RANLIB 宏,删去它。 在 Makefile.am 文件中: lib_LTLIBRARIES = libshell.la libshell_la_SOURCES = object.c subr.c symbol.c 与原来的写法非常相似! .la 库只能连入 .lo( 使用 libtool 生成的目标文件 ) libshell_la_LDADD = xmalloc.lo @LTLIBOBJS@ 传入库的版本号: libshell_la_LDFLAGS = -version-info 1:0:1 与其它目标文件连接时用 LDFLAGS 指定连接的方式 ( 默认是动态方式): -static, --all-static 指定静态连接。 21. 小结 Autoconf :根据用户提供的 configure.in 文件,生成一个名为 configure 的脚本。该脚本可以搜集有关移植性的平台相关信息,这些信息被用来生成 Makefiles ,配置头文件和其它平台相关的文件。 Automake :根据用户提供的一个高层次的生成规则 Makefile.am ,生成 Makefile 文件的模板 Makefile.in 。 Automake 生成的 Makefiles 符合 GNU 的 Makefile 标准,用户无需再手工编写 Makefile 文件。 Libtool :使得生成内存位置无关的代码且让共享库在不同平台间移成为可能。它可以不依赖 autoconf 和 automake 单独运行,另一方面, automake 和 libtool 可以无缝地集成使用。