1. Makefile基本语法与执行
作用: Makefile 文件告诉 Make 怎样编译和连接成一个程序
可用命令 dnf install make 安装make功能
格式: 按如下格式编写 Makefile
目标(target): 依赖(prerequiries)...
命令(command)
注意:每个命令行前面必须是一个Tab字符,即命令行第一个字符是Tab
实验: vim Makefile 编辑文件:
simpletest:simple.o simpletest.o
g++ simple.o simpletest.o -o simpletest
simple.o:simple.cpp
g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
g++ -c simpletest.cpp -o simpletest.o
结果为:
[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest
命令上下是有顺序的,上一行对下一行具有依赖关系
如果文件夹中已经有.o文件,make后会提示已经生成,需要删除.o文件后再make
clean的作用: 被指定时会删除对应.o文件,避免上述情况
simpletest:simple.o simpletest.o
g++ simple.o simpletest.o -o simpletest
simple.o:simple.cpp
g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
g++ -c simpletest.cpp -o simpletest.o
clean:
rm simpletest simple.o simpletest.o
结果为:
[root@foundation1 shishi]# make clean
rm simpletest simple.o simpletest.o
[root@foundation1 shishi]# make
g++ -c simple.cpp -o simple.o
g++ -c simpletest.cpp -o simpletest.o
g++ simple.o simpletest.o -o simpletest
2. Makefile简化过程
使用变量: 如果调用某个文件用的次数较多,可以使用变量代替,变量可以直接替换
变量定义: 变量 = 字符串
变量使用: $(变量名)
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o simpletest.o
$(TARGET):$(OBJS)
g++ $(OBJS) -o $(TARGET)
simple.o:simple.cpp
g++ -c simple.cpp -o simple.o
simpletest.o:simpletest.cpp
g++ -c simpletest.cpp -o simpletest.o
clean:
rm $(TARGET) $(OBJS)
命令自动推导: 我们可以发现,由于 .cpp 文件都是生成对应的 .o 文件,所以 makefile 文件是可以自动识别的
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o simpletest.o
$(TARGET):$(OBJS)
g++ $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
rm $(TARGET) $(OBJS)
预定义变量: 系统中自己也定义了一些变量
变量 | 程序 | 默认值 |
---|
CC | C语言编译程序 | cc | CXX | C++编译程序 | g++ | AR | C++打包程序 | ar | CPP | 带有标准输出的C语言预处理程序 | $(CC) -E | RM | 删除命令 | rm |
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o simpletest.o
$(TARGET):$(OBJS)
$(CXX) $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
$(RM) $(TARGET) $(OBJS)
假想目标: 如果文件夹中有clean文件,那么make clean就不能使用,需要使用假想目标,可以在执行命令时不查看文件夹里面的文件,直接生效
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o simpletest.o
.PHONY: clean
$(TARGET):$(OBJS)
$(CXX) $(OBJS) -o $(TARGET)
simple.o:simple.cpp
simpletest.o:simpletest.cpp
clean:
$(RM) $(TARGET) $(OBJS)
建议不生成目标文件的命令都设为假想目标
3. Makefile生成并使用库
3.1 动态库的建立与使用
vim Makefile 编辑文件:
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
.PHONY: clean
$(TARGET):$(LIB) simpletest.o
$(CXX) simpletest.o -o $(TARGET) -L. -lsimple
$(LIB):$(OBJS)
$(CXX) -shared $(OBJS) -o $(LIB)
simple.o:simple.cpp
$(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS)
simpletest.o:simpletest.cpp
$(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o
clean:
$(RM) $(TARGET) $(OBJS) $(LIB)
结果为:
[root@foundation1 shishi]# make clean
rm -f simpletest simple.o libsimple.so
[root@foundation1 shishi]# make
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ -c -fPIC simpletest.cpp -o simpletest.o
g++ simpletest.o -o simpletest -L. -lsimple
预定义变量: 还是需要在前面定义
变量 | 程序参数 |
---|
CFLAGS | 用于C编译器的额外标志 | CXXFLAGS | 用于C++编译器的额外标志 | ARFLAGS | 用于C/C++打包器的额外标志 | LDFLAGS | 链接库路径-L | LDLIBS | 链接库-l |
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
.PHONY: clean
$(TARGET):$(LIB) simpletest.o
$(CXX) simpletest.o -o $(TARGET) $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS)
$(CXX) -shared $(OBJS) -o $(LIB)
simple.o:simple.cpp
$(CXX) $(CXXFLAGS) simple.cpp -o $(OBJS)
simpletest.o:simpletest.cpp
$(CXX) $(CXXFLAGS) simpletest.cpp -o simpletest.o
clean:
$(RM) $(TARGET) $(OBJS) $(LIB)
自动变量: 自动变量是在规则每次执行时都基于目标和依赖产生新值的变量
自动变量 | 含义 |
---|
$< | 表示第一个匹配的依赖 | $@ | 表示目标 | $^ | 所有依赖 | $? | 所有依赖中更新的文件 | $+ | 所有依赖文件不去重 | $(@D) | 目标文件路径 | $(@F) | 目标文件名称 |
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
.PHONY: clean
$(TARGET):simpletest.o $(LIB)
$(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS)
$(CXX) -shared $^ -o $@
simple.o:simple.cpp
$(CXX) $(CXXFLAGS) $< -o $@
simpletest.o:simpletest.cpp
$(CXX) $(CXXFLAGS) $< -o $@
clean:
$(RM) $(TARGET) $(OBJS) $(LIB)
自动匹配: 通配符主要用于匹配文件名,makefile中使用%作为通配符。从匹配目标格式的目标名中依据通配符抽取部分字符串,再按照抽取字符串分配到每一个依赖格式中产生依赖名。例如,使用%.o:%.cpp
可以让重复的语句合为一句
makefile 文件可改为:
TARGET = simpletest
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDFLAGS = -L.
LDLIBS = -lsimple
TESTOBJ = simpletest.o
.PHONY: clean
$(TARGET):$(TESTOBJ) $(LIB)
$(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
$(LIB):$(OBJS)
$(CXX) -shared $^ -o $@
$(TESTOBJ) $(OBJS):%.o:%.cpp
$(CXX) $(CXXFLAGS) $< -o $@
clean:
$(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)

3.2 动态加载库的建立与使用
TARGET = simpletest2
OBJS = simple.o
LIB = libsimple.so
CXXFLAGS = -c -fPIC
LDLIBS = -ldl
TESTOBJ = simpletest2.o
.PHONY: clean
# 生成可执行文件
$(TARGET):$(TESTOBJ) $(LIB)
$(CXX) $< -o $@ $(LDFLAGS) $(LDLIBS)
# 生成库
$(LIB):$(OBJS)
$(CXX) -shared $^ -o $@
# 生成目标文件
$(TESTOBJ) $(OBJS):%.o:%.cpp
$(CXX) $(CXXFLAGS) $< -o $@
clean:
$(RM) $(TARGET) $(OBJS) $(LIB) $(TESTOBJ)
结果为:
[root@foundation1 C++7.4]# make clean
rm -f simpletest2 simple.o libsimple.so simpletest2.o
[root@foundation1 C++7.4]# make
g++ -c -fPIC simpletest2.cpp -o simpletest2.o
g++ -c -fPIC simple.cpp -o simple.o
g++ -shared simple.o -o libsimple.so
g++ simpletest2.o -o simpletest2 -ldl
[root@foundation1 C++7.4]# ./simpletest2
Simple()
Test()
~Simple()
|