Makefile 中 :
和 ::
的使用指南
1. 概述
在 Makefile 中,:
(单冒号)和 ::
(双冒号)都用于定义目标(target),但它们的行为存在关键区别。理解它们的用法可以帮助我们更好地组织 Makefile,提高可维护性和灵活性。
2. :
(单冒号)与 ::
(双冒号)的区别
语法 | 行为 |
---|---|
: (单冒号) | 定义唯一规则,如果同一目标出现多次,后面的规则会覆盖前面的规则 |
:: (双冒号) | 定义多个独立规则,同一目标可以有多个规则,所有规则都会被执行 |
3. :
(单冒号)的用法
3.1 基本示例
all: build
@echo "Running build"
all: test
@echo "Running test"
执行 make all
结果:
Running test
解释:
all:
目标被定义了两次。- 后面的
all: test
覆盖 了前面的all: build
,因此只执行test
相关的命令。
3.2 依赖的覆盖
all: build
test:
@echo "Testing..."
all: test # 覆盖前面的规则
执行 make all
结果:
Testing...
解释:
all: build
先定义了build
依赖。all: test
覆盖了前面的all: build
,最终all
只依赖test
。
适用场景:
- 适用于单一规则的目标,如
CC = gcc
这类变量定义。 - 确保不执行重复规则,仅保留最后一次的定义。
4. ::
(双冒号)的用法
4.1 基本示例
all:: build
@echo "Running build"
all:: test
@echo "Running test"
执行 make all
结果:
Running build
Running test
解释:
all::
目标被定义了两次,但不会相互覆盖。make all
会依次执行所有all::
规则。
4.2 组合依赖
test:: unit-test
t@echo "Integration testing..."
test:: integration-test
t@echo "Unit testing..."
执行 make test
结果:
Integration testing...
Unit testing...
解释:
test::
目标多次定义,每个规则都会被执行。
适用场景:
- 适用于模块化规则,比如
make test
可能需要多个测试步骤。 - 扩展性更强,多个
Makefile
片段可以独立定义test::
,不会相互覆盖。
5. :
vs ::
适用场景总结
适用场景 | 使用 : (单冒号) | 使用 :: (双冒号) |
---|---|---|
唯一规则目标 | ✅ | ❌ |
可累积执行的目标 | ❌ | ✅ |
变量赋值(如 CC=gcc ) | ✅ | ❌ |
多 Makefile 规则合并 | ❌ | ✅ |
防止规则覆盖 | ❌ | ✅ |
6. 结论
:
(单冒号) 适用于唯一规则,如果目标重复定义,后面的规则会覆盖前面的。::
(双冒号) 允许多次定义相同目标,并且所有规则都会被执行。- 如果 Makefile 可能被多个文件拆分并包含(
include Makefile.common
),推荐使用::
以避免目标覆盖。
🚀 掌握 :
和 ::
的区别,有助于编写更灵活和可维护的 Makefile!