博客首页:何与非的博客
欢迎关注点赞收藏⭐️留言
❤️ 期待一起交流!
作者水平很有限,如果发现错误,求告知,多谢!
有问题可私信交流!!!
Makefile步步为营第一步,简单玩玩
Makefile步步为营第二步,来点花活儿
Makefile步步为营第三步,来点真实的
Makefile步步为营第四步,整点动静
这是文章的第一节,简单介绍了make和Makefile,并且提供一个简单的例子进行展示,在之后的文章中也将使用这个例子进行展示。
在Windows下编程时,我们可以使用各种IDE省去手动进行编译链接的操作,但是在Linux下,经常只有黑黑的窗口显示在你面前,这时我们无法使用IDE来进行这些操作。不过还好Linux提供了make工具来帮助我们进行“自动化”。简单来说,make 是一个命令工具,它解释 Makefile 中的指令(应该说是规则)。Makefile 文件中描述了整个工程所有文件的编译顺序、编译规则。 我们把这些编译、链接规则写好在Makefile文件中后,在终端命令行中输入一个make,代码文件就自动生成了可执行的程序。
一个简单的 Makefile 描述规则组成:
TARGET... : PREREQUISITES...
COMMAND
...
...
target:规则的目标。通常是最后需要生成的文件名或者为了实现这个目的而必需的中间过程文件名。可以是.o 文件、也可以是最后的可执行程序的文件名等。另外,目标也可以是一个 make执行的动作的名称,如目标“clean”,我们称这样的目标是“伪目标”。
prerequisites:规则的依赖。生成规则目标所需要的文件名列表。通常一个目标依赖于一个或者多个文件。
command:规则的命令行。是规则所要执行的动作(任意的 shell 命令或者是可在 shell 下执行的程序)。它限定了 make 执行这条规则时所需要的动作。
一个规则可以有多个命令行,每一条命令占一行。
在这节和以后的各节里,我们都会使用这个例子里的代码文件来进行展示。以下是文件结构:
我们创建了2个.h文件和3个.c文件。其中fun_x表示函数,main文件表示测试文件。以下是各文件中的具体代码:
fun1.h
//fun1.h
#ifndef FUN1_H_
#define FUN1_H_
void fun1();
#endif
fun1.c
//fun1.c
#include
#include "fun1.h"
void fun1()
{
printf("this is fun1\n");
}
fun2.h
//fun2.h
#ifndef FUN2_H_
#define FUN2_H_
void fun2();
#endif
fun2.c
//fun2.c
#include
#include "fun2.h"
void fun2()
{
printf("this is fun2\n");
}
main.c
//main.c
#include
#include "fun1.h"
#include "fun2.h"
int main()
{
#ifdef USE_FLAG
printf("this is main\n");
#endif
fun1();
fun2();
printf("end\n");
}
代码文件已经写好了,但是却无法运行,这时就需要用到make和makefile了。下面是最基础的makefile写法:
makefile
#makefile
a.out:main.o fun1.o fun2.o
cc -o a.out main.o fun1.o fun2.o
main.o:main.c fun1.h fun2.h
cc -c main.c
fun1.o:fun1.c fun1.h
cc -c fun1.c
fun2.o:fun2.c fun2.h
cc -c fun2.c
clean:
rm a.out main.o fun1.o fun2.o
整个makefile的核心思想是把所有.c和其对应的.h文件编译生成.o文件,再将.c链接在一起生成a.out可执行文件。根据规则,我们已经将makefile写好了,将makefile与代码文件放在一起,打开终端输入一个make,gcc编译器就会自动的生成main.o、fun1.o、fun2.o、a.out文件,其中a.out文件就是可执行文件了,在终端中输入./a.out就能看到程序运行时在屏幕上打印出的信息。
此时我们已经使用make和makefile进行过一次实践了,接下来的几节主要结合make手册进行更新升级makefile,并且生成和使用静态库和动态库。
参考:
跟我一起写Makefile
make手册
makefile从入门到放弃——博主吐血整理的笔记