linux-make与makefile

make工具与makefile文件编写

GNU make命令的主要功能是读进一个文本文件makefile并根据makefile的内容执行一系列的工作,完成整个编译过程。要使用make命令,必须编写一个叫做makefile的文件。makefile文件描述了编译当前程序需要做的所有工作,如设置环境变量,编译依赖项,寻找头文件和库文件,自动为不同编译对象添加合适的编译选项等。类似于脚本文件,编写makefile文件需要遵循makefile语法。makefile写好之后,每次改变了某些源文件,只要执行make命令,则所有相关联的目标将重新编译。Make程序利用makefile中的数据和每个文件的最后修改时间来确定那个文件需要更新,对于需要更新的文件,make程序执行makefile数据中定义的命令来更新。一个Makefile文件主要含有一系列的规则,每条规则包含以下内容:

  • 一个目标(target),即make最终需要创建的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如“clean”。
  • 一个或多个依赖文件(dependency)列表,通常是编译目标文件所需要的其他文件。
  • 一系列命今(command),是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,且每个命令行的起始字符必须为TAB字符。

例如:

test:prog.o code.o
		gcc –o test prog.o code.o
prog.o:prog.c prog.h code.h
		gcc –c prog.c –o prog.o
code.o:code.c code.h
		gcc –c code.c –o code.o
clean:
		rm –rf *.o 

上面的Makefile文件中共定义了四个目标:test、prog.o、code.o和clean。

目标从每行的最左边开始写,后面跟一个冒号(:),如果有与这个目标有依赖性的其他目标或文件,把它们列在冒号后面,并以空格隔开。然后另起一行开始写实现这个目标的一组命令。在Makefile中,可使用续行号(\)将一个单独的命令行延续成几行。但要注意在续行号(\)后面不能跟任何字符(包括空格)。

make target

target是Makefile文件中定义的目标之一,如果省略target,make就将生成Makefile文件中定义的第一个目标。对于上面Makefile的例子,单独的一个“make”命令等价于:

make test

因为test是Makefile文件中定义的第一个目标,make首先将其读入,然后从第一行开始执行,把第一个目标test作为它的最终目标,所有后面的目标的更新都会影响到test的更新。第一条规则说明只要文件test的时间戳比文件prog.o或code.o中的任何一个旧,下一行的编译命令将会被执行。

但是,在检查文件prog.o和code.o的时间戳之前,make会在下面的行中寻找以prog.o和code.o为目标的规则,在第三行中找到了关于prog.o的规则,该文件的依赖文件是prog.c、prog.h和code.h。同样,make会在后面的规则行中继续查找这些依赖文件的规则,如果找不到,则开始检查这些依赖文件的时间戳,如果这些文件中任何一个的时间戳比prog.o的新,make将执行“gcc –c prog.c –o prog.o”命令,更新prog.o文件。

以同样的方法,接下来对文件code.o做类似的检查,依赖文件是code.c和code.h。当make执行完所有这些套嵌的规则后,make将处理最顶层的test规则。如果关于prog.o和code.o的两个规则中的任何一个被执行,至少其中一个.o目标文件就会比test新,那么就要执行test规则中的命令,因此make去执行gcc命令将prog.o和code.o连接成目标文件test。

在上面Makefile的例子中,还定义了一个目标clean,它是Makefile中常用的一种专用目标,即删除所有的目标模块。

Makefile中的变量

Makefile中的变量是用一个文本串在Makefile中定义的,这个文本串就是变量的值。只要在一行的开始写下这个变量的名字,后面跟一个“=”号,以及要设定这个变量的值即可定义变量,下面是定义变量的语法:

VARNAME=string

使用时,把变量用括号括起来,并在前面加上$符号,就可以引用变量的值:

${VARNAME}

变量一般都在Makefile的头部定义。按照惯例,所有的Makefile变量都应该是大写。如果变量的值发生变化,就只需要在一个地方修改,从而简化了Makefile的维护。

现在利用变量把前面的Makefile重写一遍:

OBJS=prog.o code.o
CC=gcc
test:${ OBJS }
		${ CC } –o test ${ OBJS }
prog.o:prog.c prog.h code.h
		${ CC } –c prog.c –o prog.o
code.o:code.c code.h
		${ CC } –c code.c –o code.o
clean:
		rm –rf *.o

Makefile的隐含规则(自动变量)

make可以使工作更加自动化,也就是说,make知道一些默认的动作,它有一些称作隐含规则的内置的规则,这些规则告诉make当用户没有完整地给出某些命令的时候,应该怎样执行。

像在前面的例子中所定义的那样
make使用变量CC来定义编译器,并且传递变量CFLAGS(编译器参数)、CPPFLAGS(C语言预处理器参数)、TARGET_ARCH(目标机器的结构定义)给编译器,然后加上参数-c,后面跟变量$<(第一个依赖文件名),然后是参数-o加变量$@(目标文件名)。综上所述,一个C编译的具体命令将会是:

$ {CC} $ {CFLAGS} $ {CPPFLAGS} $ {TARGET_ARCH} –c $< -o $@

在上面的例子中,利用隐含规则,可以简化为:

OBJS=prog.o code.o
CC=gcc
test:${ OBJS }
	${ CC } –o $@ $^
prog.o:prog.c prog.h code.h
code.o:code.c code.h
clean:
	rm –rf *.o

实践

(1)假设有max.c及max.h文件;

(2)入口main.c;

(3)编写makefile文件,管理以上工程。

(4)通过make生成执行文件;

maxgo:max.o main.o
	gcc -o maxgo max.o main.o
max.o:max.c max.h
	gcc -c max.c -o max.o
main.o:main.c
	gcc -c main.c -o main.o
clean:
	rm *.o
posted @ 2020-08-07 20:42  漫漫长夜何时休  阅读(240)  评论(0编辑  收藏  举报