makefile使用总结(一)

发布时间 2023-04-01 15:55:18作者: 是对的人
本文参考《跟我一起写 Makefile》编写,并做了一些适合个人习惯的修改,稍加总结而成。
 
首先提出的问题是:什么是makefile?为什么要用makefile?如何使用makefile?
为了回答这三个问题,下面就围绕这些问题做一些记录。
  1. 什么是makefile?
简单点说 makefile 是一个描述了整个工程的编译规则的文件。
  1. 为什么要用makefile?
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,如何靠手动编译,那么无异于为自己找麻烦。此时就可以体现 makefile 带来的好处——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  1. 如何使用makefile?
好处很多,所以需要掌握如何使用它。
 
一、先了解下Makefile的规则
target ... : prerequisites ...
    command
    ...
看不懂,下面解释一下:
  • target是一个目标文件,可以是object file,也可以是执行文件。
  • prerequisites是要生成的target所需要的文件或是目标。
  • command也就是make需要执行的命令(任意的Shell命令),命令必须由[tab]开头。
target这一个或多个的目标文件依赖于prerequisites中的文件,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行。
 
二、再来一个示例看看Makefile怎么写。
edit : main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o
    cc -o edit main.o kbd.o command.o display.o \
    insert.o search.o files.o utils.o

main.o : main.c defs.h
    cc -c main.c
kbd.o : kbd.c defs.h command.h
    cc -c kbd.c
command.o : command.c defs.h command.h
    cc -c command.c
display.o : display.c defs.h buffer.h
    cc -c display.c
insert.o : insert.c defs.h buffer.h
    cc -c insert.c
search.o : search.c defs.h buffer.h
    cc -c search.c
files.o : files.c defs.h buffer.h command.h
    cc -c files.c
utils.o : utils.c defs.h
    cc -c utils.c

这个工程包含了3个头文件,和8个C文件。

反斜杠(\)是换行符的意思,这样比较便于Makefile的易读。我们可以把这个内容保存在文件为“Makefile”或“makefile”的文件中,然后在该目录下直接输入命令“make”就可以生成执行文件edit。

在这个makefile中,目标文件(target)包含:执行文件edit和中间目标文件(*.o),依赖文件(prerequisites)就是冒号后面的那些 .c 文件和 .h文件。每一个 .o 文件都有一组依赖文件,而这些 .o 文件又是执行文件 edit 的依赖文件。在定义好依赖关系后,后续的那一行定义了如何生成目标文件的命令。

编写完Makefile文件后,就需要使用make命令执行这个文件。

三、make工作机制

在默认的方式下,只输入make命令即可。然后:
  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“edit”这个文件,并把这个文件作为最终的目标文件。
  3. 如果edit文件不存在,或是edit所依赖的后面的 .o 文件的文件修改时间要比edit这个文件新,那么,他就会执行后面所定义的命令来生成edit这个文件。
  4. 如果edit所依赖的.o文件也不存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 .o 文件,然后再用 .o 文件生命make的终极任务,也就是执行文件edit了。
在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。记住,make并不管命令是怎么工作的,他只管执行所定义的命令。
在我们编程中,如果这个工程已被编译过了,当我们修改了其中一个源文件,比如file.c,那么根据我们的依赖性,我们的目标file.o会被重编译,于是file.o的文件也是最新的啦,file.o的文件修改时间要比edit要新,所以edit也会被重新链接了。
 
Makefile和make的简单使用是没什么问题,碰到需要复杂的工程就需要继续学习Makefile其他知识了,为了文章简洁点,就放在下一个篇幅了。