Makefile #
xxx.mk 文件或者 Makefile 都统称为 Makefile 脚本文件
功能:指导 Make 软件控制 arm-gcc 等工具链去编译工程文件最终得到可执行文件
基础规则 #
目标:依赖条件
命令
拓展
#.mk-V0
#根据工作原理,如果只改变其中一个文件,就只会编译这个文件
hello: main.cpp printhello.cpp factorial.cpp
g++ -o hello main.cpp printhello.cpp factorial.cpp
#.mk-V1
#使用变量CXX、TARGET 、OBJ,同时采用不同的依赖分别编译
#根据工作原理,如果只改变其中一个文件,就只会编译这个文件
CXX = g++
TARGET = hello
OBJ = main.o printhello.o factorial.o
$(TARGET): $(OBJ)
$(CXX) -o $(TARGET) $(OBJ)
main.o: main.cpp
$(CXX) -c main.cpp
printhello.o: printhello.cpp
$(CXX) -c printhello.cpp
factorial.o: factorial.cpp
$(CXX) -c factorial.cpp
##.mk-V2: ALL
#makefile 默认第一个目标文件为终极目标,生成就跑路,这时候可以用 ALL 来指定终极目标。
CXX = g++
TARGET = hello
OBJ = main.o printhello.o factorial.o
ALL : $(TARGET)
$(TARGET): $(OBJ)
$(CXX) $(OBJ) -o $(TARGET)
main.o: main.cpp
$(CXX) -c main.cpp
printhello.o: printhello.cpp
$(CXX) -c printhello.cpp
factorial.o: factorial.cpp
$(CXX) -c factorial.cpp
#.mk-V3: wildcard & patsubst
src = $(wildcard ./*.c) #匹配当前工作目录下的所有.c 文件
obj = $(patsubst %.c, %.o, $(src)) # 将参数 3 中,包含参数 1 的部分,替换为参数 2
###
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
main.o: main.cpp
$(CXX) -c main.cpp
printhello.o: printhello.cpp
$(CXX) -c printhello.cpp
factorial.o: factorial.cpp
$(CXX) -c factorial.cpp
$(TARGET): $(obj)
$(CXX) $(obj) -o $(TARGET)
#.mk-V4: clean
src = $(wildcard ./*.c) #匹配当前工作目录下的所有.c 文件
obj = $(patsubst %.c, %.o, $(src)) # 将参数 3 中,包含参数 1 的部分,替换为参数 2
###
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
main.o: main.cpp
$(CXX) -c main.cpp
printhello.o: printhello.cpp
$(CXX) -c printhello.cpp
factorial.o: factorial.cpp
$(CXX) -c factorial.cpp
$(TARGET): $(obj)
$(CXX) $(obj) -o $(TARGET)
clean :
-rm -rf $(obj) $(TARGET)# “-” :作用是,删除不存在文件时,不报错。顺序执行结束。
#.mk-V5: 三个自动变量
$@ # 在规则的命令中,表示规则中的目标。
$^ # 在规则的命令中,表示所有依赖条件。组成一个列表,以空格隔开,如果这个列表中有重复项,则去重
$< # 在规则的命令中,表示第一个依赖条件。如果将该变量应用在模式规则中,它可将依赖条件列表中的依赖依次取出,套用模式规则。
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
main.o: main.cpp
$(CXX) -c $<
printhello.o: printhello.cpp
$(CXX) -c $<
factorial.o: factorial.cpp
$(CXX) -c $<
$(TARGET): $(obj)
$(CXX) $^ -o $@
clean :
-rm -rf $(obj) $(TARGET)
#.mk-V6: 模式规则
#要添加一个.cpp文件,不需要在 makefile 里面增加这个文件的 -o 的部分
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
%.o : %.c
$(CXX) -c $< -o $@
$(TARGET): $(obj)
$(CXX) $^ -o $@
clean :
-rm -rf $(obj) $(TARGET)
#.mk-V7: 静态模式规则??
#使用静态模式规则,就是指定模式规则给谁用,这里指定模式规则给 obj 用,以后文件多了,文件集合会有很多个,就需要指定哪个文件集合用什么规则
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
$(obj) : %.o : %.c
$(CXX) -c $< -o $@
$(TARGET): $(obj)
$(CXX) $^ -o $@
clean :
-rm -rf $(obj) $(TARGET)
#.mk-V8: 伪目标
#当前文件夹下有 ALL 文件或者 clean 文件时,会导致 makefile 瘫痪,此时使用.PHONY: clean ALL
.PHONY: clean ALL
CXX = g++
TARGET = hello
src = $(wildcard *.cpp)
obj = $(patsubst %.cpp, %.o, $(src))
ALL : $(TARGET)
$(obj) : %.o : %.c
$(CXX) -c $< -o $@
$(TARGET): $(obj)
$(CXX) $^ -o $@
clean :
-rm -rf $(obj) $(TARGET)
#.mk-V9: 文件分类
#将上述 .cpp 文件都放到 src 目录中,.h 文件都放在 inc 目录中
CXX = g++
TARGET = hello
src = $(wildcard ./src/*.cpp)
obj = $(patsubst ./src/%.cpp, ./obj/%.o, $(src))
inc_path = ./inc
CXXFLAGS = -Wall -c -I$(inc_path)
ALL : $(TARGET)
./obj/%.o : ./src/%.cpp
$(CXX) $(CXXFLAGS) $< -o $@
$(TARGET): $(obj)
$(CXX) $^ -o $@
clean :
-rm -rf $(obj) $(TARGET)
.PHONY: clean
make 的参数 #
- -n:模拟执行 make、 make clean 命令。仅输出执行过程中的命令序列,但并不执行。
- -f:指定文件执行 make 命令。 xxxx.mk
- -j:可以并行构建多个目标,加快构建速度
- -s 或 **–silent 或 –quiet**:不显示命令。
Makefile 语法 #
使用echo进行printf
:= # 即时变量 = # 延时变量 ?= # 延时变量,如果是第 1 次定义才起效,如果在前面该变量已定义则忽略这句 += # 附加,他是即时变量还是延时变量取决于前面的定义,中间会有空格,加在后面
Makefile 函数 #
wildcard 函数 格式: $ (wildcard PATTENR) 展开指定的目录
notdir 函数 格式: $ (notdir $ (var) ) 去掉路径。
dir 函数: $(dir ) 取出目录
patsubst 函数:$(patsubst 原文件,目标文件,文件列表)替换
foreach 函数: 格式:$(foreach ,
- ,
)功能:把参数 - 中的单词逐一取出放到参数 所指定的变量中,然后再执行
所包含的表达式。每一次 会返回一个字符串
编译标志
-O2
:优化代码。-g
:包含调试信息。-Wall
:开启所有警告。-std=c++11
:指定使用 C++11 标准。-I
:指定包含(头文件)搜索路径。-L
:指定库文件搜索路径。-l
:指定链接时使用的库。
参考 #
CMake #
用于生成make文件
同类产品:XMake
cmake_minimum_required (VERSION 2.8)#lowest version requirement
project (learn_cmake) #project name
add_executable(hello hello.cpp)#要生成的可执行文件名为hello,后面的参数是需要的依赖
aux_source_directory(./your_src_dir var)#把dir目录中的所有源文件都储存在var变量中, 用“${var}”替换上面的hello.cpp.如果分别在多个文件,那么可以多次使用aux_source_directory
include_directories ( ./your_inc_dir )#他的作用是 自动去dir目录下寻找头文件,相当于 gcc中的 gcc -I dir
cmake . #执行CMakeLists.txt
#之后会生成Makefile
make #执行Makefile
案例1 #
- PROJECT_BINARY_DIR是cmake系统变量,意思是执行cmake命令的目录,我们计划在build目录下执行cmake命令,所以这个变量也就等同于build目录
- set_target_properties重新定义了库的输出名称,如果不使用set_target_properties也可以,那么库的名称就是add_library里定义的名称。具体可以参考官方文档
- LIBRARY_OUTPUT_PATH 是cmake系统变量,项目生成的库文件都放在这个目录下。这里我指定库生成到lib目录。