目录
1、简介
2、语法规则
3、变量
4、函数
5、伪目标.PHONY
6、嵌套执行makefile
7、makefile示例
8、gcc编译选项
基本选项
调试选项
优化选项
警告选项
语言选项
链接选项
预处理选项
其他选项
1、简介
makefile是一个用于自动化构建程序的脚本文件,它包含一组规则,这些规则描述了如何从一个或多个源文件(如.c/.cpp文件)编译生成目标文件(如.o文件)再链接生成可执行文件(如.exe文件)或库(如.dll文件)。makefile的好处就是自动编译,只需一个make命令就能完成整个工程的编译。
gcc:可以简单的认为是编译器,它可以编译多种语言(如C、C++、Java等)。我们的程序中包含很多的源文件,都可以用gcc命令逐个编译,但当源文件太多时就容易混乱且工作量大,这时就需要批量处理,因此就有了make工具。
make:可以看成是一个智能的批处理工具,它没有编译和链接功能,而是通过执行makefile文件中用户指定的命令来完成编译和链接。
makefile:该文件中包含了调用gcc去编译某个源文件的命令。当工程非常大时,手写makefile也比较麻烦,因此就有了cmake工具辅助生成makefile文件。
cmake:也有自己的一套规则,它根据CMakeLists.txt文件更简单的生成makefile文件。
那有没有更简单的工具来生成CMakeLists.txt文件呢?
答:no,这就需要自己动手了。
2、语法规则
目标 ... : 依赖 ...命令1命令2. . .
目标:即要生成的文件,默认情况下makefile的第一个目标为终极目标;
依赖:即生成目标文件所需要的源文件;
命令:即通过执行命令由依赖文件生成目标文件,注意每条命令之前必须有一个tab;
all:makefile文件默认只生成第一个目标文件即完成编译,但我们可以通过all指定所需要生成的目标文件。
all: target1 target2 target3
target1:
# 编译规则1
target2:
# 编译规则2
target3:
# 编译规则3
3、变量
‘$’符号通常表示取变量的值,当变量名多于一个字符时,使用"( )";
‘$^’ 表示所有的依赖文件;
‘$@’ 表示生成的目标文件;
‘$<’ 表示第一个依赖文件;
‘:=’ 符号用于变量赋值(当前值);
‘=’ 符号用于变量赋值(整个makefile中最后被指定的值);
‘?=’ 符号表示如果该变量没有被赋值,则赋值等号后的值;
‘+=’ 符号表示将符号后面的值追加到前面的变量上;
4、函数
# 匹配当前目录下所有.c文件
SRC = $(wildcard *.c)# 将SRC中所有文件名中的.c替换成.o
OBJ = $(patsubst %.c, %.o, $(SRC))ALL: hello.outhello.out: $(OBJ)gcc $(OBJ) -o hello.out%.o: %.cgcc -c $< -o $@clean:rm -rf $(OBJ) hello.out.PHONY: clean ALL
wildcard:是make工具提供的一个函数,用于查找匹配模式的所有文件名;
patsubst:该函数用于匹配模式替换,基于一种模式替换文本字符串中另一部分;
5、伪目标.PHONY
为目标只是个标签,clean是个伪目标,没有依赖文件,只有make来调用时才执行;
6、嵌套执行makefile
在一些大工程中,会把不同模块的源文件放在不同目录中,我们可以在每个目录中都写一个makefile,这有利于让我们的makefile更简洁。列如在子目录subdir目录下有个Makefile文件,来指明这个目录下文件的编译规则。外部总控Makefile可以这样写
subsystem:cd subdir && $(MAKE)
其等价于:
subsystem:$(MAKE) -C subdir
如果需要传递变量到下级makefile中,可以这样写
export variable := value
如果不想传递变量到下级makefile中,可以这样写
unexport variable := value
7、makefile示例
假设有一个项目结构如下:
myproject/
├── Makefile # 主Makefile
├── src/
│ ├── main.c
│ └── Makefile # src目录的Makefile
└── include/ └── myheader.h
主makefile
# myproject/Makefile # 设置编译器和编译选项
CC=gcc
CFLAGS=-Wall -Iinclude # 定义子目录
SUBDIRS=src # 默认目标
all: $(SUBDIRS) # 伪目标,用于构建子目录
.PHONY: $(SUBDIRS) # 递归地调用子目录中的Makefile
$(SUBDIRS): $(MAKE) -C $@ # 清理目标,也递归地调用子目录中的清理目标
clean: for dir in $(SUBDIRS); do \ $(MAKE) -C
$$
dir clean; \ done # 安装目标(示例)
install: # 这里你可以添加安装命令,比如复制到某个目录 echo "Installing project..." # 卸载目标(示例)
uninstall: # 这里你可以添加卸载命令,比如从某个目录删除文件 echo "Uninstalling project..."
src目录下makefile
# myproject/src/Makefile # 假设我们有一个名为main的目标文件
OBJ=main.o # 链接main.o生成可执行文件
main: $(OBJ) $(CC) $(CFLAGS) -o $@ $^ # 编译main.c生成main.o
%.o: %.c $(CC) $(CFLAGS) -c $< -o $@ # 清理目标
clean: rm -f $(OBJ) main # 依赖项(如果需要)
# DEPS = ...
# ...(依赖项的处理)
8、gcc编译选项
GCC(GNU Compiler Collection)提供了大量的编译选项,这些选项允许用户定制编译过程以满足不同的需求。以下是一些常用的GCC编译选项的概述:
基本选项
-c
:只编译不链接,生成目标文件(.o)。-o <output_file>
:指定输出文件名。-S
:只进行编译预处理和汇编,生成汇编文件(.s)。-E
:只进行编译预处理,生成预处理后的文件(通常是.i文件,但默认输出到标准输出)。
调试选项
-g
:生成调试信息,使调试器(如GDB)能够使用。-ggdb
:生成GDB可以使用的调试信息。-g3
:生成包含额外调试信息的调试信息。
优化选项
-O0
:不进行优化(默认)。-O1
:进行基本优化。-O2
:进行更多的优化,但不增加编译时间太多。-O3
:进行更多的优化,可能会增加编译时间。-Os
:优化生成代码的大小。-Ofast
:进行所有可能的优化,包括那些可能改变程序行为的优化(如浮点运算的舍入模式)。
警告选项
-Wall
:显示所有警告信息。-Wextra
:显示额外的警告信息。-Werror
:将警告信息当作错误处理。-Wno-<warning>
:禁用指定的警告(例如,-Wno-unused-variable
禁用未使用变量的警告)。
语言选项
-std=<standard>
:指定C或C++语言标准(如-std=c99
、-std=c++11
)。-fPIC
:生成位置无关代码(Position Independent Code),常用于共享库。-fPIE
:生成位置无关的可执行文件。
链接选项
-L<directory>
:添加库文件的搜索目录。-l<library>
:链接指定的库(如-lm
链接数学库)。-static
:静态链接库(而不是默认的动态链接)。-shared
:生成共享库(动态链接库)。
预处理选项
-I<directory>
:添加头文件搜索目录。-D<macro>
:定义宏(如-DDEBUG
)。-U<macro>
:取消定义宏。
其他选项
-v
:显示详细的编译和链接过程。-version
:显示GCC版本信息。-M
:生成依赖关系(通常是预处理器的依赖关系),但不编译。-MM
:与-M
类似,但忽略系统头文件。-MP
:生成phony目标,以便在头文件更改时重新编译。-MT
:指定目标名称,通常与-M
、-MM
一起使用。
这只是一个GCC编译选项的简要概述,GCC还提供了许多其他选项和功能。要获取完整的选项列表和详细信息,请查阅GCC的官方文档或使用gcc --help
命令。