linux下makefile编写及automake整理

makefile编写规则


在一个makefile中通常包含如下内容:
1 需要由make工具创建的目标体(target),通常是目标文件或可执行文件
2 要创建的目标体所依赖的文件(dependency_file)
3 创建每个目标体时需要运行的命令(command),这一行必须以制表符(tab键)开头
格式:
target: dependency_files
command /* 该行必须以tab键开头*/

例如,有两个文件分别为hello.c和hello.h,创建的目标体为hello.o,执行的命令为gcc编译指令:gcc –c hello.c,那么,对应的makefile就可以写为:
#The simplest example
hello.o: hello.c hello.h
gcc –c hello.c –o hello.o

执行:
[root@yunduan makefile]# make hello.o
gcc –c hello.c –o hello.o
[root@yunduan makefile]# ls
hello.c hello.h hello.o makefile


makefile变量


用户自定义变量:
makefile变量定义的两种方式:(使用格式为:$(VAR))
递归展开方式:能很好的完成用户指令,但变量后不可追加内容,可能造成无穷循环:定义格式:VAR=var
简单方式:变量的值在定义处展开,并且只展开一次,不包含任何对其他变量的引用:定义格式:VAR:=var


变量名:
变量名大小写敏感
推荐在makefile内部使用小写字母作为变量名,预留大写字母作为控制隐含规则参数或用户重载命令选项参数的变量名。
不包括“:”、“#”、“=”以及结尾空格的任何字符串,同时,变量名中包含字母、数字以及下划线以外的情况应尽量避免,因为它们可能在将来被赋予特别的含义


常见预定义变量:

AR       库文件维护程序的名称,默认值为ar
AS       汇编程序的名称,默认值为as
CC       C编译器的名称,默认值为cc
CPP      C预编译器的名称,默认值为$(CC) –E
CXX      C++编译器的名称,默认值为g++
FC       Fortran编译器的名称,默认值为f77
RM       文件删除程序的名称,默认值为rm –f
ARFLAGS  库文件维护程序的选项,无默认值
ASFLAGS  汇编程序的选项,无默认值
CFLAGS   C编译器的选项,无默认值
CPPFLAGS C预编译的选项,无默认值
CXXFLAGS C++编译器的选项,无默认值
FFLAGS   Fortran编译器的选项,无默认值


常见的自动变量:

$@    目标文件的完整名称
$*    不包含扩展名的目标文件名称
$<    第一个依赖文件的名称
$%    如果目标是归档成员,则该变量表示目标的归档成员名称

$+    所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件
$?    所有时间戳比目标文件晚的依赖文件,并以空格分开
$^    所有不重复的依赖文件,以空格分开

在makefile中还可以使用环境变量。使用环境变量的方法相对比较简单,make 在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量。用户自定义变量会覆盖同名的环境变量。


makefile规则

隐式规则:
只需把目标文件列出即可,make 会自动搜索隐式规则目录来确定如何生成目标文件,它只能查找到相同文件名的不同后缀名文件,如“kang.o”文件必须由“kang.c”文件生成

makefile中常见隐式规则目录
C编译:      .c变为.o $(CC) –c $(CPPFLAGS) $(CFLAGS)
C++编译:    .cc或.C变为.o $(CXX) -c $(CPPFLAGS) $(CXXFLAGS)
Pascal编译: .p变为.o $(PC) -c $(PFLAGS)
Fortran编译:.r变为-o $(FC) -c $(FFLAGS)


模式规则:用来定义相同处理规则的多个文件,隐式规则仅仅能够用make 默认的变量来进行操作,而模式规则还能引入用户自定义变量,为多个文件建立相同的规则,实用模式规则时相关文件前必须用“%”标明

例如:
david:kang.o yul.o
gcc kang.o bar.o -o myprog
kang.o : kang.c kang.h head.h
gcc –Wall –O -g –c kang.c -o kang.o
yul.o : bar.c head.h
gcc - Wall –O -g –c yul.c -o yul.o

修改后:(递归展开方式)
OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
david : $(OBJS)
$(CC) $(OBJS) -o david
kang.o : kang.c kang.h
$(CC) $(CFLAGS) -c kang.c -o kang.o
yul.o : yul.c yul.h
$(CC) $(CFLAGS) -c yul.c -o yul.o

