1. 定义
target: dependencies
[tab] command
NOTE: [tab] 不能为四个空格。
2. 使用规则
2.1 测试文件
func.h func.cpp main.cpp
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
void PrintHello(); | void PrintHello() | int main()
| { | {
| cout << "Hello World!"; | PrintHello();
| } | }
2.2 原始社会
g++ func.cpp main.cpp -o prog
当有多个文件的时候,每次都需要g++ 一串cpp文件,繁琐低效。
2.3 奴隶社会
compile.sh
-----------------
#!/bin/sh
g++ func.cpp main.cpp -o prog
事先写好脚本,编译操作一键式完成,./compile.sh
。同样,文件数量急剧上涨的时候,问题显现出来。
无论源文件是否改动,每次都需要将所有的cpp编译成.o
目标文件,耗时低效。
2.4 封建社会
通过makefile的依赖关系,只需要编译修改的文件即可,没有修改的源文件,没有必要重新编译。省时,但不省力。
prog: func.o main.o
g++ func.o main.o -o prog
func.o: func.cpp
g++ -c func.cpp -o func.o
main.o: main.cpp
g++ -c main.cpp -o main.o
2.5 社会主义
在封建社会中,只要存在一个cpp文件,就要为这个cpp文件写规则,一旦源文件数量上升,makefile将成为瓶颈。
CC = g++
RM = rm -rf
CFLAGS = -g -WALL
OBJS = main.o func.o
EXEC = main
$(EXEC): $(OBJS)
$(CC) $^ $(CFLAGS) -o $@
%.o : %.cpp
$(CC) -c $< -o $@
clean:
$(RM) $(OBJS) $(EXEC)
变量
自定义变量
= 使用等号给自定义变量赋值
# 注释内建变量
$^ 依赖关系列表
$< 依赖关系列表中第一个
$@ target 名字
prog: main.o func.o
g++ $^ -o $@$^ => main.o func.o
$@ => prog
$< => main.o
模式规则
target目标中包含%
,即为一个模式规则。
%.o : %.cpp
指导任何一个cpp
文件编译成对应的.o
文件
2.5 共产主义
社会主义中,工作效率已经得到了极大的提升,但是,仍需要手动将每个.cpp
文件对应为.o
文件。共产主义社会中,通过引入函数,自动完成这一繁琐工作。
CC = g++
RM = rm -rf
CFLAGS = -g -WALL
SRCS = $(wildcard *.cpp)
OBJS = $(SRCS:.cpp=.o)
EXEC = main
$(EXEC): $(OBJS)
$(CC) $^ $(CFLAGS) -o $@
%.o : %.cpp
$(CC) -c $< -o $@
clean:
$(RM) $(OBJS) $(EXEC)
函数
语法
$(function arguments)
- function 函数名
- arguments 函数参数
Makefile 手册: Functions for Transforming Text
wildcard 函数
wildcard
为通配符函数,类似于通配符 %
(wildcard *.cpp) 得到当前目录下,所有的cpp文件
变量替换
foo = test.c main.c
bar = $(foo:**.**c=**.**o)
prog :
echo $(bar)
-------------------
输出: test.o main.o
MakeFile 手册:Substitution References
替换规则:
- 针对单词进行替换, foo 变量单词直接以空格隔开
- 后缀替换,仅仅替换匹配的后缀
foo = test.o oppo.o
bar = $(foo: o = x)bar => test.x oppo.x
3. Shell 语法
脚本语法
- 每行一个进程进行处理,因而每个命令单元不能断行
- makefile中变量以$
开头,所有为了避免冲突,shell变量获取以$$
开头
DIRS = common logic middle_tier bootstrap
all:
@for dir in $(DIRS); do make -C $$dir; done
rm -rf prog/conf/*
mkdir -p prog/conf
cp -r bootstrap/conf/* prog/conf
Note:
@ 执行此条命令,但不要输出任何信息
make -C 嵌套调用子目录中的Makefile
Shell 函数
files = $(shell echo *.c)
DIRS = $(shell ls -F | grep /$)
all:
@for dir in $(DIRS); do make -C $$dir; done