摘自:http://blog.csdn.net/jundic/article/details/17535445

参考文档:http://blog.csdn.net/wrx1721267632/article/details/52840355

参考文档:http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile:%E9%9A%90%E5%90%AB%E8%A7%84%E5%88%99

  以前在windows上学习单片机、ARM的时候都是用IDE去管理编译代码,很多时候都不知道各个程序之间是怎么编译成可执行文件的,只要点下鼠标就可以了。虽然自己也有学习linux以及uboot 但都是看看改改程序。对于makefile认识也是单文件小工程的。认为makefile就是个编译工具,没必要深究。随着阅读的代码量的增多,发现,对于理解一些源码框架比如u-boot、inux 、andriod,要是看不懂makefile理解起来比较困难。而且在嵌入式系统开发中,考虑功能的模块化和可移植性,makefile是一个绕不过的东西。最近一次工作经历深深地刺激了我。是这样,我之前已经完整编译了整个工程,后面修改了某个配置文件,执行make 总是提示那个配置的东西不存在。即使make clean后再make还是会报一堆不知名的错误,我意识到makefile某些编译项用的是未改前的配置,现在有冲突了,当然会报错,这个系统是我们公司开发的有十几万个文件,每次编译都要二十多分钟,我当天一直查这个问题到11:00,伤心地回了家。第二天我默默地从服务器上重新下载新的code,直接修改配置文件,直接make正如我所料一次性编译通过。

果然是该死的makefile第一次编译ok,修改配置文件,第二次编写就把代码编坏了。这种情况我相信很多搞程序的都遇到过,其实在此前就发现makefile不怎么完美,我经常添加模块还要去修改多个makefile才能使得添加的模块编译进去。跟进的项目终于接近尾声,决心好好研究下。

makefile 其实也是编程语言,他只是编译工具语言,也有语法,个人觉得我们实际应用中掌握常用的语法就好了下面是我总结的常用的Makefile语法。

一、Makefile 中的赋值方法

=    递归赋值 可以向后引用变量

:= 简单扩展 只能引用前面的变量

?= 如果没有赋值 则赋值一次

+=  在原来的基础上添加赋值变量

一个例子说明

 x = before
y = $(x)
x = later xx = before
yy := $(xx)
xx = later xxx = before
xxx ?= later yyy ?= before
yyy = later x += last all :
@echo "x=" $(x)
@echo "y=" $(y)
@echo "xx=" $(xx)
@echo "yy=" $(yy)
@echo "xxx=" $(xxx)
@echo "yyy=" $(yyy)

输出是

x= later last

y= later last

xx=later

yy=before

xxx=before

yyy=later

二、Makefile 自动变量

所谓自动化变量,就是这种变量会把模式中所定义的一系列的文件自动地挨个取出,直至所有的符合模式的文件都取完了。这种自动化变量只应出现在规则的命令中。

下面是所有的自动化变量及其说明:

$@

  表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,"$@"就是匹配于目标中模式定义的集合。

$%

  仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是"foo.a(bar.o)",那么,"$%"就是 "bar.o","$@"就是"foo.a"。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。

$<

  依赖目标中的第一个目标名字。如果依赖目标是以模式(即"%")定义的,那么"$<"将是符合模式的一系列的文件集。注意,其是一个一个取出来的。

$^

  所有的依赖目标的集合。以空格分隔。如果在依赖目标中有多个重复的,那个这个变量会去除重复的依赖目标,只保留一份。

$?

  所有比目标新的依赖目标的集合。以空格分隔。

