目标、依赖、命令
- 目标:要生成的文件名,可执行文件,或对象文件
- 依赖:生成目标所需要的文件和其他目标,位于目标后边
- 命令:创建目标文件所需要执行的命令
示例
target: dependencies
commands
$(TARGET) : $(OBJS)
$(CC) $(CXXFLAGS) $(OBJS) -o $(TARGET) $(LIBSPATH) $(LIBS)
详情请参考示例文件
注释
#
用于添加注释,从#
开始到该行末尾的所有内容都会被忽略。
Makefile变量
自动变量
简介
不需要明确定义的变量,在特定的上下文中自动获取值
说明
$@
表示规则中的目标文件$<
表示规则中第一个依赖文件名$^
表示规则中所有依赖文件列表以空格分割$?
表示比目标文件更新的依赖文件列表,以空格分割$*
表示目标文件去掉后缀的部分,在[[规则模式]]特别有用$+
类似于$^
,但它包括了重复的依赖文件
自定义变量
预定义变量也属于自定义变量
示例
请参考下方示例,此处为示例的解释
下面逐一解析这些自定义变量及其含义:
-
TARGET
:- 默认值为
./out/myjson.out
。 - 通过
?=
操作符赋值,意味着如果在调用 make 时没有指定TARGET
的值,则默认使用此值。 - 指定了构建的目标文件路径和名称。
- 默认值为
-
CC
:- 被设置为
g++
,指定了用于编译项目的 C++ 编译器。
- 被设置为
-
CXXFLAGS
:- 编译器选项,包括:
-g
:生成调试信息。-std=c++11
:使用 C++11 标准。-fno-elide-constructors
:禁用构造函数消除优化。-Wall
:打开大多数编译警告。-O2
:使用第二级别的优化。-pthread
:启用 POSIX 线程库的支持。
- 编译器选项,包括:
-
LIBSPATH
:- 指定库文件搜索路径,这里是
./lib
。
- 指定库文件搜索路径,这里是
-
LIBS
:- 链接的库,初始包含
-lyhlog
,后来添加了-lstdc++
。 - 使用
+=
进行追加,表明可能链接多个库。
- 链接的库,初始包含
-
INCDIRS
:- 包含的头文件目录,初始包括
include
、src
和src/protocol
。 - 使用
+=
追加目录。
- 包含的头文件目录,初始包括
-
SRCDIRS
:- 源文件目录,初始设置为
src
和src/protocol
。 - 也是使用
+=
追加目录。
- 源文件目录,初始设置为
-
INCLUDE
:- 根据
INCDIRS
中的目录生成的-I
包含标志,用于指示编译器查找头文件的目录。
- 根据
-
CFILES
:- 使用
foreach
和wildcard
函数,搜索SRCDIRS
中的所有.cpp
文件。
- 使用
-
CFILENDIR
:- 使用
notdir
函数从CFILES
中移除路径,只留下文件名。
- 使用
-
CXXOBJS
:- 将
CFILENDIR
中的.cpp
文件名后缀替换为.o
,并放入obj/
目录中,生成目标文件列表。
- 将
-
OBJS
:- 现在等同于
CXXOBJS
。这样设计可能是为了保留将来添加不同类型对象文件的灵活性。
- 现在等同于
-
VPATH
:- 用于指定 make 应该搜索源文件的目录列表。在这个 Makefile 中,它被设置为包含所有源文件目录的
SRCDIRS
。
- 用于指定 make 应该搜索源文件的目录列表。在这个 Makefile 中,它被设置为包含所有源文件目录的
整个构建过程中使用这些变量来控制编译器和链接器的行为,从而灵活地管理项目的构建过程。
引用变量
引用变量:使用 $(变量名)
的方式引用变量。
all:
$(CC) $(CFLAGS) main.c -o main
模式规则
- 使用
%
作为通配符,可以定义模式规则,来匹配多个目标。
makefileCopy code
%.o: %.c $(CC) $(CFLAGS) -c $< -o $@
伪目标
伪目标不是文件名,是一个标记执行特定任务
.PHONY:clean
clean:
rm -f *
示例
TARGET ?= ./out/test.out
CC := g++
CXXFLAGS := -g -std=c++11 -fno-elide-constructors -Wall -O2 -pthread
LIBSPATH := -L./lib
LIBS += -llog
LIBS += -lstdc++
INCDIRS := include
INCDIRS += src
SRCDIRS := src
INCLUDE := $(patsubst %, -I %, $(INCDIRS))
CFILES := $(foreach dir, $(SRCDIRS), $(wildcard $(dir)/*.cpp))
CFILENDIR := $(notdir $(CFILES))
CXXOBJS := $(patsubst %, obj/%, $(CFILENDIR:.cpp=.o))
OBJS := $(CXXOBJS)
#makefile会自动在 内置变量VPATH 中去找.cpp文件
VPATH := $(SRCDIRS)
.PHONY: clean
$(TARGET) : $(OBJS)
$(CC) $(CXXFLAGS) $(OBJS) -o $(TARGET) $(LIBSPATH) $(LIBS)
$(CXXOBJS) : obj/%.o : %.cpp
$(CC) $(CXXFLAGS) -c $(INCLUDE) -o $@ $<
clean:
rm -rf $(TARGET) $(CXXOBJS)