【MakeFile】基础培训2

一,定义多行变量

前面定义的变量都是单行的。

变量值有多行,多用于定义shell指令

语法

perl 复制代码
define <varable_name>  # 默认为 = 
# 变量内容
endef
​
define <varable_name> :=
# 变量内容
endef
​
define <varable_name> +=
# 变量内容
endef

示例:

然后可以看到我们可以用define和endef来定义一个多行变量

二,取消变量

如果想清除一个变量,用以下方法

复制代码
undefine <变量名>   如 undefine files,  undefine objs


不难看到这样输出的就是Nothing to be done没有东西可以执行,那么就是表示执行成功,这里因为要强制将all输出出来,这里就把all设置为了伪目标。

三,环境变量的使用

系统中的环境变量可以直接在Makefile中直接使用,使用方法跟普通变量一样

perl 复制代码
all:
    @echo $(USERNAME)
    @echo $(JAVA_HOME)
    @echo $(SystemRoot)

这样就可以使用环境变量了

四,变量替换引用

语法:$(var:a=b),意思是将变量var的值当中每一项结尾的a替换为b,直接上例子

perl 复制代码
files = main.cpp hello.cpp
objs := $(files:.cpp=.o) # main.o hello.o
# 另一种写法
objs := $(files:%.cpp=%.o)

这样我们可以看到这样对于我们操作更简便了

五,变量覆盖


这样就可以将原先的变量进行覆盖

六,局部变量和全局变量


局部变量就是在前面加上对应的目标,这样就知道这个局部变量是从属于哪一个目标了,然后全局变量就是直接变量等于一直值就可以。

七,自动变量

$@:①本条规则的目标名;②如果目标是归档文件的成员,则为归档文件名;③在多目标的模式规则中, 为导致本条规则方法执行的那个目标名;

$<:本条规则的第一个依赖名称

$?:依赖中修改时间晚于目标文件修改时间的所有文件名,以空格隔开

$^:所有依赖文件名,文件名不会重复,不包含order-only依赖

$+:类似上一个, 表示所有依赖文件名,包括重复的文件名,不包含order-only依赖

$|:所有order-only依赖文件名

$*:(简单理解)目标文件名的主干部分(即不包括后缀名)

$%:如果目标不是归档文件,则为空;如果目标是归档文件成员,则为对应的成员文件名

以下变量对应上述变量,D为对应变量所在的目录,结尾不带/,F为对应变量除去目录部分的文件名

(@D) (@F)

(\*D) (*F)

(%D) (%F)

(\(<F)

(\^D) (^F)

(+D) (+F)

(?D) (?F)

八,二次展开

前面说过依赖中的变量都是在Makefile读取阶段立即展开的。如果想让依赖的的变量延迟展开,可以使用.SECONDEXPANSION:,添加之后,在依赖中使用变量时用$$,可以让变量在第二阶段进行二次展开,从而达到延迟展开的效果。

perl 复制代码
VAR1 = main.cpp
.SECONDEXPANSION:
all: $$(VAR1)
    @echo $^
​
VAR1 = hello.cpp

九,多目标与多规则(简写)

显式规则中一条规则可以有多个目标,多个目标可以是相互独立的目标,也可以是组合目标,用写法来区分

独立多目标

相互独立的多个目标与依赖之间直接用:,常用这种方式的有以下两种情况

  1. 只需要写目标和依赖,不需要写方法的时候

    复制代码
    block.o input.o scene.o : common.h

    这种写法等价于

    复制代码
    block.o : common.h
    input.o : common.h
    scene.o : common.h
  2. 生成(更新)目标的方法写法一样的,只是依赖与目标不一样时。之前写的Makfile中,有如下代码:

    复制代码
    block.o: block.cpp common.h block.h color.h
        g++ -c block.cpp
    command.o: command.cpp command.h scene.h
        g++ -c command.cpp
    input.o: input.cpp common.h utility.inl
        g++ -c input.cpp
    main.o: main.cpp scene.h input.h test.h
        g++ -c main.cpp
    scene.o: scene.cpp common.h scene.h utility.inl
        g++ -c scene.cpp
    test.o: test.cpp test.h
        g++ -c test.cpp

    所有.o文件的生成都用的同一方法

    复制代码
    g++ -c <文件名>

    如果不考虑依赖源文件进行更新时,可以进行简写如下:

    复制代码
    block.o command.o input.o main.o scene.o test.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)

    这种写法实际上等价于

    复制代码
    block.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)
    command.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)
    input.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)
    main.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)
    scene.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)
    test.o : common.h block.h command.h ...
        g++ -c $(@:%.o=%.cpp)

独立多目标虽然写在一起,但是每个目标都是单独调用一次方法来更新的。和分开写效果一样。

最后也可以是这种形式,多目标形式
这里就是利用隐式规则来判断,就是make他自己判断依赖文件是什么

组合多目标

多目标与依赖之前用&:,这样的多个目标称为组合目标。与独立多目标的区别在于,独立多目标每个目标的更新需要单独调用一次更新方法。而组合多目标调用一次方法将更新所有目标

复制代码
block.o input.o scene.o &: block.cpp input.cpp scene.cpp common.h
    g++ -c block.cpp
    g++ -c input.cpp
    g++ -c scene.cpp

所有目标的更新方法都写到其中,每次更新只会调用一次

同一目标多条规则

同一目标可以对应多条规则。同一目标的所有规则中的依赖会被合并。但如果同一目标对应的多条规则都写了更新方法,则会使用最新的一条更新方法,并且会输出警告信息。

同一目标多规则通常用来给多个目标添加依赖而不用改动已写好的部分。

复制代码
input.o: input.cpp utility.inl
    g++ -c input.cpp
main.o: main.cpp scene.h input.h test.h
    g++ -c main.cpp
scene.o: scene.cpp scene.h utility.inl
    g++ -c scene.cpp
​
input.o main.o scene.o : common.h

同时给三个目标添加了一个依赖common.h,但是不用修改上面已写好的部分。

相关推荐
tod11313 天前
Makefile进阶(上)
linux·运维·服务器·windows·makefile·进程
一个平凡而乐于分享的小比特1 个月前
Makefile 源码编译系统详解
linux·makefile
一个平凡而乐于分享的小比特1 个月前
Autoconf:Linux自动生成Makefile的详解
makefile·cmake·autoconf
一个平凡而乐于分享的小比特1 个月前
Linux内核构建三剑客:Kconfig、.config与Makefile关系详解
linux·makefile·kconfig·.config
ベadvance courageouslyミ1 个月前
项目一(线程邮箱)
c语言·线程·makefile·进程间通信·线程邮箱
熊猫钓鱼>_>1 个月前
Makefile应用场景实践日志:构建高效C/C++项目工作流
c语言·c++·bug·mfc·makefile·编译·kmp
___波子 Pro Max.2 个月前
Makefile设置DEBUG宏定义方法总结
makefile·make
乖乖是干饭王2 个月前
Linux 内核 Kbuild 中的 ld 调用机制
linux·c·makefile
fareast_mzh2 个月前
redis: undefined reference to `log‘
redis·makefile