文章目录

  • 一、demo的目录结构
  • 二、使用Makefile生成可执行文件
    • 1、简单版本的Makefile
    • 2、使用变量改进Makefile
    • 3、使用自动变量继续改进Makefile
    • 4、使用 %.o:%.c 样式继续改进Makefile
    • 5、使用模块化继续改进Makefile
  • 三、Makefile中一些关键语法
    • 1、wildcard
    • 2、notdir
    • 3、patsubst
    • 4、`@、$@、$^、$<`
  • 四、一个实例详解

  Makefile是一个神奇的东西,有了它只需一个make命令就可以让源文件按你的规则编译成你所想要的程序。非常简单,方便。对于Keil,VS等IDE,一般只需点一下绿色的三角按钮,就可以完成编译。但具体内部是怎么实现编译的?改动文件后如何只编译改动的文件?学完makefile就可以掌握这些东西,从而对系统编程会有更深层次的理解。

一、demo的目录结构

二、使用Makefile生成可执行文件

1、简单版本的Makefile

//例行公式,表示在bin目录下生成可执行文件
all : ../bin/make_test //可执行文件(make_test)的生成依赖于多个目标文件(.o),'\'表示转义字符
../bin/make_test : ./main.o ./sub1/dummy1.o \./sub1/dummy2.o ./sub2/dummy3.o \./sub2/dummy4.o//生成目标文件(.o)g++ -o ../bin/make_test ./main.o ./sub1/dummy1.o \./sub1/dummy2.o ./sub2/dummy3.o \./sub2/dummy4.o//目标文件(.o)的生成依赖于源文件(.cpp)
./main.o : ../src/main.cppg++ -o ./main.o -c ../src/main.cpp -I ../inc./sub1/dummy1.o : ../src/sub1/dummy1.cppg++ -o ./sub1/dummy1.o -c ../src/sub1/dummy1.cpp -I ../inc./sub1/dummy2.o : ../src/sub1/dummy2.cppg++ -o ./sub1/dummy2.o -c ../src/sub1/dummy2.cpp -I ../inc./sub2/dummy3.o : ../src/sub2/dummy3.cppg++ -o ./sub2/dummy3.o -c ../src/sub2/dummy3.cpp -I ../inc./sub2/dummy4.o : ../src/sub2/dummy4.cppg++ -o ./sub2/dummy4.o -c ../src/sub2/dummy4.cpp -I ../inc//清理目标文件(.o)和可执行文件
clean:rm -rf ./*.o ./sub1/* ./sub2/* ../bin/*

2、使用变量改进Makefile

all : ../bin/make_test//':='表示不跟踪变量,一般用于固定格式的命令或变量
RM := rm -rf//'='表示跟踪变量,可以追加和修改,类似于C++中的引用
OBJS = ./main.o ./sub1/dummy1.o \./sub1/dummy2.o ./sub2/dummy3.o \./sub2/dummy4.o//$(val)表示使用变量
../bin/make_test : $(OBJS)g++ -o ../bin/make_test $(OBJS)./main.o : ../src/main.cppg++ -o ./main.o -c ../src/main.cpp -I ../inc./sub1/dummy1.o : ../src/sub1/dummy1.cppg++ -o ./sub1/dummy1.o -c ../src/sub1/dummy1.cpp -I ../inc./sub1/dummy2.o : ../src/sub1/dummy2.cppg++ -o ./sub1/dummy2.o -c ../src/sub1/dummy2.cpp -I ../inc./sub2/dummy3.o : ../src/sub2/dummy3.cppg++ -o ./sub2/dummy3.o -c ../src/sub2/dummy3.cpp -I ../inc./sub2/dummy4.o : ../src/sub2/dummy4.cppg++ -o ./sub2/dummy4.o -c ../src/sub2/dummy4.cpp -I ../incclean:$(RM) $(OBJS) ../bin/*

3、使用自动变量继续改进Makefile

all : ../bin/make_testRM := rm -rfOBJS = ./main.o ./sub1/dummy1.o \./sub1/dummy2.o ./sub2/dummy3.o \./sub2/dummy4.o../bin/make_test : $(OBJS)g++ -o $(@) $(^)./main.o : ../src/main.cppg++ -o $(@) -c $(<) -I ../inc./sub1/dummy1.o : ../src/sub1/dummy1.cppg++ -o $(@) -c $(<) -I ../inc./sub1/dummy2.o : ../src/sub1/dummy2.cppg++ -o $(@) -c $(<) -I ../inc./sub2/dummy3.o : ../src/sub2/dummy3.cppg++ -o $(@) -c $(<) -I ../inc./sub2/dummy4.o : ../src/sub2/dummy4.cppg++ -o $(@) -c $(<) -I ../incclean:$(RM) $(OBJS) ../bin/*

4、使用 %.o:%.c 样式继续改进Makefile

all : ../bin/make_testRM := rm -rfOBJS = ./main.o ./sub1/dummy1.o \./sub1/dummy2.o ./sub2/dummy3.o \./sub2/dummy4.o../bin/make_test : $(OBJS)g++ -o $(@) $(^)./%.o : ../src/%.cppg++ -o $(@) -c $(<) -I ../inc./sub1/%.o : ../src/sub1/%.cppg++ -o $(@) -c $(<) -I ../inc./sub2/%.o : ../src/sub2/%.cppg++ -o $(@) -c $(<) -I ../incclean:$(RM) $(OBJS) ../bin/*

5、使用模块化继续改进Makefile

// ./sub1/sub.mkOBJS += ./sub1/dummy1.o ./sub1/dummy2.o./sub1/%.o : ../src/sub1/%.cppg++ -o $(@) -c $(<) -I ../inc
// ./sub2/sub.mkOBJS += ./sub2/dummy3.o ./sub2/dummy4.o./sub2/%.o : ../src/sub2/%.cppg++ -o $(@) -c $(<) -I ../inc
// ./sub.mkOBJS += ./main.o \./%.o : ../src/%.cppg++ -o $(@) -c $(<) -I ../inc
// Makefile终极版本RM := rm -rf-include ./sub.mk
-include ./sub1/sub.mk
-include ./sub2/sub.mkall : ../bin/make_test../bin/make_test : $(OBJS)@echo 'Building target : $@'@echo 'Invoking : GCC C++ Linker'g++ -o $(@) $(^)@echo 'Finishing building target: $@'@echo ' '//显式指定某个目标为伪目标 ,表明不论是否有 clean 这个文件, make clean 中 make 都会将 clean 当作伪目标。
.PHONY : clean clean:-$(RM) $(OBJS) ../bin/*

三、Makefile中一些关键语法

  Makefile里的函数使用,和取变量的值类似,是以一个‘$’开始,然后是一个括号里面是函数名和需要的参数列表,多个变量用逗号隔开,像这样:

return = $(functionname  arg1,arg2,arg3...)。

1、wildcard

SRC = $(wildcard *.c ./foo/*.c)

  搜索当前目录及./foo/下所有以.c结尾的文件,生成一个以空格间隔的文件名列表,并赋值给SRC.当前目录文件只有文件名,子目录下的文件名包含路径信息,比如./foor/bar.c。

2、notdir

SRC = $(notdir wildcard)

  去除所有的目录信息,SRC里的文件名列表将只有文件名

3、patsubst

OBJ = $(patsubst %.c %.o $(SRC))

  patsubst是patten substitude的缩写,匹配替代的意思。这句是在SRC中找到所有.c 结尾的文件,然后把所有的.c换成.o

4、@、$@、$^、$<

// target:表示我们的目标,components:表示依赖对象,rule:表示规则
target:componentsrule@:表示不显示命令本身$@:代表目标文件(target)$^:代表所有的依赖文件(components)$<:代表第一个依赖文件(components中最左边的那个)。

四、一个实例详解

# 定义一些变量
DIR_BIN = .
DIR_OBJ = ./obj
DIR_SRC = ./src# 把DIR_SRC目录下所有的.CPP文件展开
SRC = $(wildcard $(DIR_SRC)/*.cpp)
# 把DIR_SRC目录下所有的.CPP替换为.o文件
OBJ = $(patsubst %.cpp,$(DIR_OBJ)/%.o,$(notdir $(SRC)))#  -g表示调试,-Wall表示让所有编译警告都显示出来,
# -std=c++11表示使用C++11版本,-pthread表示使用多线程库,
# -O3表示产生更高级别的优化
CXX_FLAG = -g -Wall -std=c++11 -pthread -O3
CC = g++TARGET = exec# 生成可执行文件
$(DIR_BIN)/$(TARGET) : $(OBJ)$(CC) $(CXX_FLAG) -o $@ $^# 表示把DIR_SRC目录下所有的.cpp文件编译成.o文件。
$(DIR_OBJ)/%.o : $(DIR_SRC)/%.cppif [ ! -d $(DIR_OBJ) ];    then mkdir -p $(DIR_OBJ); fi;$(CC) $(CXX_FLAG) -c $< -o $@# 清空所有目标文件
.PHONY : clean
clean : -rm -rf $(DIR_OBJ)

  

  
【Note】:

Make和Makefile相关推荐

  1. 浅显易懂 Makefile 入门 (12)— Makefile 常见的错误信息

    1. 常见的错误信息 make 执行过程中所产生错误并不都是致命的,特别是在命令行之前存在 -.或者 make 使用 -k 选项执行时. make 执行过程的致命错误都带有前缀字符串 ***.错误信息 ...

  2. 浅显易懂 Makefile 入门 (10)— 嵌套执行 make、export 的使用

    1. 嵌套执行 make 在一个大的工程文件中,不同的文件按照功能被划分到不同的模块中,每个模块可能都会有自己的编译顺序和规则,如果在一个 Makefile 文件中描述所有模块的编译规则,就会很乱,执 ...

  3. 浅显易懂 Makefile 入门 (09)— include 文件包含、MAKECMDGOALS

    1. include文件包含 当 make 读取到 include 关键字的时候,会暂停读取当前的 Makefile,而是去读 include 包含的文件,读取结束后再继读取当前的 Makefile ...

  4. 浅显易懂 Makefile 入门 (08)— 默认 shell (/bin/sh)、命令回显、make参数(-n 只显示命令但不执行,-s 禁止所有回显)、单行命令、多行命令、并发执行

    1. shell 相关 1.1 默认 shell Makefile 所使用的命令是由 shell 命令行组成,他们是一条一条执行的. 多个命令之间要使用分号隔开,Makefile 中的任何命令都要以 ...

  5. 浅显易懂 Makefile 入门 (07)— 其它函数(foreach 、if、call、origin )

    1. foreach 函数 foreach 函数定义如下: $(foreach <var>,<list>,<text>) 函数的功能是:把参数 <list&g ...

  6. 浅显易懂 Makefile 入门 (06)— 文件名操作函数(dir、notdir、suffix、basename、addsuffix、addperfix、join、wildcard)

    编写 Makefile 的时候,很多情况下需要对文件名进行操作.例如获取文件的路径,去除文件的路径,取出文件前缀或后缀等等. 注意:下面的每个函数的参数字符串都会被当作或是一个系列的文件名来看待. 1 ...

  7. 浅显易懂 Makefile 入门 (03)— 目标文件搜索(VPATH 和 vpath 的区别和使用)、隐含规则

    1. 目标文件搜索(VPATH和vpath) 如果需要的文件是存在于不同的路径下(即源文件与 Makefile 文件不在同一个路径下),在编译的时候就用到了 Makefile 中为我们提供的目录搜索文 ...

  8. 浅显易懂 Makefile 入门 (02)— 普通变量和自动变量定义、使用($@、$^、$< 作用)、变量覆盖 override、变量的来源 origin

    1. 变量的定义 Makefile 文件中定义变量的基本语法如下: 变量的名称=值列表 变量的名称可以由大小写字母.阿拉伯数字和下划线构成.等号左右的空白符没有明确的要求,因为在执行 make 的时候 ...

  9. 浅显易懂 Makefile 入门 (01)— 什么是Makefile、为什么要用Makefile、Makefile规则、Makefile流程如何实现增量编译

    1. 什么是 Makefile Makefile 文件描述了 Linux 系统下 C/C++ 工程的编译规则,它用来自动化编译 C/C++ 项目.一旦写编写好 Makefile 文件,只需要一个 ma ...

  10. Android 的NDK的Makefile编写

    Android.mk 是google根据Linux GNU Makefile精简编译脚本.具体来说:这就是GNU Makefile的一小部分. 举一个简单例子: LOCAL_PATH := $(cal ...

最新文章

  1. 五分钟体验分布式事务框架Seata
  2. python mkl freebsd_FreeBSD:在uwsgi中使用python3而不是python2
  3. ABAP实例:一个现金流量表的代码
  4. JavaScript可否多线程? 深入理解JavaScript定时机制
  5. unity应用开发实战案例_「简历」STAR法则的实战应用,附手把手教学案例
  6. Mybatis多表模型
  7. 测试奶粉真假的软件,体绝假货!最详尽的奶粉真假辨别方法都在这里!
  8. oppoJava面试!mysql客户端安装包
  9. php递归函数名字,php递归函数
  10. VS2017专业版和企业版激活密钥
  11. 有监督学习(supervised learning))与无监督学习(unsupervised learning)之间有何区别?
  12. CSS 的 hsl() 和 hsla() 函数(设置颜色的方式之一)
  13. wps里的茶色字体怎么设置_wps字体加茶色背景2 wps茶色如何设置
  14. c++17之结构化绑定
  15. 计算机的删除快捷键,电脑删除的快捷键是什么
  16. BZOJ 5109 [CodePlus 2017]大吉大利,晚上吃鸡!
  17. 【翻译】开发人员的技术写作
  18. 世界上最好的加密软件
  19. 阿里技术专家的编程方法论:如何写出一手漂亮的代码?
  20. 产品化软件开发与项目化软件开发的对比

热门文章

  1. 小飞升值记——(21)
  2. 产品介绍 | 51LA短链分发平台
  3. 基于matlab的电流滞环控制,电流滞环控制matlab
  4. 2022年全球与中国数模转换器市场现状及未来发展趋势
  5. Python必学的4个实战项目,拿走不谢
  6. 飞扬的小鸟1.0测试版
  7. GTX 770 (GK 104)
  8. 《管理学》第四章 计划
  9. null不可以toString
  10. 前端怎么加粗字体_泣血总结,死磕前端知识点