改写后:(自动变量)
OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
david : $(OBJS)
$(CC) $^ -o $@
kang.o : kang.c kang.h
$(CC) $(CFLAGS) -c $< -o $@
yul.o : yul.c yul.h
$(CC) $(CFLAGS) -c $< -o $@

修改后:(隐式规则)
OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
david : $(OBJS)
$(CC) $^ -o $@

改写后:(模式规则)
OBJS = kang.o yul.o
CC = gcc
CFLAGS = -Wall -O -g
david : $(OBJS)
$(CC) $^ -o $@
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@


make命令的使用
只需在make命令的后面键入目标名即可建立指定的目标,如果直接运行make,则建立makefile中的第一个目标

make的命令行选项

-C dir 读入指定目录下的makefile
-f file 读入当前目录下的file文件作为makefile
-I 忽略所有的命令执行错误
-I dir 指定被包含的makefile所在目录
-n 只打印要执行的命令,但不执行这些命令
-p 显示make变量数据库和隐含规则
-s 在执行命令时不显示命令
-w 如果make在执行过程中改变目录,则打印当前目录名


autotools
生成makefile 同时又能拥有make的功能
which命令进行查看aclocal autoscan autoconf autoheader automake是否安装

vim hello.c
#include <stdio.h>
int sum(int);
int main(){
    printf("the sum of 1-50 is %d\n",sum(50));
}
int sum(int n){
    int i,sum;
    for(i = 1,sum = 0; i <= n; ++i){
        sum += i;
    }
    return sum;
}

流程:
1.autoscan
在给定目录及其子目录树中检查源文件,若没有给出目录,就在当前目录及其子目录树中进行检查。它会搜索源文件以寻找一般的移植性问题并创建一个文件"configure.scan",该文件就是接下来autoconf 要用到的"configure.in"原型

[root@yunduan makefile]# ll
总用量 4
-rw-r--r-- 1 root root 207 4月  30 10:15 hello.c
[root@yunduan automake]# autoscan
[root@yunduan automake]# ll
总用量 8
-rw-r--r-- 1 root root   0 4月  30 10:18 autoscan.log
-rw-r--r-- 1 root root 467 4月  30 10:18 configure.scan
-rw-r--r-- 1 root root 207 4月  30 10:15 hello.c


2.修改configure.scan
configure.in是autoconf的脚本配置文件,它的原型文件"configure.scan"

# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.63)
#AC_INIT(FULL-PACKAGE-NAME,VERSION,BUG-REPORT-ADDRESS)
AC_INIT(hello,1.0)
AM_INIT_AUTOMAKE(hello,1.0)
AC_CONFIG_SRCDIR([hello.c])
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

脚本文件解释:
1 以"#"号开始的行是注释。
2 AC_PREREQ 宏声明本文件要求的autoconf版本,如本例使用的版本2.59。
3 AC_INIT 宏用来定义软件的名称和版本等信息,在本例中省略了BUG-REPORT-ADDRESS,一般为作者的E-mail。
4 AM_INIT_AUTOMAKE 是automake 所必备的宏,使automake 自动生成makefile.in,也同前面一样,PACKAGE 是所要产生软件套件的名称,VERSION 是版本编号,也可不带参数直接写成AM_INIT_AUTOMAKE。
5 AC_CONFIG_SRCDIR宏用来检查所指定的源码文件是否存在,以及确定源码目录的有效性。在此处源码文件为当前目录下的hello.c。
6 AC_CONFIG_HEADER宏用于生成config.h文件,以便autoheader 使用。
7 AC_CONFIG_FILES宏用于生成相应的makefile文件。
8 中间的注释之间可以分别添加用户测试程序、测试函数库、测试头文件等宏定义。

改写"configure.scan"文件,并重命名为"configure.in"

3.autoheader
接着使用autoheader 命令,它负责生成config.h.in 文件。该工具通常会从"acconfig.h"文件中复制用户附加的符号定义,因为这里没有附加符号定义,所以不需要创建"acconfig.h"文件


4 aclocal
使用aclocal生成一个"aclocal.m4"文件,该文件主要处理本地的宏定义


