makefile

1.变量

1 变量的定义

1
2
cpp := src/main.cpp 
obj := objs/main.o

2 变量的引用

  • 可以用 (){}
1
2
3
4
5
6
7
cpp := src/main.cpp 
obj := objs/main.o

$(obj) : ${cpp}
@g++ -c $(cpp) -o $(obj)

compile : $(obj)
  • make compile 的时候 会去找obj(这个是obj := objs/main.o 而不是 $(obj) : ${cpp}) obj依赖于cpp

3 预定义变量

  • $@: 目标(target)的完整名称
  • $<: 第一个依赖文件(prerequisties)的名称
  • $^: 所有的依赖文件(prerequisties),以空格分开,不包含重复的依赖文件
1
2
3
4
5
6
7
8
9
cpp := src/main.cpp 
obj := objs/main.o

$(obj) : ${cpp}
@g++ -c $< -o $@
@echo $^

compile : $(obj)
.PHONY : compile

2.Makefile 的常用函数

函数调用,很像变量的使用,也是以 “$” 来标识的,其语法如下:

1
$(fn, arguments) or ${fn, arguments}
  • fn: 函数名
  • arguments: 函数参数,参数间以逗号 , 分隔,而函数名和参数之间以“空格”分隔

1 shell

1
$(shell <command> <arguments>)
  • 名称:shell 命令函数 —— shell
  • 功能:调用 shell 命令 command
  • 返回:函数返回 shell 命令 command 的执行结果

示例

1
2
3
4
# shell 指令,src 文件夹下找到 .cpp 文件
cpp_srcs := $(shell find src -name "*.cpp")
# shell 指令, 获取计算机架构
HOST_ARCH := $(shell uname -m)

2 subst

1
$(subst <from>,<to>,<text>)
  • 名称:字符串替换函数——subst
  • 功能:把字串 <text> 中的 <from> 字符串替换成 <to>
  • 返回:函数返回被替换过后的字符串

示例:

1
2
3
4

cpp_srcs := $(shell find src -name "*.cpp")
cpp_objs := $(subst src/,objs/,$(cpp_objs))

3 patsubst

1
$(patsubst <pattern>,<replacement>,<text>)
  • 名称:模式字符串替换函数 —— patsubst
  • 功能:通配符 %,表示任意长度的字串,从 text 中取出 patttern, 替换成 replacement
  • 返回:函数返回被替换过后的字符串

示例

1
2
cpp_srcs := $(shell find src -name "*.cpp") #shell指令,src文件夹下找到.cpp文件
cpp_objs := $(patsubst %.cpp,%.o,$(cpp_srcs)) #cpp_srcs变量下cpp文件替换成 .o文件

4 foreach

1
$(foreach <var>,<list>,<text>)
  • 名称:循环函数——foreach。
  • 功能:把字串<list>中的元素逐一取出来,执行<text>包含的表达式
  • 返回:<text>所返回的每个字符串所组成的整个字符串(以空格分隔)

示例:

1
2
3
4
library_paths := /datav/shared/100_du/03.08/lean/protobuf-3.11.4/lib \
/usr/local/cuda-10.1/lib64

library_paths := $(foreach item,$(library_paths),-L$(item))

同等效果

1
I_flag := $(include_paths:%=-I%)

5 dir

1
$(dir <names...>)
  • 名称:取目录函数——dir。
  • 功能:从文件名序列中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前
    的部分。如果没有反斜杠,那么返回“./”。
  • 返回:返回文件名序列的目录部分。
  • 示例:
1
$(dir src/foo.c hacks)    # 返回值是“src/ ./”。

6 notdir

1
$(notdir <names...>)

示例

1
libs   := $(notdir $(shell find /usr/lib -name lib*))

7 filter

1
$(filter <names...>)
1
2
3
libs    := $(notdir $(shell find /usr/lib -name lib*))
a_libs := $(filter %.a,$(libs))
so_libs := $(filter %.so,$(libs))

8 basename

1
$(basename <names...>)
1
2
3
libs    := $(notdir $(shell find /usr/lib -name lib*))
a_libs := $(subst lib,,$(basename $(filter %.a,$(libs))))
so_libs := $(subst lib,,$(basename $(filter %.so,$(libs))))

9 filter-out

  • 剔除不想要的字符串
1
2
objs := objs/add.o objs/minus.o objs/main.o
cpp_objs := $(filter-out objs/main.o, $(objs))

10 wildcard

  • The wildcard function expands to a space-separated list of filenames that match the given patterns
1
cpp_srcs := $(wildcard src/*.cc src/*.cpp src/*.c)

Examples

boost.mk

1
2
3
4
5
6
7
8
9
ROOT := /usr

sys_INCLUDE := $(ROOT)/include
sys_LIB_DIR := /usr/lib/x86_64-linux-gnu
full_paths := $(shell find $(sys_LIB_DIR) -name "libboost_*")
sys_LIBS = $(filter %.a %.so, $(full_paths))
# sys_LIBS := $(wildcard $(sys_LIBS)*.a $(sys_LIBS)*.so)
sys_LIBS := $(basename $(notdir $(sys_LIBS)))
sys_LIBS := $(patsubst lib%,%,$(sys_LIBS))