6、变量的高级主题

变量值的替换:使用指定字符(串)替换变量值中的后缀字符(串)。

语法格式:$(var:a=b)或${var:a=b}

替换表达式中不能有任何的空格.

make中支持使用${}对变量进行取值。

src :=a.cc b.cc c.cc

obj :=$(src:cc=o) //(a.o b.o c.o)

test :

    @echo "obj =>$(obj)"

变量的模式替换:

使用%保留变量值中的指定字符,替换其他字符。

语法格式: $(var:a%b=x%y) 或 ${var:a%b=x%y}

替换表达式中不能有任何的空格。

make中支持使用${}对变量进行取值。

src :=a1b.c a2b.c a3b.c

obj :=$(src:a%b.c=x%y)  //x1y x2y x3y

test:

        @echo "obj=>$(obj)"

规则中的模式替换:

targets:target-pattern:prereq-pattern

    command1

    command2

    ...

意义:通过target-pattern从targets中匹配子目标;在通过prereq-pattern从子目标生成依赖;进而构成完整的规则。

规则中的模式替换示例:

OBJS :=func.o main.o

$(OBJS)(目标): %.o(模式取子串) : %.c //模式替换.o->.c

            gcc -o $@ -c $^

=>

func.o: func.c

        gcc -o $@ -c $^

main.o : main.c

        gcc -o $@ -c $^

makefile:

src1 :=a.cc b.cc c.cc
obj1 :=$(src1:cc=0)
test1:
@echo "obj1=>$(obj1)" 

src2:=a11b.c a22b.c a33b.c
obj2:=$(src2:a%b.c=x%y)
test2:

@echo "obj2=>$(obj2)"

3变量的嵌套应用:

一个变量名之中可以包含对其他变量的引用。

嵌套引用的本质是使用一个变量表示另外一个变量。

x :=y

y:=z

a:=$($(x)) ==> a:=$(y)==> a:=z //$(x) 取x的值

命令行变量:

运行make时,在命令行定义变量。

命令行变量默认覆盖makefile中定义的变量。

hm :=hello makefile

test :

    @echo "hm=>$(hm)"

make hm=cmd ->hm=>cmd 临时改变变量的值

override关键字:

用于指示makefile中定义的变量不能被覆盖。变量的定义和赋值都需要使用override关键字。

override var :=test

test :

    @echo "var =>$(var)"

make var=cmd -->hm=>test

define关键字:

用于在makefile中定义多行变量。

多行变量的定义从变量名开始到endef结束。

可使用override关键字防止变量被覆盖。

define定义的变量等价于使用=定义的变量。

makefile:

define foo

I'm fool!

endef

override define cmd

    @echo "run cmd ls..." //多行变量的值是命令的话,要使用Tab键

    @ls

endef

func.o main.o

小结:变量值的替换:$(var:a=b) 或 ${var: a=b}。

变量的模式替换:$(var:a%b=x%y) 或 ${ var:a%b=x%y }。

makefile支持将模式替换可以直接用于规则中。

makefile中的变量值能够嵌套使用。变量值当作变量名

命令行中定义的变量能够覆盖makefile中定义的变量。

override用于指示makefile中定义的变量不能被覆盖。

define用于在makefile中定义值为多行的变量。

7、变量的高级主题(下)

环境变量(全局变量):系统定义的

makefile中能够直接使用环境变量的值。

定义了同名变量,环境变量将被覆盖。

运行make时指定“-e”选项,优先使用环境变量。

为什么要在makefile中使用环境变量?

优势:环境变量可以在所有makefile中使用。

劣势:过多的依赖于环境变量会导致移植性降低。

变量在不同makefile之间的传递方式:

直接在外部定义环境变量进行传递。

使用export定义变量进行传递(定义临时环境变量)。

定义make命令行变量进行传递(推荐)。

export JAVA_HOME :=java home 
#jiang xi tong zhong huan jing bian liang de zhi gai xie
export var :=D.t.software
new :=tdelphi
test:
@echo "JAVA_HOME=>$(JAVA_HOME)"
@echo "make anothwe file..."
@$(MAKE) -f makefile.2 #dang qian make jie shi qi wen jian ming

@$(MAKE) -f makefile.2 new:=$(new) #tong guo ming ling hang chuan di

makefile.2:

test:

@echo "JAVA_HOME=>$(JAVA_HOME)"
@echo "var=>$(var)"

@echo "new=>$(new)"

目标变量(局部变量):

作用域只在指定目标及连带规则中。

target:name<assignment> value

target: override name<assignment> value

var :=D.o

test: var :=test-var

test:

    @echo "test:"

    @echo "var =>$(var)"

模式变量:

