Linux 软件系列之十六——makefile

1.Makefile简介

一般来说,无论是C、C++、首先要把源文件编译成中间目标文件。在Windows下也就是 .obj 文件,UNIX下是 .o 文件,即 Object File,这个动作叫做编译(compile)。然后再把大量的Object File合成执行文件,这个动作叫作链接(link)。通过链接生成最终可执行文件。Makefile带来的好处就是——“自动化编译”。一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。另外,一个工程有很多文件组成,每一个文件的改变都会导致工程的重新链接,但是,不是所有的文件都需要重新编译,Makefile中记录有文件的信息,在make时会决定在链接的时候需要重新编译哪些文件。

在编写makefile的时候一般不直接使用gcc test.c -o test这种写法

往往是先生成.o文件,然后再生成可执行文件,这样做的原因是:gcc test.c -o test如果其中一个.c文件修改了,那么所有的.c文件都会被重新编译一次。

2. makefile基本结构

Makefile是make默认读入的配置文件,以下是Makefile的编写规则。

target ... : prerequisites ...

              command

target是一个目标文件,可以是Object File,也可以是执行文件。prerequisites是要生成那个target所需要的源文件或是目标文件。command是make需要执行的命令。(任意的shell命令),command前面一定要有tab空格。

如:hello.o:hello.c hello.h

              gcc hello.c -o hello.o -c

3.make使用

Make命令本身可带有四种参数:标志、宏定义、描述文件名和目标文件名。其标准形式为:make [flags] [macro definitions] [targets]

-f file(为flags的一种):指定file文件为描述文件。如果没有“-f”参数,则系统将默认当前目录下名为GNUmakefile或者makefile或者Makefile的文件为描述文件。在Linux中,GNU make 工具在当前工作目录中按照GNUmakefile、makefile、Makefile的顺序搜索 makefile文件。通过命令行参数中的targets ,可指定make要编译的目标,并且允许同时定义编译多个目标,操作时按照从左向右的顺序依次编译target选项中指定的目标文件。如果命令行中没有指定目标,则系统默认target指向描述文件中第一个目标文件。

make中的宏定义会覆盖makefile中宏定义。比如Makefile中的第一行为:obj=test

如果在终端输入make命令为:make obj=target

那么Makefile中所有跟obj变量有关的都被替换为target,而不是test。

4.隐含规则

在make工具中包含有一些内置的或隐含的规则,这些规则定义了如何从不同的依赖文件建立特定类型的目标。“隐含规则”为make提供了重建特定目标文件的通用方法,不需要在Makefile中明确地给出重建特定目标文件所需要的细节描述。例如:典型地make对C文件的编译过程是由.c源文件编译生成.o目标文件。当Makefile中出现一个.o文件目标时,make会使用这个通用的方式将后缀为.c的文件编译称为目标的.o文件。系统中默认的常用文件扩展名及其含义为: 

.o  目标文件

.c  C源文件

.f  FORTRAN源文件

.s  汇编源文件
.cpp C++源文件

每一个内嵌的隐含规则中都存在一个目标模式和依赖模式,而且同一个目标模式可以对应多个依赖模式。例如:一个.o文件的目标可以由c编译器编译对应的.c源文件得到、Pascal编译器编译对应的.p的源文件得到,等等。make会根据不同的源文件来使用不同的编译器。对于“test.c”就是用c编译,对于“test.p”就使用Pascal编译器编译。如果在目录下存在“test.p”与“test.c”。执行make的结果就不是用“pc”编译“test.p”来生成目标文件,而是用“cc”编译“test.c”来生成目标文件。这是因为在隐含规则列表中对.c文件的隐含规则处于.p文件隐含规则之前。

5.变量

变量与c语言中的宏定义一样,代表一个文本字符串。定义:使用“=”定义。如:

object = test.o

引用:在引用宏时只需在变量前加$符号,但值得注意的是,如果变量名的长度超过一个字符,在引用时就必须加圆括号()。

如:$(object):test.c

cc -c test.c -o $(object)

隐含变量:内嵌隐含规则的命令中,所使用的变量都是预定义的变量。我们将这些变量称为“隐含变量”。

例如,编译.c源文件的隐含规则为:“$(CC) -c $(CFLAGS) $(CPPFLAGS)”。CC就是隐含变量,CC=cc。默认的编译命令是“cc”,执行的命令是:“cc –c”。

6. #,@

Makefile中“#”字符后的内容被作为是注释内容(和shell脚本一样)处理。如果此行的第一个非空字符为“#”,那么此行为注释行。注释行的结尾如果存在反斜线(\),那么下一行也被作为注释行。一般在书写Makefile时推荐将注释作为一个独立的行,而不要和Makefile的有效行放在一行中书写。当在Makefile中需要使用字符“#”时,可以使用反斜线加“#”(\#)来实现(对特殊字符“#”的转义),其表示将“#”作为一字符而不是注释的开始标志。

@:不显示执行的命令行

7. clean

格式:

.PHONY:clean #声明clean为伪目标

clean:

        -rm 文件名

作用:清空目标文件,便于重新编译,保持文件的清洁。.PHONY意思表示clean是一个“伪目标”,只是一个标签,clean之后并没有什么文件用来生成clean这个文件。在rm前加上一个“-”的意思是,也许某些文件会出现问题,但是不要管,继续做后面的事情。一个不成文的规矩是:clean都是放在文件的后面。使用:只有执行make clean命令,才能执行清除功能。

8. ifeq,ifnef,ifdef,ifndef

MAIN=main

ifeq ($(MAIN),main)//ifeq后面要有空格

source=main.o

else

source=test.o

endif

all:$(source)

gcc -o main $(source)

 

#MAIN =              //会执行else后的代码

ifdef MAIN

source=main.o

else

source=test.o

endif

all:$(source)

gcc -o main $(source)

注意:如果要生成多个可执行文件的时候,由于makefile只能有一个目标,理论上makefile的语法就不满足了,所以可以构造一个没有规则的终极目标all,比如:all:main1 main2,只有目标是all,需要的文件是main1和main2然而执行的操作是空的。通过这样的形式来让makefile满足语法规则。

9. automake

介绍如何利用 GNU Autoconf 及 Automake 这两套工具来协助我们自动产生 Makefile文件,并且让开发出来的软件可以像大多数源码包那样,只需“./configure”, “make”,“make install” 就可以把程序安装到系统中。

1)进入代码目录。

2)使用命令autoscan生成configure.scan。将configure.scan改名为configure.in并将其内容按需修改。


3)使用命令aclocal:生成aclocal.m4文件,这个文

                件中包含需要的宏定义。

4)使用命令autoconf:将configure.in中的宏展开

   ,生成configure脚本。需要用到aclocal.m4中的

   宏定义。

5)使用命令autoheader,负责生成config.h.in文件

   。这个工具通常会从“acconfig.h”文件中复制

   用户附加的符号定义。

6)创建创建Makefile.am文件。

                Makefile.am内容是:


7)执行命令:automake --add-missing

自动添加一些必须的脚本文件。

8)执行命令:./configure

9)执行命令:make

进行编译,生成最终的可执行文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值