Makefile 双冒号规则

双冒号规则就是使用“::”代替普通规则的“:”得到的规则。当同一个文件作为多
个规则的目标时,
双冒号规则的处理和普通规则的处理过程完全不同
(双冒号规则允许
在多个规则中为同一个目标指定不同的重建目标的命令)。
首先需要明确的是:Makefile
中,一个目标可以出现在多个规则中。但是这些规
则必须是同一类型的规则,要么都是普通规则,要么都是双冒号规则。而不允许一个目
标同时出现在两种不同类型的规则中。
双冒号规则和普通规则的处理的不同点表现在以
下几个方面:
1. 双冒号规则中,当依赖文件比目标更新时。规则将会被执行。

对于一个没有依赖而只有命令行的双冒号规则,当引用此目标时,规则的命令将会被无条件执行。

而普通单冒号规则,当规则的目标文件存在时,此规则的命令永远不会被执行(目标文件永远是最新的)。

2.
当同一个文件作为多个双冒号规则的目标时。这些不同的规则会被独立的处理,而不是像普通规则那样合并所有的依赖到一个目标文件。

这就意味着对这些规则的处理就像多个不同的普通规则一样。就是说多个双冒号规则中的每一个的依赖文件被改变之后,

make 只执行此规则定义的命令,而其它的以这个文件作为目标的双冒号规则将不会被执行。
我们来看一个例子,在我们的 Makefile
中包含以下两个规则:

Newprog :: foo.c
    $(CC) $(CFLAGS) $<
-o [email protected]
Newprog :: bar.c
    $(CC) $(CFLAGS) $< -o
[email protected]

如果“foo.c”文件被修改,执行make以后将根据“foo.c”文件重建目标“Newprog”。
而如果“bar.c”被修改那么“Newprog”将根据“bar.c”被重建。回想一下,如果以
上两个规则为普通规时出现的情况是什么?(make
将会出错并提示错误信息)
当同一个目标出现在多个双冒号规则中时,
规则的执行顺序和普通规则的执行顺序
一样,按照其在 Makefile
中的书写顺序执行。
GNU make
的双冒号规则给我们提供一种根据依赖的更新情况而执行不同的命令
来重建同一目标的机制。一般这种需要的情况很少,所以双冒号规则的使用比较罕见。
一般双冒号规则都需要定义命令,
如果一个双冒号规则没有定义命令,
在执行规则时将
为其目标自动查找隐含规则。

http://blog.csdn.net/terry_linux/archive/2010/05/15/5594904.aspx

----伪目标----
target:
   
commands

如果makefile 所在目录没有target 同名文件:make target 则导致commands
总是被执行。
如果makefile 所在目录下存在target 同名文件:make target 则commands 不被执行,认为target
总是最新的。

.PHONY:target
target:
   
commands

不论makefile 所在目录下存不存在与target 同名文件,make target 导致commands
的执行,与上一种写法的区别是引用‘.PHONY‘
的意义所在。
-----强制目标-----
target:

因为没有命令,所以make target ,与makefile
所在目录下是否存在与target
同名的文件没有直接关系。

-----双冒号规则-----
target::
   
commands

无论makefile 所在目录下存不存在与target同名文件,make target 导致commands
的执行,与使用‘.PHONY‘ 定义的伪目标效果相同。

----------1
.PHONY
target
all:target
    commands1
#
伪目标
target:
   
commands

----------2
all:target
    commands1
#
伪目标
target:
   
commands

---------3
all:target
    commands1
#
强制目标
target:

---------4
all:target
   
commands1
# 双冒号规则
target::
    commands

1和4 make
all执行情况相同,无论makefile 所在目录下存不存在与target 同名文件,commands1 和commands 都被执行。
2和3 make
all执行情况在makefile 所在目录下存在与target 同名文件,commads 不被执行( 认为target 目标是最新的) ,commands1
将被执行;而如果不存在与target 同名的文件,则2 运行效果与1 和4 相同,3 运行将导致commands1
的执行。

.PHONY:target1

all1:target1
    @echo
"all1_target1_.PHONY_command_all1"
target1:
    @echo
"all1_target1_.PHONY_command_target1"
all2:target2
   
@echo "all2_target2_command_all2"
target2:
    @echo
"all2_target2_command_target2"
all3:target3
    @echo
"all3_target3_force_command_all3"
target3:

all4:target4
   
