Skip to main content

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!