Chinaunix首页 | 论坛 | 博客
  • 博客访问: 41011
  • 博文数量: 5
  • 博客积分: 415
  • 博客等级: 一等列兵
  • 技术积分: 70
  • 用 户 组: 普通用户
  • 注册时间: 2008-10-06 16:39
文章分类

全部博文(5)

文章存档

2011年(1)

2009年(1)

2008年(3)

分类: 嵌入式

2008-10-21 22:03:25

GNU make最初是Unix系统下的一个工具,设计之初是为了维护C程序文件不必要的重新编译。使用make工具,可以将大型的开发项目分解成多个更易于管理的模块。
make是一个解释Makefile文件中指令的命令工具,其最基本的功能就是通过Makefile文件来描述源程序之间的相互关系并自动维护编译工作,它会告诉系统以何种方式编译何链接程序。一旦正确完成Makefile文件,剩下的就是在Linux终端下输入make这样的一个命令,就可以自动完成所有的编译任务,并生成目标文件程序。由此可见Makefile文件的重要价值。本文只是对Makefile相关知识的总结,其内容包括:1.GNU make基础知识及原理;2.Makefile相关知识;3.手工制作Makefile文件;4.利用autoconf和automake自动生成Makefile文件
因为本人也属于菜鸟级别的,有不足的地方,各位包容,千万别仍鸡蛋---谢谢
1.GNU make基础知识及原理
GNU makede 工作流程如下:

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:指定所有的Makefile所在的目录

-h:help文档,显示Makefile的help信息

例:习惯makeflie文件名为Makefile,当然以这知识习惯。我们可以自己随意的命名。这时我们可以用带-f的选项的make命令来指定Makefile文件

#make -f makename

2.Makefile相关知识

2.1 Makefile规则:

#注释

目标文件....:依赖文件列表

命令列表

注意:是按Tab建 不能用简单的空格建替代

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,并删除编译过程产生的中间目标文件,执行main

./main

屏幕会打印出

hello makefile!

4.利用autoconf和automake自动生成Makefile文件

Autoconf上可以自动生成一个shell脚本,利用他你可在不同的unix下自动生成特定的Makefile文件,而且这个脚本可以脱离autoconf来运行。生成的这个脚本名字叫configure,执行他后。

4.1  在/root/project/main目录下创建一个文件main.c,其内容如下:

------------------------------------------------
#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,并且编辑它

mv configure.scan configure.in

vi 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文件,是我这几天正在看的东西,网上有不少这方面的知识,我这部分也就是对自己找到的几份资料的综合

阅读(1359) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~