尝试编写makefile
参考链接:https://cs.colby.edu/maxwell/courses/tutorials/maketutor/
outline
0. 手动编译
1. make&makefile
2.文件结构
2. 尝试编写
3. 迭代优化
手动编译
$ gcc -o hello_world hello_world.c
翻译:用gcc编译器,把hello_world.c文件生成可执行文件hello_world,-o后面是目标文件的名字。
make&makefile
make工具:一般用于维护软件开发的工程项目。它可以根据时间戳自动判断项目的哪些部分是需要重新编译,每次只重新编译必要的部分。
makefile:make命令执行时读取的文件,内含编译项目的规则,包括依赖和命令。
文件结构
target: dependencies
command 1
command 2
...
command n
其中,target是我们构建(Build)的目标,而dependencies是构建该目标所需的其它文件或其他目标。
之后是构建出该目标所需执行的指令。
有一点尤为需要注意:每一个指令(command)之前必须有一个TAB。这里必须使用TAB而不能是空格,否则make会报错。
make 工具文件间的依赖关系:想要构建 target,那么首先要准备好 dependencies,接着执行 command 中的命令,然后target 就会最终完成。
在编写完恰当的规则之后,只需要在 shell 中输入 make target,即可生成相应的目标。 make 只有在依赖文件中存在文件的修改时间比目标文件的修改时间晚的时候 (也就是对依赖文件做了改动),shell 命令才被会执行,编译生成新的目标文件。
尝试编写&迭代优化
1.准备源文件3个
hellomake.c:
#include <hellomake.h>
int main() {
// call a function in another file
myPrintHelloMake();
return(0);
}
hellofunc.c:
#include <stdio.h>
#include <hellomake.h>
void myPrintHelloMake(void) {
printf("Hello makefiles!\n");
return;
}
hellomake.h
void myPrintHelloMake(void);
易得这个hellomake的程序从入口函数进入以后,调用myPrintHelloMake()函数,声明于.h文件,实现于hellofunc.c
2.手动编译:
gcc -o hellomake hellomake.c hellofunc.c -I .
包含 -I.,以便 gcc 将在当前目录(.)中查找包含文件 hellomake.h
(这里作死去试了一下,报错才发现没看到I后面的点点儿,才知道-I后面要加路径,写.h文件的位置就可以了)
(先忽略makefile)
3.编写makefile文件
version 1.0
hellomake: hellomake.c hellofunc.c
gcc -o hellomake hellomake.c hellofunc.c -I.
这个版本只是把原命令直接放到command里,起一个target名字,再把dependecy揪出来。
version 2.0
CC=gcc
CFLAGS=-I.
hellomake: hellomake.o hellofunc.o
$(CC) -o hellomake hellomake.o hellofunc.o
所以现在我们已经定义了常量CC和CFLAGS。事实证明,这些是特殊的常量,它们通过通信来决定我们想要如何编译文件hellomake.c和hellofunc.c。特别是,宏 CC 是要使用的 C 编译器,CFLAGS 是要传递给编译命令的标志列表。通过将对象文件 hellomake.o 和 hellofunc.o 放在依赖项列表和规则中,知道它必须首先单独编译.c版本,然后构建可执行的 hellomake。
对于大多数小型项目,使用这种形式的生成文件就足够了。但是,缺少一件事:对包含文件的依赖性。例如,如果要对 hellomake.h 进行更改,则 make 不会重新编译.c文件,即使它们需要重新编译。为了解决这个问题,我们需要告诉make所有.c文件都依赖于某些.h文件。我们可以通过编写一个简单的规则并将其添加到生成文件来执行此操作。
version 3.0
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: hellomake.o hellofunc.o
$(CC) -o hellomake hellomake.o hellofunc.o
宏 DEPS是.c文件所依赖的 .h 文件集。
然后,我们定义一个规则,该规则适用于以 .o 后缀结尾的所有文件。该规则指出,.o 文件取决于文件的.c版本和 DEPS 宏中包含的 .h 文件。然后,该规则指出,要生成 .o 文件,需要使用 CC 宏中定义的编译器编译 .c 文件。-c 标志表示生成对象文件,-o $ @ 表示将编译的输出放在 : 左侧命名的文件中,$<是依赖项列表中的第一项,CFLAGS 宏定义如上所示。
宏 $@ 和 $^,它们分别是 : 的左侧和右侧
version 3.5(final)
CC=gcc
CFLAGS=-I.
DEPS = hellomake.h
OBJ = hellomake.o hellofunc.o
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
hellomake: $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
加入宏OBJ存放目标文件
碎碎念
-I是要引用的引入文件的路径,如果与要编译的文件不再同一个目录下,要修改成相对应的路径。
不同makefile之间可以互相引用以实现各种各样的功能。
最最最重要的是:lab0已完成!