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

时间:2019-03-17 07:17:38

标签: 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来生成所有目标文件,因此无法构建可执行文件,因为我在配方命令中为{使用了$<自动变量{1}}目标。

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

$(OBJECT_FILES)

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

1 个答案:

答案 0 :(得分:1)

根据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 $@