Makefile 笔记
处理流程
graph LR
A(预编译)-->B(编译)-->C(汇编)-->D(链接)
选项 |
含义 |
-c |
只编译不生成执行文件 |
-g |
调试 |
-o |
优化级别 |
-ldir |
编译时增加一个(或多个)搜索头文件的目录 |
-Ldir |
编译源文件是增加一个额外库文件目录 |
-Llibrary |
编译链接时增加额外的库 libxxx.so,去掉lib 和 .so |
-w |
禁止警告 |
-Wall |
产生所有警告,-Werror 把warning 当作error |
|
|
预定义变量
命令格式 |
含义 |
CXX |
C++ 编译器名称 |
RM |
清理名称(默认rm -f),跨平台使用 |
CXXFLAGS |
编译器选项 |
CPPFLAGS |
C预编译选项 |
CXXFLAGS |
C编译器选项 |
AR |
库文件维护程序名称,跨平台,默认ar,静态库编译使用 |
使用举例
makefile变量使用
命令格式 |
含义(命令都是字符串,可以拼接) |
$* |
不包含扩展名的文件名称 |
$+ |
所有的依赖文件,空格分开,可以重复 |
$< |
第一个依赖文件名称 |
$? |
所有时间戳比目标晚的依赖,空格分开 |
$@ |
目标的完整名称 |
$^ |
所有不重复的依赖文件,空格分开 |
$% |
目标是归档成员,该变量表示目标的归档成员名称 |
makefile格式
1 2 3
| taeget:depandence1 depandence2 [tab]command1 [tab]command2
|
1 2
| hellow:first.cpp data.cpp $(CXX) $^ -o $@ -lpthread
|
1 2 3
| TARGET=hellow $(TARGET):first.cpp data.cpp $(CXX) $^ -o $@ -lpthread
|
1 2 3 4 5 6
| TARGET=hellow OBJS=first.cpp data.cpp $(TARGET):$(OBJS) @$(CXX) $^ -o $@ -lpthread @echo "$(TARGET) build success!"
|
makefile格式 |
含义 |
$(…) |
变量展开 |
echo “…” |
打印输出 |
@… |
不显示命令 |
-… |
如果此行错误,继续执行下一行 |
CXXFLAGS |
编译选项(见下) |
.PHONY |
伪目标(见下) |
1 2 3 4 5 6 7 8 9 10 11
| TARGET=hellow OBJS=first.cpp data.cpp
CXXFLAGS=-I../test_gcc $(TARGET):$(OBJS) @$(CXX) $^ -o $@ -lpthread @echo "$(TARGET) build success!" clean: $(RM) $(OBJS) $(TARGET) .PHONY: clean *clean
|
创建动态库
1 2 3 4 5 6 7 8 9
| TARGET=libhello.so OBJS=hello.o LDFLAGS=-shared CXXFLAGS=-fPIC $(TARGET):$(OBJS) $(CXX) $(LDFLAGS) $^ -o $@ clean: $(RM) $(TARGET) $(OBJS) .PHONY: clean
|
查看动态链接.so文件的链接情况
调用动态链接库
1 2 3 4 5 6 7 8 9 10 11 12 13
| TARGET=mycode OBJS=mycode.o
CXXFLAGS=-I../hello
LDFLAGS=-L../hello
LIBS=-lhello $(TARGET):$(OBJS) $(CXX) $^ -o $@ $(CXXFLAGS) $(LDFLAGS) clean: $(RM) $(TARGET) $(OBJS) .PHONY: clean
|
还得在shell中设置LD_LIBRARY_PATH
LD_LIBRARY_PATH 是在运行的时候指定动态链接库,而LD_FLAGS 是指编译的时候寻找动态链接库
使用脚本进行创建run.sh
1 2 3
| —LD_LIBRARY_PATH=../hello export LD_LIBRARY_PATH ./mycode
|
创建静态库
静态库和动态库的区别在于,静态库只需要编译的时候寻找,动态库在编译的时候链接,而且运行的时候也要寻找.
1 2 3 4 5 6 7 8 9
| TARGET=libsta.a
OBJS=sta.o
$(TARGET):$(OBJS) $(AR) -cvr $@ $^ clean: $(RM) $(TARGET) $(OBJS) .PHONY: clean
|
调用静态库
在之前调用动态库的基础之上
1 2 3 4 5 6 7 8 9 10 11 12 13
| TARGET=mycode OBJS=mycode.o
CXXFLAGS=-I../hello -I../sta
LDFLAGS=-L../hello -L../sta
LIBS=-lhello $(TARGET):$(OBJS) $(CXX) $^ -o $@ $(CXXFLAGS) $(LDFLAGS) clean: $(RM) $(TARGET) $(OBJS) .PHONY: clean
|
MAKEFILE传递变量
这里就举例是将上面的创建静态库进行变量选择,是的其可以创建动态库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| TARGET=libsta
OBJS=sta.o
ifeq ($(STATIC),1) TARGET:=$(TARGET).a $(TARGET):$(OBJS) $(AR) -cvr $@ $^ else TARGRT:=$(TARGET).so LDFLAGS=-shared CXXFLAGS=-fPIC $(TARGET):$(OBJS) $(CXX) $(LDFLAGS)$^ -o $@ endif
clean: $(RM) $(TARGET) $(OBJS) .PHONY: clean
|
使用makeflie函数
函数 |
作用 |
wildcard() |
列出工作目录下所有匹配文件 |
patsubst(,,) |
替换text中的符合patten的文件,成为replace |
|
|
1 2 3 4
| SRC:=$(wildcard *.cpp) $(patsubst %.c,%.o,$(SRC))
|
额外
下面的CPP代码是头文件中防止多次引用的代码
1 2 3 4 5 6 7 8
| #ifndef HELLOW_H #define HELLOW_H include <thread> class{ }
#endif
|