分类:
2008-08-11 22:22:06
u#title
不同的automake,autoconf,autoscan之间存在着一定的不兼容性。这里推荐 autoscan 2.59和 automake 1.9配合使用。如果你是debian或者ubuntu,那么可你可以简单按照下面的方式安装
apt-get install autoconf apt-get remove automake1.4 apt-get install automake1.9
现在google Makefile 和 automake就能找到一些文章。以一个Hello 程序描述为一个project生成Makefile的过程。
这个例子其实在 Info automake 里能看到。大家把它翻成中文的,不错。
但实际上按照这个例子来做的话,步骤都对,就是太简单,一些常用的设置需要写进去,但是没有提到,还是要自己info, google, try.
AM_INIT_AUTOMAKE(myprojectname , version) AC_OUTPUT( 最后要生成的Makefile , 包括 子目录中的,中间用空格隔开) , 例如 AC_OUTPUT(Makefile subdir/Makefile subdir1/Makefile) AC_PROG_RANLIB (意义见第四条末尾)
最上层的要写明
AUTOMAKE_OPTIONS = foreign
如果这个目录没有要编译的文件 ,只包含了子目录,则只写个
SUBDIRS = dir1
就ok了。
例如我的工程,最上层只是包含了源码目录,于是就写了
AUTOMAKE_OPTIONS=foreign SUBDIRS=src
如果有文件要编译,则要指明target 先。比如我的src目录底下既有文件,又有目录,而src的这层目录中的文件最后是要编译成一个可执行文件,则src目录下的Makefile.am这么写。
bin_PROGRAMS= myprogram SUBDIRS= sub1 myprogram_SOURCES= \ a.cpp\ b.cpp\ # 要编译的源文件。这儿的_SOURCES是关键字 EXTRA_DIST= \ a.h \ b.h # 不用编成.o,但生成target myprogram也需要给编译器处理的头文件放这里 myprogram_LDADD = libsub1.a 这个_LDADD是关键字, # 最后生成myprogram这个执行文件,还要link src/sub1这个目录中的内容编成的一个lib :libsub1.a, myprogram_LDFLAGS = -lpthread -lglib-2.0 -L/usr/bin $(all_libraries) # myprogram还要link系统中的动态so,以此类推,需要连自编译的so,也写到这个关键字 _LDFLAGS后面就好了。 AM_CXXFLAGS = -D_LINUX # 传递给g++编译器的一些编译宏定义,选项, INCLUDES=-IPassport -Isub1/ -I/usr/include/glib-2.0\ -I/usr/lib/glib-2.0/include $(all_includes) # 传递给编译器的头文件路径。
下面是sub1种生成lib的Makefile.am
noinst_LIBRARIES = libprotocol.a # 不是生成可执行文件,而是静态库,target用noinst_LIBRARIES libprotocol_a_SOURCES = \ alib.cpp EXTRA_DIST = mylib.h\ alib.h INCLUDES= -I../ $(all_includes) AM_CXXFLAGS = -D_LINUX -DONLY_EPOLL -D_SERVER
ok ,最后补上AC_PROG_RANLIB涵义,如果要自己生成lib,然后link到最终的可执行文件中,则要加上这个宏,否则不用。
[讨论] 每个目录至少都要有一个target,或者是可执行文件或者是lib,似乎对目录的划分带来点局限。
比如我的目录结构如果是这样
./Src ./Src/sub1 ./Src/sub2
而我想这样,sub1,sub2都没有target,目录划分只是为了区别代码的不同模块,然后把两个目录中编译出的中间文件一起link ,得到最后需要的 myprogram 。
似乎在Src/Makefile.am中要这么写
myprogram_SOURCES = sub1/a.cpp \ sub2/b.cpp
可以实现,但我没试,:P
当然和设成先编译出libsub1.a libsub2.a 最后Link得到myprogram 没有本质区别了。
Ok , Makefile.in应该放到各个目录下了。
软件版本间的不兼容总是会带来不少麻烦。
首先我对比了网上的一些文章和gnu的autoconf文档,发现差别很大,新版本和老版本有很多不同,当然大部分特性新版本还是兼容老版本的,令人郁闷的是automake的文档中对configure.in的描述还是针对autoconf老版本的。
软件版本: autoscan 2.59 automake 1.9.5 参考文档: automake 1.7.8 doc autoconf 2.59 doc
cd ~/src mkdir hello 编辑文件hello.c
不予理会,生成了文件configure.scan
cp configure.scan configure.ac
修改configure.ac的内容如下:
# -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) AC_INIT(hello, 1.0, beyondwdq@gmail.com) AC_CONFIG_SRCDIR([configure.ac]) AM_INIT_AUTOMAKE(hello,1.0) AC_CONFIG_HEADER([config.h]) # Checks for programs. AC_PROG_CC # Checks for libraries. # Checks for header files. # Checks for typedefs, structures, and compiler characteristics. # Checks for library functions. AC_CONFIG_FILES([Makefile]) AC_OUTPUT
这里说明一下的是,老版本的autotools使用configure.in作为输入,后来新版本改为configure.ac,但configure.in也可以。
bin_PROGRAMS = hello hello_SOURCES = hello.c
touch README NEWS AUTHORS ChangeLog 建立这些文件
2.aclocal (automake):根据已经安装的宏,用户定义宏和acinclude.m4文件中的宏将configure.ac文件所需要的宏集中定义到文件 aclocal.m4中。aclocal是一个perl 脚本程序,它的定义是:“aclocal - create aclocal.m4 by scanning configure.ac”
user input files optional input process output files ================ ============== ======= ============ acinclude.m4 - - - - -. V .-------, configure.in ------------------------>|aclocal| {user macro files} ->| |------> aclocal.m4 `-------' 3.autoheader(autoconf): 根据configure.ac中的某些宏,比如cpp宏定义,运行m4,声称config.h.in user input files optional input process output files ================ ============== ======= ============ aclocal.m4 - - - - - - - . (acconfig.h) - - - -. | V V .----------, configure.in ----------------------->|autoheader|----> config.h.in `----------'
4.automake: automake将Makefile.am中定义的结构建立Makefile.in,然后configure脚本将生成的Makefile.in文件转换为Makefile。如果在configure.ac中定义了一些特殊的宏,比如AC_PROG_LIBTOOL,它会调用libtoolize,否则它会自己产生config.guess和config.sub
user input files optional input processes output files ================ ============== ========= ============ .--------, | | - - -> COPYING | | - - -> INSTALL | |------> install-sh | |------> missing |automake|------> mkinstalldirs configure.in ----------------------->| | Makefile.am ----------------------->| |------> Makefile.in | |------> stamp-h.in .---+ | - - -> config.guess | | | - - -> config.sub | `------+-' | | - - - -> config.guess |libtoolize| - - - -> config.sub | |--------> ltmain.sh | |--------> ltconfig `----------'
5.autoconf:将configure.ac中的宏展开,生成configure脚本。这个过程可能要用到aclocal.m4中定义的宏。
user input files optional input processes output files ================ ============== ========= ============ aclocal.m4 - - - - - -. V .--------, configure.in ----------------------->|autoconf|------> configure `--------'
References:
INCLUDES = -I/include LIBS = -lm -lcrypt
autoconf 是用来生成自动配置软件源代码脚本(configure)的工具。configure 脚本独立于 autoconf 运行,而且在运行的过程中,不需要用户的干预,通常不需要附带参数。它是用来检验软件必须的参数的。autoconf 从一个列举编译软件时所需要各种参数的模板文件中创建 configure。autoconf 需要 GNU m4 来生成该脚本。
由 autoconf 生成的脚本一般起名为 configure。当运行时,configure 创建了多个文件,并对这些文件中的配置参数赋予适当的值。由 configure 创建生成的文件有:
为了让 autoconf 生成 configure 脚本,需要以 configure.in 为参数调用 autoconf。如果要检测自己的各种参数,以作为对 autoconf 的补充,则需要写 aclocal.m4 和 acsite.m4 的文件。如果要使用 C 头文件,需要写 acconfig.h,并且将 autoconf 生成的 config.h.in 同软件一起发行。
your source files --> [autoscan*] --> [configure.scan] --> configure.in configure.in --. .------> autoconf* -----> configure +---+ [aclocal.m4] --+ `---. [acsite.m4] ---' | +--> [autoheader*] -> [config.h.in] [acconfig.h] ----. | +-----' [config.h.top] --+ [config.h.bot] --' Makefile.in -------------------------------> Makefile.in Files used in configuring a software package: .-------------> config.cache configure* ------------+-------------> config.log | [config.h.in] -. v .-> [config.h] -. +--> config.status* -+ +--> make* Makefile.in ---' `-> Makefile ---'
编辑 configure.in 文件:
configure.in 文件中包含了对 autoconf 宏的调用,这些宏是用来检测软件所必须的各项参数的。为了能够得到 configure.in 文件,需要使用 autoscan。 configure.in 文件中,在进行各项检测前,必须在最开始调用 AC_INIT,在最后调用 AC_OUTPUT。另外有些宏由于检测的关系是和在文件中的位置相关的。最好每一个宏占用一行。
使用 autoscan 创建 configure.in 文件
可以将目录做为参数调用 autoscan,如果不使用参数的化,则认为是当前目录。 autoscan 将检查指定目录中的源文件,并创建 configure.scan 文件。在将 configure.scan 改名为 configure.in 文件前,需要手工改动它以进行调整。
使用 autoconf 创建 configure 脚本
不带任何参数的运行 autoconf。autoconf 将使用 m4 宏处理器和 autoconf 宏,来处理处理 configure.in 中的宏。
configure.in 中的宏:
AC_INIT(在源代码中唯一的一个文件):configure 将检查该文件是否存在,并检查包含它的目录是否存在。 AC_OUTPUT(文件):指定创建的输出文件。在 configure.in 文件中调用一次。文件名间用空格分开。比如:AC_OUTPUT(Makefile:templates/top.mk lib/Makefile:templates/lib.mk)
在 configure.in 中,有一些被 autoconf 宏预先定义的变量,重要的有如下几个:
bindir:安装可执行文件的目录。 includedir:C 头文件目录。 infodir:info 页安装目录。 mandir:安装手册页的目录。 sbindir:为管理员运行该该程序提供的安装路径。 srcdir:为 Makefile 提供的源代码路径。 top_srcdir:源代码的最上层目录。 LIBS:给连接程序的 -l 选项 LDFLAGS:给连接程序的 stripping(-s)和其他一些选项。 DEFS:给 C 编译器的 -D 选项。 CFLAGS:给 C 编译器的 debug 和优化选项。当调用了 AC_PROG_CC 才有效。 CPPFLAGS:头文件搜索路径(-I)和给 C 预处理器和编译器的其他选项。 CXXFLAGS:给 C++ 编译器的 debug 和优化选项。当调用了 AC_PROG_CXX 才有效。
如果在同一个目录下编译多个程序的话,使用 AC_CONFIG_SUBDIRS 宏,它的语法是:
AC_CONFIG_SUBDIRS(DIR....):
其他重要的宏:
AC_PROG_CC:选择 C 编译器。如果在环境中不设置 CC 的话,则检测 gcc。 AC_PROG_CXX:选择 C++ 编译器。
一般操作 Automake 工作时,读取一个叫'Makefile.am'的文件,并生成一个'Makefile.in'文件。Makefile.am中定义的宏和目标,会指导 automake生成指定的代码。例如,宏'bin_PROGRAMS'将导致编译和连接的目标被生成。 Makefile.am中包含的目标和定义的宏被拷贝到生成的文件中去,这允许你添加任意代码到生成的Makefile.in文件中去。例如,使一个Automake发布中包含一个非标准的dvs-dist目标,Automake的维护者用它来从它的源码控制系统制作一个发布。 请注意,GNU生成的扩展名不被Automake所识别,在一个'Makefile.am'中使用这样一个扩展名会导致错误。 Automake试图以一种聪明的方式将相邻的目标(或变量定义)注释重组。 通常,Makefile.am中定义的目标会覆盖任何由automake自动生成的有相似名字的这样的目标。尽管这是种被支持的属性,但最好避免这么做,因为有些时候,生成的规则很严格。 类似的,Makefile.am中定义的变量会覆盖任何由automake自动生成的变量定义。这一特性经常要比目标定义的覆盖能力更常用。请注意,很多automake生成的变量只用于内部使用,在将来发布时他们的名字可能会变化。 当测试一个变量定义时,Automake降递归的测试在定义中引用的变量。例如,如果Automake看到这段snippet程序中的'foo_SOURCES': xs = a.c b.c foo_SOURCES = c.c $(xs) 它将使用文件:'a.c','b.c'和'c.c' 作为foo_SOURCES的内容. Automake 也允许不被拷贝到输出的注释形式,所有以'##'开头的行将被Automake 完全忽略. 深度 Automake 支持三种目录层次:'flat', 'shallow', 'deep'. flat: 所有的文件都在一个目录中. 相应的Makefile.am中缺少SUBDIRS宏. termutils 是一个例子. deep: 所有的资源都在子目录中,指定曾目录主要包含配置信息.GNU cpio 是一个很好的例子.GNU tar.相应的最顶层Makefile.am中将包含一个SUBDIR宏,但没有其他的宏来定义要创建的对象. shallow: 主资源存在于最顶层目录,而不同的部分(典型的,库函数)在子目录中.Automake 就是这样的一个包. 严格性 当Automake 被GNU包维护者使用时,它的确努力去适应,但不要试图使用所有的GNU惯例. 目前,Automake 支持三种严格性标准: foreign:Automake 将只检查绝对必须的东西. gnu:Automake 将尽可能多的检查以适应GNU标准, 这是默认项. gnits:Automake 将进行检查,以适应“尚未成文”的Gnits标准。 他们基于GNU标准,但更详尽。除非您是Gnits标准的制定者。建议您最好避免这个选项,指导该标准正式发布。 统一命名规范 Automake变量一般遵循一套统一的命名规范以很容易的决定如何创建和安装程序(和其他派生对象)。给规范还支持configure时动态决定创建规则。 在make时,一些变量被用于决定那些对象要被创建。写变量叫做primary variables。例如,PROGRAM变量包括一个要被编译和连接的程序列表。 另一个变量集用于决定被创建变量被安装到哪里。这些变量以相应的主变量命名,但加一个前缀,表示那些标准目录应被用作安装路径。这些标准目录的名称规定在GNU标准中。Automake用pkglibdir, pkgincludedir 和 pkgdatadir来展开这一列表。他们和没有pkg前缀的版本一样,只不过有‘@PACHAGE@’扩展,PKGLIBDIR被定义为 $(DATADIR)/@PACKAGE@. 对每一个主变量,有一个EXTRA_前缀的变量。这个变量用于列出所有对象,至于哪些变量被创建,哪些变量不被创建则取决于 configure。之所以需要这个变量,是因为Automake必须静态的指导要创建对象的完整列表以便生成一个‘Makefile。in’文件。 例如,cpio 在configure时决定创建那些程序。一些程序被安装在bindir,一些被安装在sbindir: EXTRA_PROGRAMS = mt rmt bin_PROGRAMS = cpoi pax sbin_PRGRAMS = @PROGRAMS@ 定义没有前缀的主变量是错误的(如:PROGRAMS)。值得注意的是,“dir”在作为构成变量名时会被忽略。一次,我们写成bin_PROGRAMS 而不是bindir_PROGRAMS. 不是每一种对象都得以安装在每个目录下。Automake 将标记那些他认为是错误的尝试,他也能够诊断一些明显的目录名拼写错误。 有时标准目录--被Automake使用的--不过用。特别的,有时为了清晰,将对象安装在一些预定义的子目录,是很有用的。 Automake允许你增加安装目录。如果以一个变量名(如,zar)加上dir的另一个变量(如,zardir)被定义了,那么他也是合法的。 例如,如果HTML没支持Automake的一下部分,你就可以用他来安装HTML源文件: htmldir = $(prefix)/html html_DATA = automake.html “noinst”前缀专门指定有问题的对象不被安装。 “check”前缀表示有问题的对象知道make check命令被执行猜被创建。 可用的主变量是 'PROGRAMS','LIBRARIES','LISP','SCRIPTS','DATA','HEADERS','MANS'和'TEXINFOS' 导出变量是如何命名的 有时一个Makefile变量名有一些用户支持的文本导出。例如程序名被重写进Makefile宏名称。Automake读取这些文本,所以他不必遵循命名规则。当生成后引用时名称中的字符除了字母,数字,下划线夺回被转换为下划线。例如,如果你的程序里有sniff-glue,则导出变量名将会是sniff_glue_SOURCES,而不是sniff-glue_SOURCES. 一些例子 一个完整简单的例子 假设你写了一个名为zardoz的程序。 第一步,更新你的configure.in文件以包含automake所需的命令。最简单的办法就是在AC_INIT后加一个AM_INIT_AUTOMAKE调用: AM_INIT_AUTOMAKE(zardoz, 1.0) 如果你的程序没有任何复杂的因素。这是最简单的办法。 现在,你必须重建‘configure’文件。这样做,你必须告诉autoconf如何找到你所用的新宏。最简单的方式是使用 aclocal程序来 生成你的‘aclocal.m4’.aclocal让你将你的宏加进‘acincluide.m4’,所以你只需重命名并运行他 mv aclocal.m4 acinclude.m4 aclocal autoconf 现在是为你的zardoz写Makefile.am的时候了。zardoz是一个用户程序,所以逆向将他安装在其他用户程序安装的目录。zardoz还有一些Texinfo文档。你的configure.in脚本使用AC_REPLACE_FUNCS,所以你需要链接‘@LIBOBJS@’ bin_PROGRAMS = zardoz zardoz_SOURCES = main.c head.c float.c vortex9.c gun.c zardoz_LDADD = @LIBOBJS@ info_TEXINFOS = zardoz.texi 现在你可以运行Automake以生成你的Makefile.in文件。 一个经典的程序 hello 以其简单和多面幸而闻名。着一段将显示在Hello包Automake如何被使用。 下面是 dnl用 autoconf 处理它以产生一个 configure 脚本. AC_INIT(src/hello.c) AM_INIT_AUTOMAKE(hello, 1.3.11) AM_CONFIG_HEADER(config.h) dnl Set of available languages ALL_LINGUAS="de fr es ko nl no pl pt sl sv" dnl Checks for programs. AC_PROG_CC AC_ISC_POSIX dnl Checks for libraries. dnl Checks for header files. AC_STDC_HEADERS AC_HAVE_HEADERS(string.h fcntl.h sys/file.h sys/param.h) dnl Checks for library functions. AC_FUNC_ALLOCA dnl Check for st_blksize in struct stat AC_ST_BLKSIZE dnl internationalization macros AM_GNU_GETTEXT AC_OUTPUT([Makefile doc/Makefile intl/Makefile po/Makefile.in \ src/Makefile tests/Makefile tests/hello], [chmod +x tests/hello]) 'AM_'宏由Automake(或Gettext 库)提供;其余的是Autoconf标准宏。 top-level ‘Makefile.am’: EXTRA_DIST = BUGS ChangeLog.O SUBDIRS = doc intl po src tests --如你所见,这里所有的工作时在子目录中真正完成的. --'po' 和 'intl'目录是用 gettextize自动生成的,这里不做进一步讨论. 在'doc/Makefile.am'文件中我们看到: info_TEXINFOS = hello.texi hello_TEXINFOS = gpl.texi --这已足以创建,安装和发布手册. 这里是'tests/Makefile.am'文件: TESTS = hello EXTRA_DIST = hello.in testdata --脚本'hello'被configure创建,并且是唯一的测试.make check将运行它. 最后是,'src/Makefile.am',所有的真正的工作是在这里完成的: bin_PROGRAMS = hello hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h hello_LDADD = @INTLLIBS@ @ALLOCA@ localedir = $(datadir)/locale INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" 创建一个'Makefile.in'文件 要为一个包创建所有的'Makefile.in',在顶层目录运行automake不带参数的程序.automake将自动查找每个适当的'Makefile.am'文件,并声称相应的'Makefile.in'文件.请注意,automake会简要的察看一下包的构成;它假定一个包在顶层只有一个'configure.in'文件.如果你的包有多个'configure.in'文件,那么你必须在每一个含有 'configure.in'文件的目录运行一次'automake'程序. 你可以随意送给automake一个参数;'.am'会加到变量名的后面,并且作为输入文件的文件名.这一特性通常被用来自动重建一个'过时的''Makefile.in'文件.注意,automake必须在最顶级%B