1 介绍
Makefile 是 linux 下的项目管理工具,想象一下当有很多源文件需要编译、链接时,你只需执行 make命令即可完成编译操作,这样是不是很方便呢。make 命令执行时,需要一个 Makefile 文件,用来告诉 make命令需要怎么样的去编译和链接程序,下面详细介绍 Makefile 的使用与书写规则
2 makefile 书写规则
Makefile 里面的规则由“目标:依赖命令”组成。例如,以一个最简单 Makefile 文件为例,有一个源程序 hello.c 文件,编写 Makefile 文件编译生成可执行文件 hello,Makefile 内容如下:
hello:hello.cgcc hello.c -o hello
clean:rm -f hello
当执行 make 命令后,make 会在当前目录下找名字叫“Makefile”或“makefile”的文件。如果找到,它会找文件中的第一个目标文件(hello),并把这个文件作为最终的目标文件。如果 hello 文件不存在,或是 hello所依赖的文件的文件修改时间要比 hello 这个文件新,那么,他就会执行后面所定义的命令来生成 hello 这个文件。
像 clean 这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行,不过,我们可以显示要 make 执行。即命令——“make clean”,以此来清除所有的目标文件,以便重编译。
注意:命令前面是以一个 Tab 键缩进,不能使用空格代替,所以 gcc hello.c -o hello 和 rm -f hello 前面是一个 Tab 键,切记!
3 Makefile 变量使用
当有很多源文件,头文件需要包含的时候,依赖项和编译命令的书写变得很麻烦,尤其当需要修改的时候,写的到处都是,很容易出错,这时候我们可以使用变量来方便我们的书写。
举个例子,有源文件 test1.c、test2.c、test3.c 编译生成可执行程序 test,Makefile 内容如下:
objects = test1.c test2.c test3.c
test: $(objects)gcc -o test $(objects)
clean:rm -f test
如例子中所写的,我们创建了一个 objects 变量,它的值是我们的依赖文件,这样在下面用到依赖文件的时候,可以用$(objects)来替代,这样做的好处就是,当我们需要修改依赖文件的时候,只需要修改 objects的值即可,便于维护。
Makefile 有三个非常有用的变量。分别是 @ , @, @,^,$<,代表的意义分别是:
$@:目标文件;
$^:所有的依赖文件;
$<:第一个依赖文件。
objects = test1.c test2.c test3.c
test: $(objects)
gcc -o $@ $^
clean:
rm -f test
4 输出 “Hello World
4.1 使用vim 编辑
#include <stdio.h>
int main()
{printf("hello world \n");return 0;
}
按“i”或者“a”进入编辑模式,将上面的代码录入进去,完成后按 Esc 键进入命令状态,再用命令“:wq”保存并退出。这样我们便在当前目录下建立了一个名为 hello.c 的文件。
4.2 运行和编译程序
gcc hello.c -o hello./hello
4.3 makefile 编译
CC = gcc
EXEC = hello
OBJS = hello.o
all: $(EXEC)
$(EXEC): $(OBJS)
$(CC) -W -Wall -o $@ $(OBJS)
.PHONY: clean
clean:
-rm -f $(EXEC) *.elf *.gdb *.o
CC,EXEC,OBJS,$@是 Makefile 文件中定义的变量,与 C/C++中的宏一样,代表了一个文本字符串,在 Makefile 中执行时会自动原模原样的展开在所使用的地方。与 C/C++不同的是,可以在 MAkefile 中改变它的值,在 Makefile 中,变量可以使用在”目标“、”依赖“、”命令“、或是 Makefile 的其它部分中。
- CC 指明编译器
- EXEC 表示编译后生成的执行文件名称
- OBJS 目标文件列表
- all: 编译主入口
- .PHONY: Makefile 关键字,其后面的目标为伪目标
- clean: 清除编译结果
宿主机 ubuntu 的命令行 root@imax:~ ,表示 r o o t 用户,主机名 i m a x ,主目录 , ,表示 root 用户,主机名 imax,主目录~, ,表示root用户,主机名imax,主目录 , 是普通用户,#是超级用户 root