变量的高级主题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了变量的高级主题相关的知识,希望对你有一定的参考价值。

        我们在前面学习了 makefile 中的相关知识,今天我们来看看在 makefile 中变量值的替换。它的替换是指使用指定字符(串)替换变量值中的后缀字符(串),语法格式为:$(var:a=b) 或 ${var:a=b}。注意:a> 替换表达式中不能有任何的空格;b> make 中支持使用 ${ } 对变量进行取值。格式如下

技术分享图片

        还有种便是变量的模式替换是指使用 % 保留变量值中的指定字符,替换其他字符。语法格式为:$(var:a%b=x%y) 或 ${var:a%b=x%y}。注意:a> 替换表达式中不能有任何的空格;b> make 中支持使用 ${ } 对变量进行取值。格式如下

技术分享图片

        规则中的模式替换如下

技术分享图片

        它的意义是通过 target-pattern 从 targets 中匹配子目标;再通过 prereq-pattern 从子目标生成依赖;进而构成完整的规则。我们来看看规则中的模式替换示例如下

技术分享图片

        下来我们通过代码来分析说明

src1 := a.cc b.cc c.cc
obj1 := $(src1:cc=o)

test1 :
    @echo "obj1 => $(obj1)"

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

test2 :
    @echo "obj2 => $(obj2)"

        我们根据之前说的,在 obj1 中将会把 .cc 替换成  .o,把 obj2 中的 a11b.c a22b.c a33b.c 替换成 x11y x22y x33y。我们来看看编译器效果

技术分享图片

        我们看到结果和我们分析的是一样的。下来再来看看模式替换,将之前的 makefile 进行改编

CC := g++
TARGET := hello-makefile.out
OBJS := func.o main.o

$(TARGET) : $(OBJS)
    $(CC) -o [email protected] $^

$(OBJS) : %.o : %.c
    $(CC) -o [email protected] -c $^

.PHONY : rebuild clean all

rebuild : clean all

all : $(TARGET)
    
clean : 
    $(RM) *.o $(TARGET)

        我们来看看编译效果和之前的是一样的吗?

技术分享图片

        结果是一样的,这样的写的意义在哪呢?在大型的工程项目中,.c源文件是成千上万的。我们就可以利用模式替换来代替重复的工作,比如我们想添加一个 const.c 文件,便可以直接在第 3 行直接加上 const.o 就OK了。我们来试试看


const.c 源码

const char* g_hello = "hello makefile";


func.c 源码

#include "stdio.h"

extern char* g_hello;

void foo()
{
    printf("void foo() : %s
", g_hello);
}


main.c 源码

extern void foo();

int main()
{
    foo();
    
    return 0;
}

        我们来看看编译效果

技术分享图片

        我们看到在编译的时候自动加上了编译 const.c 的命令,并最终正确打印出结果。这样感觉是不是很方便哈。那么在 makefile 中变量值还可以嵌套引用,就是一个变量名之中可以包含对其它变量的引用,嵌套引用的本质是使用一个变量来表示另外一个变量。格式如下

技术分享图片

        下来我们来说说命令行变量,在运行 make 时直接在命令行定义变量。命令行变量默认覆盖 makefile 中定义的变量,格式如下

技术分享图片

        那么命令行变量可以覆盖 makefile 中定义的变量,如果我们不小心手误覆盖了呢?这时 override 关键字就登场了。它是用于指示 makefile 中定义的变量不能被覆盖,变量的定义个赋值都需要使用 override 关键字。格式如下

技术分享图片

        下来我们来看看 makefile 中的  define 关键字,它是用于在 makefile 中定义多行变量,多行变量的定义从变量名开始带 endef 结束。可使用 override 关键字防止变量被覆盖,define 定义的变量等价于使用 = 定义的变量。格式入下

技术分享图片

        下来我们还是以代码为例来进行说明

hm := hello makefile

override var := override-test

define foo
I'm fool!
endef

override define cmd
    @echo "run cmd ls ..."
    @ls
endef

test :
    @echo "hm => $(hm)"
    @echo "var => $(var)"
    @echo "foo => $(foo)"
    ${cmd}

        我们来编译看看结果

技术分享图片

        我们看到在没有被 override 关键字修饰的变量 hm 可以在命令行对它进行改写,但是变量 cmd 因为被 override 修饰了,因此就在命令行里面的修改是无效的。下来我们还说说 makefile 中的环境变量(全局变量),在 makefile 中能够直接使用环境变量的值。它是在定义了同名变量的话,环境变量将被覆盖,运行 make 时指定“-e”选项,优先使用环境变量。那么为什么要在 makefile 中使用环境变量呢?它的优势是环境变量可以在所有的 makefile 中使用,劣势是过多的依赖于环境变量便会导致移植性降低。那么变量在不同的 makefile 支架的传递方式有哪些呢?a> 直接在外部定义环境变量进行传递;b> 使用 export 定义变量进行传递;c> 定义 make 命令进行传递(一般推荐使用这种)

        下来我们还是以代码为例来进行分析

export var := D.T.Software
new := TDelphi

test :
    @echo "make another file ..."
    @$(MAKE) -f makefile.4
    @$(MAKE) -f makefile.4 new:=$(new)


makefile.4 源码

test :
    @echo "var => $(var)"
    @echo "new => $(new)"

        我们来看看编译结果

技术分享图片

        我们看到在第一次的时候 new 为空,在第二次的时候 new 为我们设置的字符串。两次的 var 都传递过去了就是因为我们使用了 export 这个关键字。下来我们来看看目标变量(局部变量),其作用域只在指定目标及连带规则中。格式如下

技术分享图片

        那么模式变量便是目标变量的扩展,其作用域只在符合模式的目标及连带规则中。格式如下

技术分享图片

        下来还是以代码为例来进行分析说明

var := D.T.Software
new := TDelphi

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 "rule :"
    @echo "var => $(var)"
    @echo "new => $(new)"

        我们来看看编译结果

技术分享图片

        因为 %e 的匹配规则,所以在目标 rule 中,它的 new 为 test-new,凡是跟 test 目标相关的 var 都是 test-var。通过对 makefile 中变量的学习,总结如下:1、makefile 中的变量值能够嵌套引用;2、命令行中定义的变量能够覆盖 makefile 中定义的变量;3、override 用于提示 makefile 中定义的变量不能被覆盖;4、define 用于在 makefile 中定义值为多行的变量;5、makefile 中的三种变量:a> 全局变量是指 makefile 外部定义的环境变量;b> 文件变量是在 makefile 中定义的变量;c> 局部变量是指定目标的变量。


         欢迎大家一起来学习 makefile,可以加我QQ:243343083

以上是关于变量的高级主题的主要内容,如果未能解决你的问题,请参考以下文章

7. 高级变量主题(下)

6. 变量的高级主题(上)

PHP WordPress条件为主页SlideDeck主题代码片段

主题不适用于片段

Java进阶之光!2021必看-Java高级面试题总结

经验总结:Java高级工程师面试题-字节跳动,成功跳槽阿里!