Makefile简介

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,静态库编译使用

​ 使用举例

1
$(CXX)

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 可以添加头文件路径
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
$ldd libxxx.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
#具体引用库文件,动态库去掉lib和.so,记得添加动态库引用的库
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部分可以自动推导,自己使用.o就行,会自己编译 .h,.cpp文件
OBJS=sta.o
# -c不显示创建过程,-v显示其他过程,-r表示创建静态库
$(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
#具体引用库文件,动态库去掉lib和.so,记得添加动态库引用的库
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部分可以自动推导,自己使用.o就行,会自己编译 .h,.cpp文件
OBJS=sta.o
# -c不显示创建过程,-v显示其他过程,-r表示创建静态库
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
#将目录下的cpp文件全部放入SRC,然后将他们替换成.o文件
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

Makefile简介
http://home.ustc.edu.cn/~ustcxwy0271/2022/05/16/makefile-1/
作者
Xu Weiye
发布于
2022年5月16日
许可协议