如何在 Makefile (GNU Make) 中获得关于目标的先决条件?

How to get prerequisites with respect to the target in Makefile (GNU Make)?

有没有办法在 Makefile (GNU Make) 中获取对应于目标的先决条件?

例如,考虑以下 Makefile:

CXX = g++
CFLAGS = -Wall
MODULE_NAME = myRenderer
BUILD_DIR = bin

SOURCE_FILES = renderer/tracer.cpp renderer/lights/DiffuseLight.cpp renderer/materials/ScatterUtils.cpp
OBJECT_FILES = $(patsubst %,$(BUILD_DIR)/%, $(notdir $(SOURCE_FILES:.cpp=.o)))

$(BUILD_DIR)/$(MODULE_NAME): $(OBJECT_FILES)
    $(CXX) -o $@ $^

$(OBJECT_FILES): $(SOURCE_FILES)
    @mkdir -p "$(BUILD_DIR)"
    $(CXX) $(CFLAGS) -I. -c $< -o $@

当我 运行 make 时,我可以看到执行了以下命令:

g++ -Wall -I. -c renderer/tracer.cpp -o bin/tracer.o
g++ -Wall -I. -c renderer/tracer.cpp -o bin/DiffuseLight.o
g++ -Wall -I. -c renderer/tracer.cpp -o bin/ScatterUtils.o
g++ -o bin/myRenderer bin/tracer.o bin/DiffuseLight.o bin/ScatterUtils.o

显然,这无法构建可执行文件,因为它仅使用第一个先决条件,即 renderer/tracer.cpp 生成所有目标文件,因为我在配方命令中使用 $< 自动变量$(OBJECT_FILES) 目标。

我想知道如何修复我的 Makefile 以便能够执行这些命令:

g++ -Wall -I. -c renderer/tracer.cpp -o bin/tracer.o
g++ -Wall -I. -c renderer/lights/DiffuseLight.cpp -o bin/DiffuseLight.o
g++ -Wall -I. -c renderer/materials/ScatterUtils.cpp -o bin/ScatterUtils.o
g++ -o bin/myRenderer bin/tracer.o bin/DiffuseLight.o bin/ScatterUtils.o

我似乎找不到正确的自动变量或获取正确的源文件以构建给定目标文件的方法。

根据 Matt 的建议,您有(至少)两个选择:

  1. 一条编译规则:

    # $(1): source file
    define MY_RULE
    $$(patsubst %.cpp,$$(BUILD_DIR)/%.o,$$(notdir $(1))): $(1)
        @mkdir -p "$$(BUILD_DIR)"
        $$(CXX) $$(CFLAGS) -I. -c $$< -o $$@
    endef
    $(foreach f,$(SOURCE_FILES),$(eval $(call MY_RULE,$(f))))
    

    注意用于转义第一个扩展的 $$(详细解释见 The eval Function)。

  2. vpath directive:

    vpath %.cpp $(dir $(SOURCE_FILES))
    
    $(BUILD_DIR)/%.o: %.cpp
        @mkdir -p "$(BUILD_DIR)"
        $(CXX) $(CFLAGS) -I. -c $< -o $@