make 命令来编译自己写的程序确实是很方便。一般情况下,大家都是手工写一个简单
Makefile ,如果要想写出一个符合自由软件惯例的 Makefile 就不那么容易了。
一、Makefile 介绍
Makefile 是用于自动编译和链接的,一个工程有很多文件组成,每一个文件的改变都会导
致工程的重新链接,但是不是所有的文件都需要重新编译,Makefile 中纪录有文件的信息,
在 make 时会决定在链接的时候需要重新编译哪些文件。
Makefile 的宗旨就是:让编译器知道要编译一个文件需要依赖其他的哪些文件。当那些依赖
文件有了改变,编译器会自动的发现最终的生成文件已经过时,而重新编译相应的模块。
二、使用的环境
本文所提到的程序是基于 Linux 发行版本:Fedora Core release 1 ,它包含了我们要用到的
autoconf ,automake 。
三、从 helloworld 入手
我们从大家最常使用的例子程序 helloworld 开始。
下面的过程如果简单地说来就是新建三个文件:
helloworld.c
configure.in
Makefile.am
然后执行:
aclocal; autoconf; automake --add-missing; ./configure; make; ./helloworld
就可以看到 Makefile 被产生出来,而且可以将 helloworld.c 编译通过。
很简单吧,几条命令就可以做出一个符合惯例的 Makefile ,感觉如何呀。
现在开始介绍详细的过程:
1 、建目录
在你的工作目录下建一个 helloworld 目录,我们用它来存放 helloworld 程序及相关文件,
如在/home/my/build 下:
$ mkdir helloword
$ cd helloworld
2 、 helloworld.c
然后用你自己最喜欢的编辑器写一个 hellowrold.c 文件,如命令:vi helloworld.c 。使用下面
的代码作为 helloworld.c 的内容。
完成后保存退出。
3 、生成 configure
我们使用 autoscan 命令来帮助我们根据目录下的源代码生成一个 configure.in 的模板文件。
$ autoscan
$ ls
configure.scan helloworld.c
执 行 后 在 hellowrold 目 录 下 会 生 成 一 个 文 件 : configure.scan , 我 们 可 以 拿 它 作 为
configure.in 的蓝本。
AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld, 1.0)
m4 是一个宏处理器。将输入拷贝到输出,同时将宏展开。宏可以是内嵌的,也可以是用户
定义的。除了可以展开宏,m4 还有一些内建的函数,用来引用文件,执行命令,整数运算,
文本操作,循环等。m4 既可以作为编译器的前端,也可以单独作为一个宏处理器。
4 、新建 Makefile.am
$ vi Makefile.am
内容如下:
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=helloworld
helloworld_SOURCES=helloworld.c
Makefile.am 中 定 义 的 宏 和 目 标 , 会 指 导 automake 生 成 指 定 的 代 码 。 例 如 , 宏
bin_PROGRAMS 将导致编译和连接的目标被生成。
5 、运行 automake
$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./mkinstalldirs'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'
The other query is: I observed that gcc-3.x when compiles conftest.c file, though it says the sam
e :"ac_nonexistent.h: No such file or directory", but it does not throw fatal error and proceeds
ahead!!! Is it correct to think that thers is some code handler in gcc-4.x versions that give fatal
error and gcc-3.x don't? I am not at all clear about it, but I observed this and cross checked from
the old config.log file...
The command ./configure will run tests to check the capabilities of the actual system. This is used
to create a working build environment. These tests usually prepare small test environments and
execute special test cases. The configure script checks the result and depending on the result will
continue or fail, and also will generate makefiles and other files. conftest.c is a generated test c
source file to drive a test case. The link I gave you tried to explain the test case related to this ac_
nonexistent.h: how your compiler detects and rejects broken source code that refers to a non-ex
istent header. This is a test case among the others and it must fail. The script configure will catch
that error and that's why it will proceed ahead (because this is the expected behavior).
I was actually entangled in loop that this configuration error is causing the build to fail. But, your
explanation confirmed me. I found that the build process further failed because it could not link
-lselinux flag. For this, it might be looking for lselinux.a in the system. This all happens because
by default prelink is statically build. To overcome this issue, if you :
-remove "-all-static" flags from Makefile in prelink source;
-add another flag while configuring i.e. "--enable-static=no";
it will be built successfully.
Not all failed compilations are bugs.
That’s a sanity check, to ensure that the configuration script is correctly able to determine whether
a header file is present or not: it asks the compiler to use a non-existant header, and checks that the
compiler (correctly) fails.
6. ./configure 的过程
.-------------> [config.cache]
configure* --------------------------+-------------> config.log
|
[config.h.in] -. v .--> [autoconfig.h]
+-------> config.status* -+
Makefile.in ---' `--> Makefile
7. make 过程
[autoconfig.h] -.
+--> make* ---> 程序
Makefile ---'
config.site - - ->| |
config.cache - - ->|configure| - - -> config.cache
| +-,
`-+-------' |
| |----> config.status
config.h.in ------->|config- |----> config.h
Makefile.in ------->| .status|----> Makefile
| |----> stamp-h
| +--,
.-+ | |
| `------+--' |
ltmain.sh ------->|ltconfig|-------> libtool
| | |
`-+------' |
|config.guess|
| config.sub |
`------------'
Makefile ------>| |
config.h ------>| make |
{project sources} ---------------->| |--------> {project targets}
.-+ +--,
| `--------' |
| libtool |
| missing |
| install-sh |
|mkinstalldirs|
`-------------'
实例:
在/hello/目录下创建一个 hello.c 文件,并编译运行它:
#cd /hello/
(1) 编写源文件 hello.c:
#include<stdio.h>
int main(int argc, char** argv)
{
printf("Hello, GNU!n");
return 0;
}
[litao@vm0000131 hello]$ ll
total 4
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
一、autoscan
[litao@vm0000131 hello]$ autoscan
autom4te: configure.ac: no such file or directory
autoscan: /usr/bin/autom4te failed with exit status: 1
[litao@vm0000131 hello]$ ll
total 8
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rw-rw-r-- 1 litao litao 457 Aug 12 12:03 configure.scan
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
已经生成了 configure.scan,autoscan.log 文件
将 configure.scan 修改为 configure.in,最后修改的内容如下:
[litao@vm0000131 hello]$ mv configure.scan configure.in
[litao@vm0000131 hello]$ vim configure.in
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([hello.c])
#AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(hello, 1.0)
# Checks for programs.
AC_PROG_CC
二、acloacl
[litao@vm0000131 hello]$ aclocal
生成 aclocal.m4 和 autom4te.cache (生成 aclocal.m4 的过程中涉及到 configure.in)
[litao@vm0000131 hello]$ ll
total 44
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:08 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
三、antoconf
[litao@vm0000131 hello]$ autoconf
生成 configure (根据 configure.in, 和 aclocal.m4)
[litao@vm0000131 hello]$ ll
total 168
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:11 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rwxrwxr-x 1 litao litao 122297 Aug 12 12:11 configure
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
四、编写 Makefile.am:
AUTOMAKE_OPTIONS= foreign
bin_PROGRAMS= hello
hello_SOURCES= hello.c
五、automake
生成 Makefile.in, depcomp, install-sh 和 missing (根据 Makefile.am,和 aclocal.m4)
[litao@vm0000131 hello]$ automake
configure.in: required file `./install-sh' not found
configure.in: required file `./missing' not found
Makefile.am: required file `./depcomp' not found
[litao@vm0000131 hello]$ automake --add-missing
configure.in: installing `./install-sh'
configure.in: installing `./missing'
Makefile.am: installing `./depcomp'
[litao@vm0000131 hello]$ ll
total 192
-rw-rw-r-- 1 litao litao 31120 Aug 12 12:08 aclocal.m4
drwxr-xr-x 2 litao litao 4096 Aug 12 12:14 autom4te.cache
-rw-rw-r-- 1 litao litao 0 Aug 12 12:03 autoscan.log
-rwxrwxr-x 1 litao litao 122297 Aug 12 12:11 configure
-rw-rw-r-- 1 litao litao 496 Aug 12 12:08 configure.in
lrwxrwxrwx 1 litao litao 31 Aug 12 12:16 depcomp -> /usr/share/automake-1.9/depcomp
-rw-rw-r-- 1 litao litao 68 Aug 12 12:02 hello.c
lrwxrwxrwx 1 litao litao 34 Aug 12 12:16 install-sh -> /usr/share/automake-1.9/install-sh
-rw-rw-r-- 1 litao litao 69 Aug 12 12:15 Makefile.am
-rw-rw-r-- 1 litao litao 16561 Aug 12 12:16 Makefile.in
lrwxrwxrwx 1 litao litao 31 Aug 12 12:16 missing -> /usr/share/automake-1.9/missing
六、configure
生成 Makefile, config.log 和 config.status
生成 makefile 整个过程
configure.in :
configure.in 文件内容是一系列 GNU m4 的宏,这些宏经 autoconf 处理后会变成检查系统特
性的 shell scripts。 configure.in 内宏的顺序并没有特别的规定,但是每一个 configure.in 文件
必須在所有宏前加入 AC_INIT 宏,然后在所有宏的最后加上 AC_OUTPUT 宏。可先用
autoscan 扫描原始文件以产生一个 configure.scan 文件,再对 configure.scan 做些修改成
configure.in 文件。在范例中所用到的宏如下:
dnl
这个宏后面的字不会被处理,可以视为注释
AC_INIT(FILE)
该宏用来检查源代码所在路径,autoscan 会自动产生,一般无须修改它。
AM_INIT_AUTOMAKE(PACKAGE,VERSION)
这个是使用 Automake 所必备的宏,PACKAGE 是所要产生软件套件的名称,VERSION 是
版本编号。
AC_PROG_CC
检查系统可用的 C 编译器,若源代码是用 C 写的就需要这个宏。
AC_OUTPUT(FILE)
设置 configure 所要产生的文件,若是 Makefile ,configure 便会把它检查出来的结果带入 M
akefile.in 文件后产生合适的 Makefile。
实际上,这里使用 Automake 时,还需要一些其他的宏,这些额外的宏我们用 aclocal 来帮
助产生。執行 aclocal 会产生 aclocal.m4 文件,如果无特别的用途,可以不需要修改它,用
aclocal 所产生的宏会告诉 Automake 如何动作。
Makefile.am
Automake 会根据 configure.in 中的宏把 Makefile.am 转成 Makefile.in 文件。 Makefile.am
文件定义所要产生的目标:
AUTOMAKE_OPTIONS
设置 automake 的选项。
Automake 主要是帮助开发 GNU 软件的人员来维护软件,所以在执行 automake 时,会检查
目录下是否存在标准 GNU 软件中应具备的文件,例如 'NEWS'、'AUTHOR'、'ChangeLog' 等
文件。设置 foreign 时,automake 会改用一般软件的标准来检查。
bin_PROGRAMS
定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空白符隔开。
hello_SOURCES
定义 'hello' 这个执行程序所需要的原始文件。如果 'hello'这个程序是由多个原始文件所产生,
必 須 把 它 所 用 到 的 所 有 原 始 文 件 都 列 出 来 , 以 空 白 符 隔 开 。 假 设 'hello' 还 需 要
'hello.c'、'main.c' 、'hello.h' 三个文件的话,则定义
hello_SOURCES= hello.c main.c hello.h
如果定义多个执行文件,则对每个执行程序都要定义相对的 filename_SOURCES。