本文共 10536 字,大约阅读时间需要 35 分钟。
来源: or
这里简单整理下这本书的第五章:automatic makefiles with automake
本章的相关代码见:
makefile的功能(或许大致)可以划分为三部分:编译、测试、安装。
makefile可以纯手工构建,但是存在“进化”的空间。
autoconf的工作:为了完成跨平台的需求,根据实际安装环境,使用脚本替换makefile中的变量。
此时,makefile的生成工作能否再“进化”一些?
makefile描述了编译、测试、安装的过程。这个过程思路可能没法改进了,因为确实需要做这些事情。
但,由于GCS对于应如何构建和测试项目产品以及在何处构建,测试和安装相当明确。所以描述的方式可以简化。automake便是做了这件工作。同时,Automake为我们做了很多完善工作。
本章最基础重要的代码结构如下:
.├── common│ ├── jupcommon.h│ ├── Makefile.am│ └── print.c├── configure.ac├── Makefile.am└── src ├── main.c └── Makefile.am
在中,我们已经知道Makefile.am的作用。
automake:automake程序从高级构建规范文件(名为Makefile.am)生成标准的Makefile模板(名为Makefile.in)
configure:将从Makefile.in中生成makefile文件
为了在构建系统中启用Automake,我添加了一行代码configure.ac:在对AC_INIT和AC_CONFIG_SRCDIR的调用之间对AM_INIT_AUTOMAKE的调用。
...AC_INIT([Jupiter], [1.0], [jupiter-bugs@example.org])AM_INIT_AUTOMAKEAC_CONFIG_SRCDIR([src/main.c])...
AM_INIT_AUTOMAKE宏接受一个可选参数:用空格分隔的选项标签列表,可以将其传递到此宏中,以修改Automake的常规行为。 有关每个选项的详细说明,请参见GNU Automake手册。但是,我将在此处指出一些最有用的选项。
Automake Makefile.am文件只不过是带有其他特定于Automake语法的标准makefile。
autoconf和automake的区别在于:autoconf接受的输入是configure.ac中存在的shell脚本和M4宏,输出是shell脚本和M4宏的展开;Automake假定除了您指定的任何目标和变量之外,所有makefile都应包含旨在支持GCS的最小基础结构。
由于make实用程序使用一组相当严格的规则来处理makefile,Makefile.am中自行添加的makefile内容,将会和自动生成的makefile内容,以合理的方式处于同一个文件中。具体来说,如下:
Makefile.am文件中内容如下所示,后面会逐行分析其含义。
# 顶层的makefile.amSUBDIRS = common src
# 临时库所在目录的makefile.amnoinst_LIBRARIES = libjupcommon.alibjupcommon_a_SOURCES = jupcommon.h print.c
# 目标源代码所在目录的makefile.ambin_PROGRAMS = jupiterjupiter_SOURCES = main.c# jupiter_CPPFLAGS = -I$(top_srcdir)/commonjupiter_CPPFLAGS = -I../commonjupiter_LDADD = ../common/libjupcommon.acheck_SCRIPTS = greptest.shTESTS = $(check_SCRIPTS)greptest.sh: echo './jupiter | grep "Hello from .*jupiter!"' > greptest.sh chmod +x greptest.shCLEANFILES = greptest.sh
SUBDIRS = common src
这一行告诉Automake关于我们项目的几件事:
在目标源代码所在目录的makefile.am中,main.c是源码,jupiter是我们需要生成的product。
bin_PROGRAMS = jupiter
PLV(Product List Variables)名称由两个部分组成:prefix(eg, bin)和PRIMARY(eg, PROGRAMS),用下划线分隔。 该变量的值是此Makefile.am文件生成的product的空格分隔列表。
以下模板显示了PLV的常规格式:
[modifier-list]prefix_PRIMARY = product1 product2 ... productN
make变量中,以dir结尾的,符合GCS的位置,都可以作为安装位置,比如$(bindir)对应的位置。
通过省略变量名称的dir部分,可以在PLV前缀中引用安装位置变量。 例如,上面,$(bindir) 的make变量在用作安装位置前缀时称为bin。[bin前缀表示安装在make变量$(bindir)的位置。]
Automake还可以识别以特殊前缀pkg开头的四个安装位置变量:pkglibdir,pkgincludedir,pkgdatadir和pkglibexecdir。libdir,includedir,datadir和libexecdir变量的这些pkg版本表示应将列出的产品安装在以软件包命名的这些位置的子目录中。
举例说明:在Jupiter项目中,PLV中以lib开头的产品将被安装到$(libdir)中,而PLVlib中以pkglib开头的产品将被安装到$(libdir)/ jupiter中。
由于Automake从所有以dir结尾的make变量中获取有效安装位置和前缀的列表,因此您可以提供自己的PLV前缀,以引用自定义安装位置。
xmldir = $(datadir)/xmlxml_DATA = file1.xml file2.xml file3.xml ...
某些前缀与安装位置无关。 例如,分别使用noinst,check和EXTRA表示不安装,仅用于测试或可选地构建的产品。 以下是有关这三个前缀的更多信息:
上面介绍了PLV的prefixs。这里来介绍PLV的primaries。
primaries类似于产品类,它们表示可能由构建系统生成的产品类型。 一个primary定义了构建,测试,安装和执行特定类产品所需的一组步骤。 例如,使用不同的编译器和链接器命令构建程序和库,Java类需要虚拟机来执行它们,而Python程序需要解释器。 某些产品类(例如脚本,数据和标头)没有构建,测试或执行语义-仅具有安装语义。
全面了解Automake primaries是正确使用Automake的关键。 一些最重要的原语如下。
在目标源代码所在目录的makefile.am中,main.c是源码,jupiter是我们需要生成的product。
jupiter_SOURCES = main.c
PSV(Product Source Variables)符合以下模板:
[modifier-list]product_SOURCES = file1 file2 ... fileN
与PLV一样,PSV由多个部分组成:product和SOURCES标签。 PSV的值是用空格分隔的用于生成product的源文件列表。 最终,Automake将这些文件添加到生成的Makefile.in模板中的各种make规则依赖项列表和命令中。
product只可以是字母、数字、@符号。如果出现其他符号,automake会将其装换为下划线。
修饰符(modifier)可更改其前缀的变量的正常行为。 一些更重要的是dist,nodist,nobase和notrans。
check_SCRIPTS = greptest.shTESTS = $(check_SCRIPTS)greptest.sh: echo './jupiter | grep "Hello from .*jupiter!"' > greptest.sh chmod +x greptest.shCLEANFILES = greptest.sh
便捷库是仅在包含项目中使用的静态库。当项目中的多个二进制文件需要合并相同的源代码时,通常使用此类临时库。[因而此类库也不在打包范围内。]
这里是便捷库的Makefile.am。
noinst_LIBRARIES = libjupcommon.alibjupcommon_a_SOURCES = jupcommon.h print.c
源码所使用的Makefile.am也需要添加相应的内容,以使在编译的时候链接到该库。
jupiter_CPPFLAGS = -I../commonjupiter_LDADD = ../common/libjupcommon.a
jupiter_CPPFLAGS和jupiter_LDADD这两个新变量是从程序名称派生的。
这些 product option variables(POV)用于为用于从源代码构建产品的工具指定特定于产品的选项。[jupiter_SOURCES中的SOURCES表示源,不是选项的意思]
您可以在GNU Autoconf手册中找到程序和库option variables的完整列表,但这是一些重要的变量。
最后,需要在configure.ac中添加AC_PROG_RANLIB
宏。
为什么添加这个宏,书上给了如下解释。我不理解,暂时跳过。
There’s a lot of history behind the use of the ranlib utility on archive libraries. I won’t get into whether it’s still useful with respect to modern development tools, but I will say that whenever you see it used in modern makefiles, there always seems to be a preceding comment about running ranlib “in order to add karma” to the archive, implying that the use of ranlib is somehow unnecessary. You be the judge.
Automake通常会自动确定应使用make dist创建的发行版中应包含的内容,因为它非常了解构建过程中每个文件的角色。 为此,Automake希望被告知用于构建产品的每个源文件以及安装的每个文件和产品。 当然,这意味着所有文件都必须在一个或多个PLV和PSV变量中指定。
automake不会自动添加的内容,而我们希望天剑,可以使用EXTRA_DIST的方式手动添加。
# 将本不会自动添加的windows目录,添加大Distribution中EXTRA_DIST = windows
先创建一些必要的文件,否则autoreconf会提示缺少文件。
至于这些文件的含义,该书将其放在后续章节介绍,这里就暂时不理会这些文件的作用。
# autoreconf,提示文件没有发现。Makefile.am: error: required file './NEWS' not foundMakefile.am: error: required file './README' not foundMakefile.am: error: required file './AUTHORS' not foundMakefile.am: error: required file './ChangeLog' not found# 创建必要的文件➜ touch NEWS README AUTHORS ChangeLog
我们使用-i选项运行autoreconf以便添加Automake可能需要用于我们项目的任何新实用工具文件
➜ autoreconf -i\➜ tree -L 1.├── aclocal.m4├── AUTHORS├── autom4te.cache├── ChangeLog├── common├── compile├── config.h.in├── configure├── configure.ac├── COPYING├── depcomp├── INSTALL├── install-sh├── Makefile.am├── Makefile.in├── missing├── NEWS├── README├── src└── test-driver
接着是常见的三步走。
./configure --enable-silent-rulesmake# make install
其中./configure --enable-silent-rules
是静默规则,默认是禁用的。[更多]
如果想打包,make dist
就成。
总的来说,我开始有点喜欢automake了。
在PLV中:指定需要处理的文件类型和处理之后的安装位置 = product。
在PLS中:product_SOURCES = 源码位置
在POV中:product_选项 = 选项内容,表示从源码编译生成product所需要的参数。
转载地址:http://thta.baihongyu.com/