全部博文(5)
分类: 嵌入式
2008-10-21 22:03:25
1.查找当前目录下的Makefile文件 |
2.初始化文件中的变量 |
3.分析Makefile中的所有规则 |
4.为所有的目标文件创造依赖关系 |
5.根据依赖关系,决定哪些目标文件要重新生成 |
6.执行生成命令 |
为了比较明了地说明make工具的工作原理,举个例子。比如我们的项目有以下文件。
源程序:main.c、test1.c、test.c
头文件:head1.h、head2.h、head3.h
有源程序和头文件编译生成的目标文件:main.o、test1.o、test2.o
以及有目标文件链接生成的可执行文件:test
它们的相互依赖关系:
main.c head1.h main.o head2.h |
head2.h test1.o test1.c |
test2.c test2.o head3.h |
main.o test1.o test test2.o |
在该项目的所有文件当中,目标文件main.o的依赖文件是main.c、head1.h、head2.h;test.o的依赖文件是head2.h、test1.c;目标文件test2.o的依赖文件是head3.h、test2.c;最终的可执行文件依赖文件是main.o、test1.o、test2.o。执行make命令时,会首先处理test程序的所有依赖文件(.o文件)的更新规则,对于.o文件,会检查每个依赖程序(.c和.h文件)是否有更新,其判断依据主要是依赖文件的建立时间是否比所生成的目标文件要晚,如果是,那么就会按规则重新编译生成相应的目标文件,对于可执行文件也是如此。make工具管理项目的过程是从最底层开始。
make本身可以带有参数:Make 【选项】【宏定义】【目标文件】
make命令的常用选项:
-f file:指定Makefile的文件名
-n:打印出所有的执行命令,但实际上并不执行这些命令
-s:在执行时并不打印命令名
-w:如果在make执行时要改变目录,则打印当前的执行目录
-I
-h:help文档,显示Makefile的help信息
例:习惯makeflie文件名为Makefile,当然以这知识习惯。我们可以自己随意的命名。这时我们可以用带-f的选项的make命令来指定Makefile文件
#make -f makename
2.Makefile相关知识
2.1 Makefile规则:
#注释 目标文件....:依赖文件列表 |
注意:
2.2 变量的定义
immediate = deferred immediate ?= deferred immediate := immediate immediate += deferred or immediate define immediate deferred endef |
GNU make中对变量的赋值有两种方式:延时变量、立即变量。区别在于他们的定义方式和扩展时的方式不同,前者在这个变量使用时猜扩展开,即当真正使用时这个变量的值猜确定;后者在定义时它的的值就已经确定。”=“、”?=“和使用define指令定义的变量是延时变量;”:=“定义是立即变量。”?=“用来定义第一次出现的延时变量。
对于附加操作符”+=“,右边的变量如果在前面使用(:=)定义为立即变量则它为立即变量,否则均为延时变量。
Makefile中变量直接定义不需要什么特变的格式 例如
CC=gcc #定义变量CC 并赋值gcc |
引用变量用$() 如引用上述定义的CC变量
$(CC) |
2.3 Makefile 中的函数
函数调用的格式如下:
$(function arguments)
function为函数名 arguments为该函数的参数,之间用空格或
(1)$(subst from,to,text)
在文本text中用to替代from
(2)$(findstring find,in)
在字符串”in“中查找find,找到返回find , 否则返回值为空
(3) $(shell command arguments)
例:当前目录下有1.c、2.c、1.h、2.h
src :=$(shell ls *.c)
则结果为”1.c 2.c“
。。。。。。
由于函数较多这里不一一介绍
2.4 Makefile文件中的变量
$@:指代当前规则下的目标文件列表
$<:指代依赖文件列表中所有第一个依赖文件
$^:指代依赖文件列表中所有依赖文件
$?:指代依赖文件列表中新于对应目标文件的文件列表
3. 手工制作Makefile文件
有以上的知识我们就可以手工制作一个简单的Makefile文件了,我们还以上面make原理里面的那个项目为例。
以下是上述项目各源程序及头文件的代码:
main.c
#include int main(int argc,char *argv[]) { printf("hello makefile!\n"); return 0; } |
Makefile文件
src :=$(shell ls *c) CC=gcc main:main.c $(CC) -o main $(src) clean: rm -rf *.o |
第一行src变量的值为main.c
第二行指定编译器为gcc
第三行main 的依赖文件为main.c
其中clean为伪目标,它规定make应该执行的命令,即删除所有编译过程中产生的中间目标文件。由于伪目标clean没有任何依赖,所以make命令会认为该目标是最新的而不会执行任何操作,所以还必须手工执行如下命令
make clean |
./main |
屏幕会打印出
hello makefile! |
4.利用autoconf和automake自动生成Makefile文件
Autoconf上可以自动生成一个shell脚本,利用他你可在不同的unix下自动生成特定的Makefile文件,而且这个脚本可以脱离autoconf来运行。生成的这个脚本名字叫configure,执行他后。
4.1 在/root/project/main目录下创建一个文件main.c,其内容如下:
------------------------------------------------ mv configure.scan configure.in vi configure.in
#include
int main(int argc, char** argv)
{
printf("Hello, Auto Makefile!\n");
return 0;
}
------------------------------------------------
此时状态如下:
[root@localhost main]# ls
main.c
4.2 运行 autoscan , 自动创建两个文件: autoscan.log configure.scan
此时状态如下:
[root@localhost main]# autoscan
[root@localhost main]# ls
autoscan.log configure.scan main.c
4.3 我们可以拿上面的configure.scan作为configure.in的蓝本。现在将configure.scan改名为configure.in,并且编辑它
============================configure.in内容开始======================
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_INIT(helloworld.c)
AM_INIT_AUTOMAKE(helloworld, 1.0)
# 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_OUTPUT(Makefile)
============================configure.in内容结束==========================
修改
修改后的结果:
------------------------------------------------
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT(main, 1.0, )
AC_CONFIG_SRCDIR([main.c])
AC_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE(main,1.0)
# 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_OUTPUT([Makefile])
------------------------------------------------
4.4 运行 aclocal, 生成一个“aclocal.m4”文件和一个缓冲文件夹autom4te.cache,该文件主要处理本地的宏定义。
此时的状态是:
[root@localhost main]# aclocal
[root@localhost main]# ls
aclocal.m4 autom4te.cache autoscan.log configure.in main.c
linux的版本不一样得到的结果会稍有不同,但都会生成aclocal.m4 autom4te.cache这2个文件
4.5 运行 autoconf, 目的是生成 configure
此时的状态是:
[root@localhost main]# autoconf
[root@localhost main]# ls
aclocal.m4 autoscan.log configure.in main.c
autom4te.cache configure
4.6 运行 autoheader,它负责生成config.h.in文件。该工具通常会从“acconfig.h”文件中复制用户附加的符号定义,因此此处没有附加符号定义,所以不需要创建“acconfig.h”文件。
此时的状态是:
[root@localhost main]# autoheader
[root@localhost main]# ls
aclocal.m4 autoscan.log configure autom4te.cache config.h.in configure.in main.c
4.7 下面即将运行 automake, 但在此之前应该做一下准备工作!
首先
创建一个 Makefile.am.这一步是创建Makefile很重要的一步,automake要用的脚本配置文件是Makefile.am,用户需要自己创建相应的文件。之后,automake工具转换成Makefile.in。
这个Makefile.am的内容如下:
------------------------------------------------
AUTOMAKE_OPTIONS=foreign
bin_PROGRAMS=main
main_SOURCES=main.c
------------------------------------------------
其中的AUTOMAKE_OPTIONS为设置automake的选项。由于GNU(在第1章中已经有所介绍)对自己发布的软件有严格的规范,比如必须附 带许可证声明文件COPYING等,否则automake执行时会报错。automake提供了三种软件等级:foreign、gnu和gnits,让用 户选择采用,默认等级为gnu。在本例使用foreign等级,它只检测必须的文件。
bin_PROGRAMS定义要产生的执行文件名。如果要产生多个执行文件,每个文件名用空格隔开。
main_SOURCES定义“main”这个执行程序所需要的原始文件。如果”main”这个程序是由多个原始文件所产生的,则必须把它所用到的所有原 始文件都列出来,并用空格隔开。例如:若目标体“main”需要“main.c”、“sunq.c”、“main.h”三个依赖文件,则定义 main_SOURCES=main.c sunq.c main.h。要注意的是,如果要定义多个执行文件,则对每个执行程序都要定义相应的file_SOURCES。
其次
使用automake对其生成“configure.in”文件,在这里使用选项“—adding-missing”可以让automake自动添加有一些必需的脚本文件。
运行后的状态是:
------------------------------------------------
[root@localhost main]# automake --add-missing
configure.in:8: installing `./missing'
configure.in:8: installing `./install-sh'
Makefile.am: installing `./depcomp'
[root@localhost main]# ls
aclocal.m4 config.h.in configure.in~ main.c Makefile.in
autom4te.cache configure depcomp Makefile.am missing
autoscan.log configure.in install-sh Makefile.am~
[root@localhost main]#
------------------------------------------------
4.8 运行configure,在这一步中,通过运行自动配置设置文件configure,把Makefile.in变成了最终的Makefile。
运行的结果如下:
------------------------------------------------
[root@localhost main]# ./configure
[root@localhost main]# ls
aclocal.m4 config.h.in configure.in main.c Makefile.in
autom4te.cache config.log configure.in~ Makefile missing
autoscan.log config.status depcomp Makefile.am stamp-h1
config.h configure install-sh Makefile.am
这样Makefile就自动生成好了,
4.9 运行 make,对配置文件Makefile进行测试一下
此时的状态如下:
------------------------------------------------
[root@localhost main]# make
运行生成的文件 main:
------------------------------------------------
[root@localhost main]# ./main
Hello, Auto Makefile!
[root@localhost main]#
------------------------------------------------
目录结构:
.
|-- Makefile
|-- Makefile.am
|-- Makefile.in
|-- README
|-- aclocal.m4
|-- config.cache
|-- config.log
|-- config.status
|-- configure
|-- configure.in
|-- configure.scan
|-- install-sh -> /usr/local/share/automake/install-sh
|-- missing -> /usr/local/share/automake/missing
|-- mkinstalldirs -> /usr/local/share/automake/mkinstalldirs
|-- src
| |-- Makefile
| |-- Makefile.am
| |-- Makefile.in
| |-- dlpi.lib
| | |-- Makefile
| | |-- Makefile.am
| | |-- Makefile.in
| | |-- dlpi.c
| | |-- dlpi.o
| | |-- dlpi_lib.h
| | `-- libdlpi.a
| |-- p.c
| |-- put
| |-- put.c
| |-- put.o
| |-- t
| |-- t.c
| `-- t.o
`-- stamp-h
注:自动第四部分利用autoconf和automake自动生成Makefile文件,是我这几天正在看的东西,网上有不少这方面的知识,我这部分也就是对自己找到的几份资料的综合