makefile 使用实例(三)

这一篇主要讲一下makefile 内置函数的使用,明天就回家了。能写多少就写多少!!

变量的替换引用

对于一个已经定义的变量,可以使用“替换引用”将其值中的后缀字符(串)使用

指定的字符(字符串)替换。格式为“(VAR:A=B)”(或者“{VAR:A=B}”),意思是,

替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。“结尾”的含义是空格

之前(变量值多个字之间使用空格分开)。而对于变量其它部分的“A”字符不进行替

换。例如:

foo := a.o b.o c.o

bar := $(foo:.o=.c)

在这个定义中,变量“bar”的值就为“a.c b.c c.c”。使用变量的替换引用将变量“foo”

以空格分开的值中的所有的字的尾字符“o”替换为“c”,其他部分不变。如果在变量

“foo”中如果存在“o.o”时,那么变量“bar”的值为“a.c b.c c.c o.c”而不是“a.c

b.c c.c c.c”。

obj= main.c foo1.c foo2.c
all:main

main:  main.o foo1.o foo2.o
    gcc -o [email protected] $^
    @echo var is === $(var)

var=${obj:.c=.o}
var:
    gcc -c $<

clean:
    rm -f *.o main1 main

上面就是把main.c foo1.c foo2.c 替换为 main.o foo1.o foo2.c

打印结果是

cc    -c -o main.o main.c
cc    -c -o foo1.o foo1.c
cc    -c -o foo2.o foo2.c
gcc -o main main.o foo1.o foo2.o
var is === main.o foo1.o foo2.o

“define”定义变量的语法格式:以指示符“define”开始,“endef”结束,之

间的所有内容就是所定义变量的值。所要定义的变量名字和指示符“define”在

同一行,使用空格分开;指示符所在行的下一行开始一直到“endef”所在行的

上一行之间的若干行,是变量值。

define two-lines

echo foo

echo $(bar)

endef

下面是测试代码,我们定义define com

gcc -o main main.o foo1.o foo2.o

mv main main1

endef

当使用这两行代码地方之间可以用com代替,省下很多代码

define com
gcc -o main main.o foo1.o foo2.o
mv main main1
endef
main  : main.o foo1.o foo2.o
    $(com)

main.o : main.c
    gcc -c main.c

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c

clean:
    rm -f *.o main1 main

在使用指示符“define”定义一个多行的变量或者命令包时,其定义体

(“define”和“endef”之间的内容)会被完整的展开到Makefile中引用此变量的地方

(包含定义体中的注释行)

上面com所代表的的命令包会被展开到所在地方,上面com定义也叫做命令包

在makefile手册中这样被定义

“书写Makefile时,可能有多个规则会使用相同的一组命令。就像c语言程序中需要

经常使用到函数“printf”。这时我们就会想能不能将这样一组命令进行类似c语言函数

一样的封装,以后在我们需要用到的地方可以通过它的名字(c语言中的函数名)来对

这一组命令进行引用。这样就可减少重复工作,提高了效率。在GNU make中,可以使

用指示符“define”来完成这个功能(关于指示符“define”可参考 6.8 多行定义 一

节)。通过“define”来定义这样一组命令,同时用一个变量(作为一个变量,不能和

Makefile中其它常规的变量命名出现冲突)来代表这一组命令。通常我们把使用“define”

定义的一组命令称为一个命令包。定义一个命令包的语法以“define”开始,以“endef”

结束,”

关键字ifeq使用,

此关键字用来判断参数是否相等,格式如下:

ifeq (ARG1, ARG2)‘

ifeq ‘ARG1’ ‘ARG2”

ifeq "ARG1" "ARG2"‘

ifeq “ARG1” ‘ARG2”