@echo "all4_target4_::_command_all4"
target4::
    @echo
"all4_target4_::_command_target4"

测试方法
make all1
make all2
make
all3
make all4
然后创建4个文件target1-4
touch target{1,2,3,4}
再次执行
make
all1
make all2
make all3
make all4

你会发现
1和4 make
all执行情况相同,无论makefile所在目录下存不存在与target同名文件,commands1 和commands都被执行。
2和3 make
all执行情况在makefile 所在目录下存在与target 同名文件,commads 不被执行( 认为target目标是最新的),commands1
将被执行;而如果不存在与target 同名的文件,则2 运行效果与1 和4 相同,3 运行将导致commands1 的执行。

Makefile 双冒号规则,布布扣,bubuko.com

时间: 2024-10-12 10:26:33

Makefile 双冒号规则的相关文章

转载——c++中冒号(:)和双冒号(::)的用法

1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4; unsigned char c; } ; XXX (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{ _XXX() : y(0xc0) {} }; (3) public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"pub

[email&#160;protected]冒号(:)和双冒号(::)的用法

转自:http://blog.csdn.net/zimingjushi/article/details/6549390 1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{unsigned char a:4;unsigned char c;} ; XXX (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{_XXX() : y(0xc0) {}};

C++中的双冒号作用

1. 作用域符号::的前面一般是类名称,后面一般是该类的成员名称,C++为例避免不同的类有名称相同的成员而采用作用域的方式进行区分 如:A,B表示两个类,在A,B中都有成员member.那么 A::member就表示类A中的成员member B::member就表示类B中的成员member 2. 全局作用域符号: 例如: #include <stdio.h> int count = 0; //全局变量 0 void main() { int count = 10; //局部变量10 print

c++中冒号(:)和双冒号(::)的用法

1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4; unsigned char c; } ; XXX (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{ _XXX() : y(0xc0) {} }; (3) public:和private:后面的冒号,表示后面定义的所有成员都是公有或私有的,直到下一个"pub

c++中的点号(.),冒号(:)和双冒号(::)运算符

1.冒号(:)用法 (1)表示机构内位域的定义(即该变量占几个bit空间) typedef struct _XXX{ unsigned char a:4;  //char型的字符a占4位 unsigned char c; } XXX; (2)构造函数后面的冒号起分割作用,是类给成员变量赋值的方法,初始化列表,更适用于成员变量的常量const型. struct _XXX{ _XXX() : y(0xc0) { } }; (3) public:和private:后面的冒号,表示后面定义的所有成员都是

php中双冒号::的用法

注:本篇博客系转载,出处不可考(至少对我来说不可考...) 双冒号操作符即作用域限定操作符Scope Resolution Operator可以访问静态.const和类中重写的属性与方法. 在类定义外使用的话,使用类名调用.在PHP 5.3.0,可以使用变量代替类名. Program List:用变量在类定义外部访问 <?php class Fruit { const CONST_VALUE = 'Fruit Color'; } $classname = 'Fruit'; echo $class

wind的R接口、况客RSDK学习,双冒号以及quantmod主题

本文主要参考:来自segmentfault上的FinanceR的专栏 https://segmentfault.com/a/1190000004580610 并自己对生疏不解之处做了补充和注释. 当然,况客的R SDK的强大之处在于,你注册账号,进入网站的控制台后,会直接在浏览器模拟出一个RStudio的页面,可以直接运行操作,还可以设置. 而对于的qutke包,托管于github,所谓的API,应当就是指这个包的用法. 每个人会分配一个私钥. 个人感觉,现在他仅仅是提供了一个浏览器平台,以及数

C++ 箭头-&gt; 双冒号:: 点号.操作符区别

点 . 如果变量是一个对象或者对象引用,则用它来访问对象成员. 箭头 -> 如果变量是一个对象指针,则用它来访问对象成员. 双冒号 :: 如果操作目标是一个具有名空间的标识符,则用它来访问其名空间内的东西.具有名空间的东西很多,除了纯粹的namespace外,正如你所知道的还有class,struct,union.C++ 箭头-> 双冒号:: 点号.操作符区别

关于c++中方法名前面的双冒号

#include "iostream" using namespace std; template <typename T> void swap(T &a, T &b) { T tmp = a; a = b; b = tmp; a++; b++; } void TestSwap() { int iA = 10; int iB = 20; double dC = 1.1; double dD = 2.1; char *str1 = "ABC"