目标:依赖条件
(一个tab缩进)命令
案例,
比如我在一个目录下,有一个.cpp文件,
我想编译这个文件的代码,生成可执行文件
first_make:first_make.cpp
g++ first_make.cpp -o first_make -lpthread
first_make就是要生成的目标文件,也就是可执行文件,
first_make.cpp就是依赖条件,
g++ first_make.cpp -o first_make -lpthread就是命令。
命令前面要有一个 Tab 键的缩进。
编写完成后,在控制台输出 “make” 命令即可
上一节中,我们只创建且编译了一个 first_make.cpp 的文件
现在我们创建如下几个文件
xdata.h
xdata.cpp
first_make.cpp
其中 first_make.cpp 包含了 xdata.h 头文件,xdata.cpp 也包含了 xdata.h 头文件
first_make:first_make.cpp xdata.cpp
g++ first_make.cpp xdata.cpp -o first_make -lpthread
gcc常用选项
1, -c
仅对源文件进行编译,不链接生成可执行文件。在对源文件进行查错 时,或只需产生目标文件时可以使用该选项。
2,-g
生成调试信息。
3,-0 [ 0,1,2,3 ]
对生成代码使用优化, 中括号中的部分为优化级别,缺省的情况为2级优化,0为不进行优化。注意,采用更高级的优化并不一定得到效率更高的代码。
4,-Idir
在编译源文件时增加一个搜索库文件的额外目录------dir
即include增加一个搜索的额外目录
5,-Ldir
在编译源文件时增加一个搜索库文件的额外目录------dir
6,-llibrary
在编译链接文件时增加一个额外的库,库名为liblibrary.so
7,-w
禁止所有警告
8,-W
允许产生warning类型的警告。
9,-o
生成二进制编码文件
命令格式 | 含义 |
---|---|
AR | 库文件维护程序的名称,默认值为ar |
AS | 汇编程序的名称,默认值为as |
CC | C编译器的名称,默认值为cc |
CPP | C预编译器的名称,默认值为 $(CC)-E |
CXX | C++编译器的名称,默认值为 g++ |
FC | FORTRAN编译器的名称,默认值为f77 |
RM | 文件删除程序的名称,默认值为rm-f |
ARFLAGS | 库文件维护程序的选项,无默认值 |
ASFLAGS | 汇编程序的选项,无默认值 |
CFLAGS | C编译器的选项,,无默认值 |
CPPFLAGS | C预编译器的选项,无默认值 |
CXXFLAGS | C编译器的选项,无默认值 |
FFLAGS | FORTRAN编译器的选项,无默认值 |
命令格式 | 含义 |
---|---|
$* | 不包含扩展名的目标文件名称 |
$+ | 所有的依赖文件,以空格分开,并以出现的先后的序,可能包含重复的依赖文件 |
$< | 第一个依赖文件的名称 |
$? | 所有时间戳比目标文件晚的依赖文件,并以空格分开 |
$@ | 目标文件的完整名称 |
$^ | 所有不重复的依赖文件,以空格分开 |
$% | 如果目标是归档成员,则该变量表示目标的归档成员名称 |
用上述表格中的命令对makefile进行简化
原文件
first_make:first_make.cpp xdata.cpp
g++ first_make.cpp xdata.cpp -o first_make -lpthread
变量简化
# first_make
# $^ 依赖 不重复
# $@ 目标
first_make:first_make.cpp xdata.cpp
$(CXX) $^ -o $@ -lpthread
我们已经用了系统自带的变量进行了简化,接下来我们可以自己定义变量并简化。
自定义变量简化
# first_make
# $^ 依赖 不重复
# $@ 目标
# @ 不显示执行命令
TARGET=first_make
$(TARGET):first_make.cpp xdata.cpp
@$(CXX) $^ -o $@ -lpthread
echo "build success"
其中,TARGET 为自定义的变量。
我在当前目录下创建三个文件
test.h
test.cpp
main.cpp
我在test.h/test.cpp中写了一些程序,封装了一些接口,我想制作一个动态库,让main.cpp可以通过引用动态库来调用这些接口。
第一步:生成动态库文件(.so)文件
要注意,动态库的名字必须是以lib为开头,.so为后缀
g++ -shared -fPIC test.cpp -o libtest.so
第二步:编译main.cpp文件,引入动态库生成可执行文件main。
-ltest 表示引入名为 libtest.so的动态库
-L./ 表示动态库所在的路径为 ./
-o main 表示要生成的可执行文件为 main
g++ main.cpp -ltest -L./ -o main
第三步:添加环境变量, ./为动态库所在的路径
export LD_LIBRARY_PATH=./
第四步:运行可执行文件
./main
自动推导参数设置 CPPFLAGS
.PHONY clean清理 伪目标
有些依赖文件会由系统自动推导出来,比如 .o 文件
例如,依赖项改为 -o ,系统自动推导,就会自动先生成 .o 文件。
# first_make
# $^ 依赖 不重复
# $@ 目标
# @ 不显示执行命令
TARGET=first_make
$(TARGET):first_make.o xdata.o
@$(CXX) $^ -o $@ -lpthread
echo "build success"
如上段所示,本目录中存在 first_make.cpp 和 xdata.cpp 文件,并不存在 first_make.o xdata.o 文件,那么我们make运行
我们看到系统自动推导,自动线生成了连个.o文件。
makefile还有一种功能就是自动清理功能,清理的目标我们称之为伪目标。
当我们改动了代码需要重新编译时,就需要线清理之前生成的一些文件
# first_make
# $^ 依赖 不重复
# $@ 目标
TARGET=first_make
CXXFLAGS=-I../test_gcc
OBJS=first_make.o xdata.o
$(TARGET):$(OBJS)
@$(CXX) $^ -o $@ -lpthread
clean:
$(RM) $(OBJS) $(TARGET)
.PHONY: clean *clean
make clean