与 Makefile 中的变量扩展混淆

Confusion with variable expansion in Makefile

本文关键字:扩展 变量 Makefile      更新时间:2023-10-16

我有以下催眠制作文件:

all: SOURCE = $(wildcard src/*.cpp)
unity: SOURCE = $(wildcard unity/*.cpp)
OBJECTS = $(SOURCE:.cpp=.o)
all: prog
unity: prog
prog: $(OBJECTS)
    $(CXX) $(OBJECTS) -o prog

我需要根据初始目标使用不同的源文件/对象进行编译。在我看来,变量扩展在依赖项上发生的时间比在目标主体中发生的时间要早得多,因为上面的编译器命令可以使用正确的文件名调用,但是 prog 依赖项中的$OBJECTS仍然是空的,因此没有构建任何对象。

unity 文件夹包含一个组合的源文件,其中包含用于执行 Unity 构建的所有其他源文件。此 Unity 文件由 makefile 生成,但被省略了,实际上可能是多个 Unity 对象文件。

我的设计是失败的事业吗?我是否必须诉诸递归制作来实现这一点?

你不能

那样做。因为一般来说,可能需要构建多个目标。在命令行上,或作为中间目标。因此,设置变量将是模棱两可的。因此,目标特定变量的值"仅在目标命令脚本的上下文中可用(以及其他特定于目标的赋值)。(请参阅文件:make.info,节点:特定于目标)

但是你可以检查 MAKECMDGOALS变量。

您遇到的问题是,当生成文件被读取时,RULES(目标和依赖项列表)中的变量会扩展,而为目标设置的变量(如上面的$(SOURCES))仅在触发taget时设置。 这意味着特定于目标的变量仅在 ACTIONS 中有用,因为这是设置它们后唯一发生的事情。

综上所述,您可以通过递归调用 make 来获得所需的效果:

all:
        $(MAKE) SOURCE="$(wildcard src/*.cpp)" prog
unity:
        $(MAKE) SOURCE="$(wildcard unity/*.cpp)" prog
OBJECTS = $(SOURCE:.cpp=.o)
prog: $(OBJECTS)
        $(CXX) $(OBJECTS) -o prog
.PHONY: all unity

但这不是我通常推荐的。

您不能根据执行的 make 目标使用$SOURCE来表示不同的事情。您可以在此处很好地了解生成文件解析:http://www.gnu.org/software/make/manual/make.html#Reading-Makefiles

对于您的问题,您必须为每种类型的源文件定义不同的变量。例如:

all: SOURCE_ALL = $(wildcard src/*.cpp)
unity: SOURCE_UNITY = $(wildcard unity/*.cpp)
OBJECTS_ALL = $(SOURCE_ALL:.cpp=.o)
OBJECTS_UNITY = $(SOURCE_UNITY:.cpp=.o)
etc ...