$+
这个变量很像"$^",也是所有依赖目标的集合。只是它不去除重复的依赖目标。
$*
这个变量表示目标模式中"%"及其之前的部分。如果目标是"dir/a.foo.b",并且目标的模式是"a.%.b",那么,"$*"的值就是"dir/a.foo"。这个变量对于构造有关联的文件名是比较有用。如果目标中没有模式的定义,那么"$*"也就不能被推导出,但是,如果目标文件的后缀是make所识别的,那么"$*"就是除了后缀的那一部分。例如:如果目标是"foo.c",因为".c"是make所能识别的后缀名,所以," $*"的值就是"foo"。这个特性是GNU make的,很有可能不兼容于其它版本的make,所以,你应该尽量避免使用"$*",除非是在隐含规则或是静态模式中。如果目标中的后缀是make所不能识别的,那么"$*"就是空值。
 test.o : test1.c test2.c
@echo $@
@echo $<
@echo $^

结果为

test.o

test1.c

test1.c test2.c

三、Makefile中的常用函数

1、文本替换 函数 $(subst ma,   wo   ,hello world!!)

将hello world!! 中间的wo 替换成ma

结果为  hello marld!!

2、格式替换函数 $(patsubst %.c ,%.o , test.c test1.c test2.c)

将.c 的格式替换成.o

结果为 test.o test1.o test2.o

3、去掉空格函数 $(strip a    b               c)

结果 a b c

4、字符串查找函数

$(findstring a,a b c d)

在字符串a b c d 中查找 a  ,找到就返回查到的值 ,否则为 "  "

上面结果为 a

5、格式匹配过滤函数 $(filter %.c %.s , mod1.c mod2.o mod3.s mod4.h)

查找格式是%.c 和 %.s 的文件

结果为 mod1.c mod2.s

6、格式不匹配函数 $(filter-out %.c %.s, mod1.c mod2.o mod3.s mod4.h)

它的和filter相反

结果为 mod2.o mod4.h

7、$(sort  hello  world branck)

按字母排列

结果为  branck hello world

8 、抽取文件目录函数$( dir source/hello.c inc/hello.h mksh)

结果: source/  inc/  ./

9、抽取文件名函数 $(nodir source/hello.c inc/hello.h mksh)

结果: hello.c hello.h mksh

10、提取文件名后缀函数 $(suffix source/hello.c inc/hello.h mksh)

结果: .c  .h

11、去除后缀名函数 $(basename sourc/hello.c inc/hello.h mksh)

结果: source/hello   inc/hello mksh

12、添加后缀名函数 $(addsuffix .c ,hello fun)

结果: hello.c fun.c

13、添加前缀函数 $(addprefix source/ , mod1.c mod2.c mod3.c)

结果: source/mod1.c source/mod2.c source/mod3.c