`ifeq ‘ARG1’ “ARG2”’

替换展开“ARG1”和“ARG1”后,对它们的值进行比较。如果相同则(条件为

真)将“TEXT-IF-TRUE”作为make要执行的一部分,否则将“TEXT-IF-FALSE”作

为make要执行的一部分(上边的第二种格式)。

通常我们会使用它来判断一个变量的值是否为空(不是任何字符)。参数值可能是

通过引用变量或者函数得到的,因而在展开过程中可能造成参数值中包含空字符(空格

等)。一般在这种情况时我们使用make的“strip”函数(参考 8.2 文本处理函数 一节)

来对它变量的值进行处理,去掉其中的空字符。格式为:

ifeq ((strip(foo)),)

TEXT-IF-EMPTY

endif

这样,即就是在“$(foo)”中存在若干前导和结尾空格,“TEXT-IF-EMPTY”也会被作

为Makefile需要执行的一部分。

file=$(shell  find foo2.c )
ifeq ($(strip $(file)),foo2.c)
main_name=main2
else
main_name=main3
endif

main  : main.o foo1.o foo2.o
    @echo ===== $(file)
    gcc -o main main.o foo1.o foo2.o
    mv main $(main_name)

main.o : main.c
    gcc -c main.c

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c

clean:
    rm -f *.o main1 main

查找当前目录下是否存在foo2.c文件存在,就让可执行文件mv main main2,不存在就是 mv main main3

在 makefile中使用 shell命令 格式为 $(shell 命令),本例查找当前存在foo2.c,假如查找所有.c文件,file=(shell find *.c),

file=$(shell  find *.c )
define find_name
ifeq ($(strip $(1)),foo2.c)
main_name=main2
endif
endef

$(foreach var,$(file),$(eval $(call find_name,$(var))))

main  : main.o foo1.o foo2.o
    @echo === $(main_name)
    @echo ===== $(file)
    gcc -o main main.o foo1.o foo2.o
    mv main $(main_name)

main.o : main.c
    gcc -c main.c

foo1.o : foo1.c
    gcc -c foo1.c

foo2.o : foo2.c
    gcc -c foo2.c

clean:
    rm -f *.o main1 main

结果是:

gcc -c main.c
gcc -c foo1.c
gcc -c foo2.c
=== main2
===== foo1.c foo2.c main.c main1.c
gcc -o main main.o foo1.o foo2.o
mv main main2

“call”函数是唯一一个可以创建定制化参数函数的引用函数。使用这个函数可以

实现对用户自己定义函数引用。我们可以将一个变量定义为一个复杂的表达式,用“call”

函数根据不同的参数对它进行展开来获得不同的结果。

函数语法:

$(call VARIABLE,PARAM,PARAM,...)

函数功能:在执行时,将它的参数“PARAM”依次赋值给临时变量“(1)”、“(2)”

(这些临时变量定义在“VARIABLE”的值中,参考下边的例子)……call函

数对参数的数目没有限制,也可以没有参数值,没有参数值的“call”没有任何

实际存在的意义。执行时变量“VARIABLE”被展开为在函数上下文有效的临时

变量,变量定义中的“(1)”作为第一个参数,并将函数参数值中的第一个参数赋值给它;变量中的“(2)”一样被赋值为函数的第二个参数值;依此类推(变

量$(0)代表变量“VARIABLE”本身)。之后对变量“VARIABLE” 表达式的计

算值。

上面define用法已经说过define定义变量在使用时候会展开放在远离位置,对于复杂的表达式可以用define定义,

因为用define定义所以使用的时候要用eval函数展开define定义的find_name.

reverse = $(2) $(1)
foo = $(call reverse,a,b) 

上面这个就不需要使用eval 函数!!因为没有用define定义,不需要展开

findstring 使用:

file=$(shell  find *.c )
main_name=$(findstring foo2.c,$(file))
obj= main.o foo1.o foo2.o
main  : $(obj)
    gcc -o [email protected] $^
    @echo === $(main_name)
    @echo ===== $(file)
    mv main $(main_name)
clean:
    rm -f *.o main1 main

结果是:

cc    -c -o main.o main.c
cc    -c -o foo1.o foo1.c
cc    -c -o foo2.o foo2.c
gcc -o main main.o foo1.o foo2.o
=== foo2.c
===== foo1.c foo2.c main.c main1.c
mv main foo2.c

$(subst FROM,TO,TEXT)

函数名称:字符串替换函数—subst。

函数功能:把字串“TEXT”中的“FROM”字符替换为“TO”。

返回值:替换后的新字符串。

file=hello from DSP
main_name=$(subst DSP,PPTV,$(file))
obj= main.o foo1.o foo2.o
main  : $(obj)
    gcc -o [email protected] $^
    @echo === $(main_name)
    @echo ===== $(file)
#   mv main $(main_name)
clean:
    rm -f *.o main1 main
cc    -c -o main.o main.c
cc    -c -o foo1.o foo1.c
cc    -c -o foo2.o foo2.c
gcc -o main main.o foo1.o foo2.o
=== hello from PPTV
===== hello from DSP

不想写了。就这些

时间: 2024-11-13 06:40:27

makefile 使用实例(三)的相关文章

C语言库函数大全及应用实例三

原文:C语言库函数大全及应用实例三 [编程资料]C语言库函数大全及应用实例三 函数名: ecvt 功 能: 把一个浮点数转换为字符串 用 法: char ecvt(double value, int ndigit, int *decpt, int *sign); 程序例: #i nclude #i nclude #i nclude int main(void) { char *string; double value; int dec, sign; int ndig = 10; clrscr()

动态规划算法实例三则

动态规划属于不好理解的计算机基本算法之一. 需要经过多次实践,才能体会其精妙之处. 其精妙的地方在于:降低运算量. 下面通过实例理解动态规划解题思路. 实例一:求数组的最大连续和子数组.参考文章 用动态规划来解,首先得考虑状态和状态转移方程.如果我们把题述数组看成序列,那么是不是可以用序列DP来考虑呢? 我们不妨考虑一个这样的序列:1,-3,5,-2,4 a[i]表示这个序列的第 i 个元素,dp[i]表示最后一个元素是a[i]的最大连续和(此乃状态,是不是跟LIS的DP解法有点类似),于是:

Contiki 2.7 Makefile 文件(三)

2.第二部分 这里的usage,targets,savetarget,savedefines都是伪目标. 和all不同,这些伪目标不会被执行,除非显式指定这些目标. 这里有两个目标savetarget,savedefines前边我们提过. 通过命令 make TARGET=esb savetarget可以保存默认的TARGET到Makefile.target中. 通过命令 make TARGET=esb DEFINES=MYTRACE,MYVALUE=4711 savedefines 可以保存默

Makefile文件(三)_书写规则

Makefile书写规则包含两部分,一个是依赖关系,一个是生成目标.在Makefile中,规则的顺序很重要,因为Makefile中只有一个最终目标.一般,定义在Makefile中的目标可能会有很多,但是第一条规则中的目标将被确立为最终目标.如果第一条规则中的目标有多个,那么第一个目标会成为最终目标,也就是make所完成的目标. 一.规则举例 foo.o:foo.c defs.h  #foo模块 cc -c -g foo.c 这个规则告诉我们:文件的依赖关系,还有如果要生成或更新foo.o文件,则

【FastDev4Android框架开发】RecyclerView完全解析之结合AA(Android Annotations)注入框架实例(三十)

(一).前言: 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.本系列文章会包括到以下三个部分: RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类(点击进入) RecyclerView控件的实战实例(点击进入) RecyclerView控件集合AA

makefile使用实例(一)

先引用一段经典的makefile名言---->什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂.这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义.特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力. 因为,

Makefile 编写实例

make命令常用的三个选项: 1.-k:它的作用是让make命令在发现错误的时候仍然继续执行.我们可以利用这个选项在一次操作中发现未编译成功的源文件. 2.-n:它的作用是让make命令输出将要执行的操作步骤,而不是真正执行这些操作. 3.-f  <filename>:它的作用是告诉make命令将哪个文件作为makefile文件.如果未使用这个选项,make命令将依次查找当前目录下的makefile文件,Makefile文件. Makefile文件中,将第一个目标定义为all,然后列出其他从属

makefile 使用实例(二)

在智能一点,全部使用自动化变量 obj= main.o foo1.o foo2.o main : $(obj) gcc -o [email protected] $^ clean: rm -f *.o main1 main @代表规则目标本例就是main,^代表规则所依赖文件本例是 main.o foo1.o 和foo2.o makefile也可以编译多目标文件,我们本例拷贝一份 main.c 命名为 main1.c, obj= main.o foo1.o foo2.o obj1= main1.

Centos5.8搭建NFS 服务器实例(三)

Centos5.8搭建NFS 服务器实例: 服务器系统 角色 IP CentOS-5.8-111-server1 NFS服务器端 192.168.1.111 CentOS-5.8-119-client NFS客户端 192.168.1.119 共享CentOS-5.8-111-server1中/data/bbs目录,使192.168.1.1 IP段所有主机都可以访问 配置服务端: 首先创建实验环境目录 [[email protected] ~]# mkdir /data/bbs –p [[ema