5.automake
这一步是创建makefile 很重要的一步,automake 要用的脚本配置文件是makefile.am,用户需要自己创建相应的文件。之后,automake工具转换成makefile.in。

AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS= hello
hello_SOURCES= hello.c

解释:
1 AUTOMAKE_OPTIONS 为设置automake 的选项。GNU 对自己发布的软件有严格的规范,比如必须附带许可证声明文件COPYING 等,否则automake执行时会报错。automake提供了3种软件等级:foreign、gnu和gnits,让用户选择采用,默认等级为gnu。在本示例中采用foreign等级,它只检测必须的文件。
2 bin_PROGRAMS  定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。
3 hello_SOURCES  定义"hello"这个执行程序所需要的原始文件。如果"hello"这个程序是由多个原始文件所产生的,则必须把它所用到的所有原始文件都列出来,并用空格隔开。例如:若目标体"hello"需要"hello.c"、"david.c"、"hello.h"三个依赖文件,则定义hello_SOURCES=hello.c david.c hello.h。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的file_SOURCES

接下来可以使用automake命令来生成"configure.in"文件,在这里使用选项"-a"(或者"—adding-missing")可以让automake 自动添加一些必需的脚本文件

[root@yunduan automake]# vim makefile.am
[root@yunduan automake]# automake –a(或者automake --add-missing)
configure.in: installing ‘./install-sh‘
configure.in: installing ‘./missing‘
makefile.am: installing ‘depcomp‘
[root@yunduan automake]# ls
aclocal.m4 autoscan.log configure.in hello.c makefile.am missing
autom4te.cache configure depcomp install-sh makefile.in config.h.in

在automake之后就生成了makefile.in文件


6 autoconf
运行autoconf,生成"configure"可执行文件


7 运行configure
运行自动配置设置文件configure,把makefile.in变成了最终的makefile

运行configure 时收集了系统的信息,用户可以在configure 命令中对其进行配置。
./configure的自定义参数有两种,一种是开关式(--enable-XXX或--disable-XXX),另一种是开放式,即后面要填入一串字符(--with-XXX=yyyy)参数。
同一目录下的"config.log"文件,可以方便调试。

大体流程图:
技术分享

后续工作:

autotools所生成的makefile
1 make  生成可执行文件
2 make  install安装到系统目录中
3 make clean  make会清除之前所编译的可执行文件及目标文件(object file, *.o)
4 make dist  make将程序和相关的文档打包为一个压缩文档以供发布
5 制作debian或rmp程序包(后续)

示例步骤:
[root@yunduan automake]# autoscan 
[root@yunduan automake]# ls
autoscan.log  configure.scan  hello.c

[root@yunduan automake]# vim configure.scan 
[root@yunduan automake]# mv configure.scan configure.in
[root@yunduan automake]# ls
autoscan.log  configure.in  hello.c

[root@yunduan automake]# autoheader 
[root@yunduan automake]# ls
autom4te.cache  autoscan.log  config.h.in  configure.in  hello.c

[root@yunduan automake]# aclocal
[root@yunduan automake]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure.in  hello.c

[root@yunduan automake]# vim makefile.am
[root@yunduan automake]# automake -a
configure.in:6: installing `./install-sh'
configure.in:6: installing `./missing'
makefile.am: installing `./depcomp'
[root@yunduan automake]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure.in  depcomp  hello.c  install-sh  makefile.am  makefile.in  missing

[root@yunduan automake]# autoconf
[root@yunduan automake]# ls
aclocal.m4  autom4te.cache  autoscan.log  config.h.in  configure  configure.in  depcomp  hello.c  install-sh  makefile.am  makefile.in  missing

[root@yunduan automake]# ./configure 
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
configure: creating ./config.status
config.status: creating makefile
config.status: creating config.h
config.status: executing depfiles commands

[root@yunduan automake]# ls
aclocal.m4      autoscan.log  config.h.in  config.status  configure.in  hello.c     makefile     makefile.in  stamp-h1
autom4te.cache  config.h      config.log   configure      depcomp       install-sh  makefile.am  missing

[root@yunduan automake]# cat makefile


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。