Makefile研究 (一)—— 必备语法
摘自:http://blog.csdn.net/jundic/article/details/17535445
参考文档:http://blog.csdn.net/wrx1721267632/article/details/52840355
以前在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研究 (一)—— 必备语法的更多相关文章
- 老大写得一个非常高大上的Makefile,包括非常多语法:
一个非常高大上的Makefile,包括非常多语法: TARGET = api-login INSTALL_PATH = /huishoubao/cgi include ../../implements ...
- makefile中的shell语法
在Makefile中写shell代码有点诡异,和不同的shell语法不太一样,如果不了解,看Makefile会莫名其妙.下面总结了一些. 1:尽在Makefile文件的目标项冒号后的另起一行的代码才是 ...
- Makefile 入门与基本语法 分类: C/C++ ubuntu 2015-05-18 11:16 466人阅读 评论(0) 收藏
在我看来,学会写简单的Makefile,阅读较复杂的makefile,是每一个Linux程序员都必须拥有的基本素质.Makefile可以自动识别哪些源文件被更改过,需要重新编译,那些不需要.从而节省大 ...
- 【 MAKEFILE 编程基础之二】MAKEFILE 书写规划以及语法规则!
本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/gcc-makefile/768.html ...
- Makefile研究(三) —— 实际应用
转自:http://blog.csdn.net/jundic/article/details/17886637 前面讲了Makefile 的简单语法和简单的应用模板,但在实际项目应用中比这个肯定复杂很 ...
- C#入门中的必备语法(一)
首先我们要知道C#语言是一种面向对象的语言由C和C++演变而来,它依赖于.NET Framework..NET Framework可以提供一个强大的代码库供其调用.之所以说C#语言依赖于.NET Fr ...
- Makefile研究(二)—— 完整可移植性模板
转自:http://blog.csdn.net/jundic/article/details/17676461 一直想写一个很全很好移植的Makefile模板,我觉得一个完整makefile 应该包含 ...
- GNU autotools自动生成Makefile 介绍
一.目的 使用autotools工具来帮助我们自动地生成符合自由软件惯例的makefile(这样就可以像常见的GNU程序一样,只要使用"./configure", "ma ...
- 内核顶层Makefile相关3
http://www.groad.net/bbs/simple/?f104.html 伪目标 .PHONY是一个特殊工作目标(special target),它用来指定一个假想的工作目标,也就是说它后 ...
随机推荐
- Unity3D总结:关于射线碰撞
方法一:Physics.Raycast 光线投射 1.static function Raycast (origin : Vector3, direction : Vector3, distance ...
- SqlServer,Oracle,Mysql 获取指定行数
--sqlserver * FROM dbo.T_TASK --oracle --mysql ,
- 使用sed来自动注释/恢复crontab中的一个任务
# 注释crontab任务crontab -l > ${WORK_DIR}/cron_binarysed -i 's%\(.*/home/xyz/xyz.sh\)%#\1%' ${WORK ...
- Linux机器间ssh免密登录
前言 一台Linux机器通过ssh的方式连接别的机器或通过scp的方式传输文件,都需要输入密码. 为了解决每次输入密码的困扰,可采用添加密钥的方式实现. 实现过程 源服务器A,目标服务器B. 1.在源 ...
- Day20 Java Socket使用
Java中Socket的使用 client端 package org.tizen.test; import java.io.IOException; import java.io.OutputStre ...
- JS中小数如何转化为百分数并能四舍五入
<script type="text/javascript">//n表示百分数保留的位数 function toPercent(n){ n = n || 2; retu ...
- Tomcat启动过程中卡住了
我在部署完项目后,debug启动Tomcat会在中间卡住不继续执行,测试发现在不部署项目的时候Tomcat是可以正常启动的. 控制台信息如下: 十月 25, 2017 10:40:44 上午 org. ...
- 【LeetCode】Sqrt(x) (转载)
Implement int sqrt(int x). Compute and return the square root of x. 原文地址: http://kb.cnblogs.com/page ...
- Composite Pattern
1.将对象组合成树形结构以表示“部分--整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性. 2.Composite 模式结构图 3.实现 #ifndef _COMPONENT_H ...
- STM32 ~ 外扩SRAM
字节控制功能.支持高/低字节控制. 看看实现 IS62WV51216 的访问,需要对 FSMC进行哪些配置. 这里就做一个概括性的讲解.步骤如下: 1)使能 FSMC 时钟,并配置 FSMC 相关的 ...