模式变量是目标变量的扩展。

作用域只在符合模式的目标及连带规则中。

pattern: name<assignment> value

pattern: override name<assignment> value

new :=Telphi

%e : override new:=test-new //%通配符,名为new的局部变量,作用域是所有以e结束的目标及连带规则

rule :

    @echo "rule:"

    @echo "new=>$(new)" //值为test-new

makefile:

var :=d.t.software
new :=Twelphi
test:var:=test-var
%e:override new :=test-new
test :another
@echo "test:"
@echo "var=>$(var)"
@echo "new=>$(new)"
another:
@echo "another:"
@echo "var=>$(var)"
@echo "new=>$(new)"
rule:
@echo "another:"
@echo "var=>$(var)"

@echo "new=>$(new)"

小结:makefile中的三种变量

全局变量:makefile外部定义的环境变量。

文件变量:makefile中定义的变量。

局部变量:指定目标的变量。

8、条件判断语句

makefile中支持条件判断语句:

可以根据条件的值来决定make的执行。

可以比较两个不同变量或者变量和常量值。

ifxxx(arg1,arg2)

# for ture

else

# for false

endif

注意事项:

条件判断语句只能用于控制make执行的语句;但是,不能控制规则中命令的执行过程。

条件判断语句的语法说明:

常用形式:

ifxxx(arg1,arg2)   //(arg1,arg2)之前有空格,里边不能有空格

其他合法形式:

ifxxx "arg1" "arg2"

ifxxx 'arg1' 'arg2'

ifxxx "arg1" 'arg2'

ifxxx 'arg1' "arg2"

条件判断关键字:

ifeq 判断参数是否相等,相等为true,否则为false

ifneq 判断参数是否不相等,不相等为true,否则为false

ifdef 判断变量是否有值,有值为true,否则为false

ifndef 判断变量是否没有值,没有值为true,否则为false

.PHONY:test
var1 :=A
var2 :=$(var1)
var3 :=
test:
    ifeq ($(var1),$(var2))  
@echo "var1 == var2"
    else
@echo "var1 != var2"
    endif
    ifneq ($(var2),)
@echo "var2 is not empty"
    else
    @echo "is empty"
    endif
    ifndef var3
@echo "var3 is empty"
    else
@echo "var3 is not empty"

    endif

一些工程经验:

条件判断语句之前可以有空格,但不能有Tab字符('\t')。

在条件语句中不要使用自动变量($@, $^, $<)。

一条完整的条件语句必须位于同一个makefile中。

条件判断类似C语言中的宏,预处理阶段有效(加载makefile时对条件判断语句进行处理),执行阶段无效。

make在加载makefile时:首先计算表达式的值(赋值方式不同,计算方式不同)。根据判断语句的表达式决定执行的内容。

.PHONY:test
var1 :=
var2 :=$(var1)
var3 =
var4 =$(var3) #du gui fu zhi jia zai qi wu fa que ding var4
var3=3
test:
    ifdef var1
@echo "var1 is defined"
    else
@echo "var1 is not defined"
    endif
    ifdef var2
@echo "var2 is defined"
    else
@echo "var2 is not defined"
    endif
    ifdef var3
@echo "var3 is defined"
    else
@echo "var3 is not defined"
    endif
    ifdef var4
@echo "var4 is defined"
    else
@echo "var4 is not defined"

    endif

小结:条件判断根据条件的值来决定make的执行。条件判断可以比较两个不同变量或者变量和常量值。

条件判断在预处理阶段有效,执行阶段无效。条件判断不能控制规则中命令的执行过程。

9、函数定义及调用

makefile中支持函数的概念:

make解释器提供了一系列的函数供makefile调用。

在makefile中支持自定义函数实现,并调用执行。

通过define关键字实现自定义函数。

自定义函数的语法:

函数定义:

define func1

    @echo "my name is $(0)."

endef

define func2

    @echo "my name is $(0)." //0号参数函数名自身

    @echo "param=>$(1)" //1号参数调用时第一个实参的值

endef

函数调用:

test:

        $(call func1)

        $(call func2, D.T.Software)

深入理解自定义函数:

自定义函数是一个多行变量,无法直接调用。

自定义函数是一种过程调用,没有任何的返回值。

自定义函数用于定义命令集合,并应用于规则中。

.PHONY:test
define func1
@echo "my name is $(0)"
endef
define func2
@echo "my name is $(0)"
@echo "para 1=>$(1)"
@echo "para 2=>$(2)"
endef
var :=$(call func1) 
#call jiang shi can ti huan dao duo hang min ling dui ying wei zhi 
new :=$(func1)
test:
@echo "new=>$(new)"  //@echo "my name is  "
@echo "var=>$(var)"   //@echo "my name is func1"
$(call func1) #=>@echo my name is func1

