Linux系统中编译大型C语言项目必备技能之:Makefile文件的编写

文章目录

    • Makefile的介绍
    • Makefile的编写规范——简单举例
    • Makefile的编写规范——复杂举例
      • 项目描述
      • 编译需求
      • 编译思路

Makefile的介绍

我们在阅读一些大型的C语言项目时,通常会在项目文件夹中看到一个名为makefile的文件。Makefile是Linux系统中用于编译C语言项目的一种编译脚本,传统的Linux通过gcc工具在命令行输入命令来编译C语言程序,但当需要编译的c文件过多时,频繁的输入编译指令显得十分繁琐。makefile文件能够帮助我们更快速更方便的编写C语言项目。

Makefile的编写规范——简单举例

以一个简单的例子来说明,当我们需要编译一个名为test.c的c语言文件时,我们通常需要在终端输入以下指令:

gcc test.c -o test

当然,这句指令同样可以写入makefile文件中。想要使用makefile来编译以上的代码,我们需要在代码所在文件夹新建一个名为Makefile的文件(写作makefile同样可以,目前的系统对于第一个字母m是否为大小写均认可),并输入以下内容:

test: test.c
	gcc test.c -o test

以上是makefile最简单的一种写法,它的含义为:
第一行:第一行顶头的test表示你想要生成的可执行文件名称,后面接一个冒号,冒号后的test.c表示生成该可执行文件所需要的依赖文件。

第二行:gcc编译指令。这里需要注意的是编译指令前必须用tab隔开,如果自己的编辑器不会自动替你用tab隔开,务必加上一个tab。四个空格都不行,必须是tab。

那么以上就是一种最简单的makefile文件的写法。写好该文件后,下次的编译只需要在终端输入:

make

即可代替原本的编译指令,完成对项目的编译了。

当然以上的写法只是最简单的一种写法,接下来我们看一个复杂的项目。

Makefile的编写规范——复杂举例

项目描述

我们有以下几个文件:
main_max.c
main_min.c
max.c
min.c
util.c
command.c
max.h
min.h
util.h
command.h

其中main_max.c和main_min.c是两个包含main函数的程序,
max.c,min.c,util.c和command.c是一些函数的文件,
max.h,min.h,util.h和command.h是其对应的头文件。

编译需求

我们需要将这些c文件和h文件编译出两个可执行文件,分别为main_max和main_min,
main_max需要使用max.c,util.c和command.c中的函数,
main_min需要使用min.c,util.c和command.c中的函数,
编译时需要加上链接选项-lm及debug选项-g。

编译思路

main_max可执行文件的依赖文件,除了包含main_max.c,还包含max.o,util.o和command.o。其中.o文件指.c文件编译出的目标文件。
而max.o文件,又可以通过max.c和max.h文件编译生成,其他同理。故我们可以采用以下写法:

CC = gcc
CFLAGS = -lm -g

all: main_max main_min

main_max: main_max.c max.o util.o command.o
	$(CC) $(CFLAGS) main_max.c max.o util.o command.o -o main_max

main_min: main_min.c min.o util.o command.o
	$(CC) $(CFLAGS) main_max.c min.o util.o command.o -o main_max

max.o: max.c
	$(CC) $(CFLAGS) -c max.c

min.o: min.c
	$(CC) $(CFLAGS) -c min.c

util.o: util.c
	$(CC) $(CFLAGS) -c util.c

command.o: command.c
	$(CC) $(CFLAGS) -c command.c
	
clean:
	rm *.o main_max main_min
	
.PHONY: all clean

以上内容看起来有些复杂,让我们看一下它与上面简洁版的有什么不同

第一行中的 CC = gcc
表示makefile中的变量。当我们在makefile文件需要频繁输入某段内容时,如gcc,链接指令等,可以将其写成便于理解与修改的变量,在下文将要写到该内容时,用 $(变量名称) 即可表示。这样也方便对重复的内容进行修改。

最后的.PHONY: all clean
.PHONY表示一个声明,声明的含义为冒号后面的内容是一个伪目标。
伪目标是一类不需要在文件中编译出来的目标,如这里的all的作用为批量生成多个可执行文件。如果没有此处的all,makefile文件在执行完第一个命令生成main_max之后,便不再继续生成main_min。需要在第四行处用伪目标all列出所有需要编译出的可执行文件,才能够批量编译。

目标(.o)文件的编译
如max.o文件的编译,需要在其依赖文件也就是.c文件前,加上一个-c选项,意为将该C文件编译为目标文件。先编译为目标文件的好处是,如果我们使用了这种编译方法,那么我们在之后修改代码的过程中,如果修改了其中一个.c文件,其他的.c文件没有修改,那么编译时我们只会对修改的.c文件进行重新编译,而不会对其他文件重复的编译,在工程量大的时候,节省了整个编译过程的时间。

clean命令
通过这种编译方式,会生成可执行文件和大量的目标文件,有时,当我们需要将自己的源代码发布出来的话,文件夹里的目标文件和可执行文件一般都是需要删除掉的。这时就需要使用clean功能。clean命令后是一段Linux的rm指令,“*.o”表示文件夹内所有后缀为.o的文件。在makefile中加入的clean的指令后,我们在终端输入:

make clean

这段指令,即可将所有目标文件和可执行文件全部删除了。

以上就是一段结构完整的makefile文件,当然makefile文件远不止这些功能,更多的功能我们需要通过之后的学习慢慢领悟。

你可能感兴趣的:(linux,c语言)