14、格式匹配函数 $(wildcard  source/*.c)

查找source 目录下所有.c 文件

15、格式匹配用法

SRCS = mod1.c mod2.c mod3.c

$(SRCS : %.c = %.o)

结果为mod1.o mod2.o mod3.o

16、目录循环搜索

dirs :=  dir1 dir2 dir3 dir4

files := $( foreach dir ,$(dirs) ,$(wildcard $(dir)/*)

查找 目录 dir1 dir2 dir3 dir4 目录下所有的文件。

17、在Makefile 中执行shell 脚本的方法

$(shell command)

SRCS := $(shell ls *.c)

则srcs 中所有的c程序。

四、Makefile 中的编译基础知识

1、编译时 指定头文件路径 用 -I

2、编译时 指定库路径用 -L 指定函数库名 用 -l (小写L )

3、在Makefile 指定宏定义 配置到程序中 -D

五、条件判断语句

1、ifdef/ifndf  (param)

endif

#    param  是否定义

2、ifeq/ifneq (a,b)

endif

#  a和b是否相等

我想Makefile 的基础知识掌握这些就ok了,关键是应用。

Makefile研究 (一)—— 必备语法的更多相关文章

  1. 老大写得一个非常高大上的Makefile,包括非常多语法:

    一个非常高大上的Makefile,包括非常多语法: TARGET = api-login INSTALL_PATH = /huishoubao/cgi include ../../implements ...

  2. makefile中的shell语法

    在Makefile中写shell代码有点诡异,和不同的shell语法不太一样,如果不了解,看Makefile会莫名其妙.下面总结了一些. 1:尽在Makefile文件的目标项冒号后的另起一行的代码才是 ...

  3. Makefile 入门与基本语法 分类: C/C++ ubuntu 2015-05-18 11:16 466人阅读 评论(0) 收藏

    在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质.Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要.从而节省大 ...

  4. 【 MAKEFILE 编程基础之二】MAKEFILE 书写规划以及语法规则!

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/gcc-makefile/768.html   ...

  5. Makefile研究(三) —— 实际应用

    转自:http://blog.csdn.net/jundic/article/details/17886637 前面讲了Makefile 的简单语法和简单的应用模板,但在实际项目应用中比这个肯定复杂很 ...

  6. C#入门中的必备语法(一)

    首先我们要知道C#语言是一种面向对象的语言由C和C++演变而来,它依赖于.NET Framework..NET Framework可以提供一个强大的代码库供其调用.之所以说C#语言依赖于.NET Fr ...

  7. Makefile研究(二)—— 完整可移植性模板

    转自:http://blog.csdn.net/jundic/article/details/17676461 一直想写一个很全很好移植的Makefile模板,我觉得一个完整makefile 应该包含 ...

  8. GNU autotools自动生成Makefile 介绍

    一.目的 使用autotools工具来帮助我们自动地生成符合自由软件惯例的makefile(这样就可以像常见的GNU程序一样,只要使用"./configure", "ma ...

  9. 内核顶层Makefile相关3

    http://www.groad.net/bbs/simple/?f104.html 伪目标 .PHONY是一个特殊工作目标(special target),它用来指定一个假想的工作目标,也就是说它后 ...

随机推荐

  1. NumPy事例练习

    因为排版问题直接把jupyter里的截图过来了:暂时就写了这么点小例子,建议在ipython notebook中做测试

  2. Google Chrome的快捷键

    1.Ctrl + N 打开一个新窗口           &&            Alt + F4    关闭当前窗口 2.Ctrl + T 打开一个新的标签页 && ...

  3. windows下的txt格式转换成linux下的TXT

    存在的问题是 多出一个方框或者黑格子 主要是因为bash 不能忽略windows的问题 用sed 命令来处理,分别是windows转linux,linux转windows sed -e 's/.$// ...

  4. 【TensorFlow-windows】(一)实现Softmax Regression进行手写数字识别(mnist)

    博文主要内容有: 1.softmax regression的TensorFlow实现代码(教科书级的代码注释) 2.该实现中的函数总结 平台: 1.windows 10 64位 2.Anaconda3 ...

  5. 在“云基础设施即服务的魔力象限”报告中,AWS 连续三年被评为领导者

    在"2014 云基础设施即服务的魔力象限"中.Gartner 将 Amazon Web Services 定位在"领导者象限"中,并评价 AWS 拥有最完整.最 ...

  6. vmware安装操作系统

    安装的时候,直接选择“从光盘或者映像安装”就可以了,很方便的.不需要再去从u盘什么的安装了.

  7. left outer join preserving unmatched rows from the first table

    https://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqlj18922.html INNER JOIN operation Specifies a join ...

  8. Redis 分布式锁的正确实现方式(转)

    _ 前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各 ...

  9. 微信小程序开发:学习笔记[8]——页面跳转及传参

    微信小程序开发:学习笔记[8]——页面跳转及传参 页面跳转 一个小程序拥有多个页面,我们可以通过wx.navigateTo推入一个新的页面.在首页使用2次wx.navigateTo后,页面层级会有三层 ...

  10. MT6737 Android N 平台 Audio系统学习----录音到播放录音流程分析

    http://blog.csdn.net/u014310046/article/details/54133688 本文将从主mic录音到播放流程来进行学习mtk audio系统架构.  在AudioF ...