$(call func2, d.t.software,delphi)

make解释器中的预定义函数:

make的函数提供了处理文件名,变量和命令的函数。

可以在需要的地方调用函数来处理指定的参数。

函数在调用的地方被替换为处理的结果。

预定义函数的调用:

var:=$(func_name arg1,arg2,...)  返回值  函数名  函数实参

var :=$(abspath ./) //当前目录的绝对地址

test:

    @echo "var =>$(var)"

问题?为什么自定义函数和预定义函数的调用形式完全不同?

本质剖析:

makefile中不支持真正意义上的自定义函数。

自定义函数的本质是多行变量。

预定义的call函数在调用时将参数传递给多行变量。

自定义函数是call函数的实参,并在call中被执行(参数替换,得到命令集合)。

.PHONY:test
define func1
@echo "my name is $(0)"
endef
#func2 := @echo "my name is $(0)"
define func2
@echo "my name is $(0)"
endef
var1 :=$(call func1)
var2 :=$(call func2)
var3 :=$(abspath ./)
var4 :=$(abspath test.cpp)
test:
@echo "var1=>$(var1)"
@echo "var2=>$(var2)"
@echo "var3=>$(var3)"

@echo "var4=>$(var4)"

真正意义的函数调用都是调用makefile中的预定义函数的调用,自定义函数的调用是不存在的,仅仅是模拟的行为。

小结:

make解释器提供了一系列的函数供makefile调用。

自定义函数是一个多行变量,无法直接调用。

自定义函数用于定义命令集合,并应用与规则中。

预定义的call函数在调用时将参数传递给多行变量。

自定义函数是call函数的实参,并在call中被执行。

10、变量与函数的综合示例

实战需求:

自动生成target文件夹存放可执行文件。

自动生成objs文件夹存放编译生成的目标文件(*.o)。

支持调试版本的编译选项。

考虑代码的扩展性。

工具原料:

$(wildcard_pattern):

获取当前工作目录中满足_pattern的文件或目录列表。

$(addprefix_prefix, _names):

给名字列表_names中的每一个名字增加前缀_prefix。

关键技巧:

1.自动获取当前目录下的源文件列表(函数调用)

SRCS :=$(wildcard *.c)

2.根据源文件列表生成目标文件列表(变量的值替换)

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

3.对每一个目标文件列表加上路径前缀(函数调用)

OBJS:=$(addprefix path/, $(OBJS))

规则中的模式替换(目录结构)

工作目录中存在func.c和main.c =>

% .o : %.c  //%.c用于模式匹配当前目录下的文件,% .o用于将% .c匹配成功的文件名进行模式替换,.c替换为 .o

        gcc -o $@ -c $^ =>

func.o : func.c

        gcc -o $@ -c $^

main.o : main.c

        gcc -o $@ -c $^

编译规则的依赖:

all->target->dirs(创建文件夹) objs(编译目标文件) 生成可执行文件(链接)

makefile:

CC :=gcc
MKDIR :=mkdir
#chuang jian wen jian jia
RM :=rm -fr
DIR_OBJS := objs
DIR_TARGET :=target
DIRS :=$(DIR_OBJS) $(DIR_TARGET)
TARGET :=$(DIR_TARGET)/hello-makefile.out
SRCS :=$(wildcard *.c)
#main.c const.c func.c
OBJS :=$(SRCS:.c=.o)
#main.o const.o func.o
OBJS :=$(addprefix $(DIR_OBJS)/,$(OBJS))
#objs/main.o objs/const.o objs/func.o
.PHONY: rebuild clean all
$(TARGET):$(DIRS) $(OBJS)
$(CC) -o $@ $(OBJS) #lian jie
  @echo "Target file=> $@"
 $(DIRS):
$(MKDIR) $@ #chuang jian liang ge wenjianjia
 $(DIR_OBJS)/%.o : %.c
    ifeq ($(DEBUG),true)
$(CC) -o $@ -g -c $^ #dai tiao shi
    else
$(CC) -o $@ -c $^
    endif
 rebuild: clean all
 all: $(TARGET)
 clean:

$(RM) $(DIRS)

查看反汇编:

objdump -S hello-makefile.out  

#objdump命令反编译回去查看是否不带调试版本的可执行程序(汇编程序)

小结:目录可以成为目标的依赖,在规则中创建目录。

预定义函数是makefile实战时不可或缺的部分。

规则中的模式匹配可以直接针对目录中的文件。

可以使用命令行变量编译特殊的目标版本。

猜你喜欢

转载自blog.csdn.net/ws857707645/article/details/80758606
今日推荐