make工具简介

在Linux C/C++的开发过程当中,当源代码文件较少时,咱们能够手动使用gcc或g++进行编译连接,可是当源代码文件较多且依赖变得复杂时,咱们就须要一种简单好用的工具来帮助咱们管理。因而,make应运而生。html

make主要用来管理C/C++项目,经过Makefile书写的规则来对项目中的源代码文件进行编译,生成可执行的程序。node

make流程

make执行的主要过程以下:当在shell中使用make命令时,make会寻找当前目录下的Makefile文件,根据该文件中的规则来肯定依赖关系,若是一个文件所依赖的文件比这个文件要新,或者说修改时间更晚,那么make会根据Makefile中指明的命令来从新编译生成该文件。shell

另外,make除了自动寻找定义了编译规则的Makefile文件外,还能够手动指明定义了规则的文件。好比:工具

$ make -f rule.txt  # rule.txt中为make规则

Makefile的写法

规则

Makefile由一系列的规则构成,一条规则的基本格式以下:code

目标 : 条件 
[tab]  命令

其中,须要在命令以前加一个Tab制表符,而且条件和命令都是能够省略的,可是只能省略其一,条件省略时通常作一些编译之外的其余工做,当命令省略时其实也能够对目标进行编译生成,这涉及到了Makefile中的隐式规则,这里不过多赘述,咱们只讨论显式规则。htm

如make流程所述,当条件中的文件比目标要新时,会执行tab后的命令。ip

Makefile中有不少规则时,当在shell中执行make命令,默认会将第一条规则的目标做为最终生成的目标。ci

好比下面这个Makefile例子:开发

main: main.o sub.o
    gcc -o main main.o sub.o

sub.o: sub.c sub.h
    gcc -c -o sub.o sub.c

main.o: main.c sub.h
    gcc -c -o main.o main.c

clean:
    rm sub.o main.o

.PHONY: clean

当咱们在shell中执行make时,会最终生成main这个最终目标。get

可是若是咱们只想生成某个中间的目标也是能够的,好比只生成sub.o,只须要采用make 最终目标的形式就能够了,即make sub.o

注意到示例中省略了条件的那条规则(目标为clean的那条规则),正规上把它叫作伪目标,用来执行一些其余的任务,如本例中清除编译中生成的.o文件。固然,伪目标下的命令能够是多种多样的,好比将clean下的命令改成ls,当执行make clean时,会列出当前目录下的全部文件。可是有一点须要注意的是,若是咱们的目录下已经有了一个叫作clean的文件,当咱们执行make clean时,make就分不清这个clean究竟是那个了,为了不这种状况,须要用.PHONY: 伪目标1,伪目标2..的方式来显式的声明伪目标。

变量

当咱们Makefile中的规则变得很是多时,为了方便,也为了可维护性,咱们通常使用变量来代替某些信息。

Makefile中定义变量的格式以下:

变量名 := 变量值

其中:=也该以使用=,依我的喜爱。用$(变量名)的形式来使用变量。

先前示例中即可精简以下:

CC := gcc
LD := gcc
CFLAGS := -c
OBJS := main.o \
    sub.o

main: $(OBJS)
    $(LD) -o  main $(OBJS)

sub.o: sub.c sub.h
    $(CC) $(CFLAGS) -o sub.o sub.c

main.o: main.c sub.h
    $(CC) $(CFLAGS) -o main.o main.c

clean:
    rm $(OBJS)
.PHONY: clean

Tip: 有时候咱们的规则可能太长,写在一行又很差看,可使用\来进行换行。

内置变量

Makefile中还提供了一些内置变量,好比$(CC)表明默认的C编译器,$(CXX)表明默认的C++编译器。更多内置变量请参考这里

自动变量

Makefile中还提供了一些特殊的变量,不用定义且会根据所在的规则而改变,减小一些目标文件名和条件文件名的输入。如下是六个经常使用的自动变量:

变量名 做用
$@ 目标的文件名
$< 第一个条件的文件名
$? 时间戳在目标以后的全部条件,并以空格隔开这些条件
$^ 全部条件的文件名,并以空格隔开,且排除了重复的条件
$+ $^相似,只是没有排除重复条件
$* 目标的主文件名,不包含扩展名

根据以上自动变量,咱们能够将上面的示例改为更简便的形式:

CC := gcc
LD := gcc
CFLAGS := -c
OBJS := main.o \
    sub.o

main: $(OBJS)
    $(LD) -o $@ $^

sub.o: sub.c sub.h
    $(CC) $(CFLAGS) -o $@ $<

main.o: main.c sub.h
    $(CC) $(CFLAGS) -o $@ $<

clean:
    rm $(OBJS)
.PHONY: clean

后记

另外,尽管make工具经常用来管理C/C++项目,可是用来管理其余项目也是能够的,好比汇编项目,Pascal项目,甚至是node.js的项目,make就是一个工具,来帮咱们管理一些构建的规则,只要规则写的得当,怎么用就随你了。

最后,make虽然能够很好来管理项目了,可是仍是不够方便。试想一下,当Makefile中的规则愈来愈多,又臭又长的时候,make就又显得很难用了,这也就是为何cmake诞生的缘由。经过编写Cmakelist,来指导cmake生成各类Makefile文件和project文件,从而减轻管理Makefile的负担。


参考:

相关文章
相关标签/搜索