在不干扰 -MMD 的情况下覆盖某些目标的隐式规则

Overriding implicit rule of certain targets without interfering with -MMD

假设我有一个简单的 Makefile 像这样:

CXXFLAGS+=-O3 -Wall -pednatic -MMD -Isrc

SRCS=$(shell find src -name '*.cpp')
OBJS=${SRCS:.cpp=.o}

TEST_SRCS=$(shell find test -name '*.cpp')
TEST_OBJS=${TEST_SRCS:.cpp=.o}

all: bin/product

bin/product: $(OBJS)
  $(CXX) ($CXX_FLAGS) -o $@ $^

test: test/runner
  ./test/runner

test/runner: $(TEST_OBJS) $(OBJS)
  $(CXX) ($CXX_FLAGS) -o $@ $^

-include ${OBJS:.o=.d}
-include ${TEST_OBJS:.o=.d}

.PHONY: all test

这里要注意的重要一点是,我有两个独立的二进制目标(一个生成对象来自 src/,一个测试运行器对象来自 src/test/) .我想更改 CXXFLAGS 只是为了测试中的目标(test/runner,还有 test/foo_test.o),而不是 src。我当然可以定义我自己的规则来覆盖隐式规则(注意添加的 -Itest,这是我想如何编译测试的众多差异之一):

test/%.o: test/%.cpp
    $(CXX) $(CXXFLAGS) -Itest -c -o $@ $^

但这有一个不幸的后果,即覆盖了 -MMD 创建的包含的 *.d 文件的依赖项。例如 test/foo_test.d:

test/foo_test.o: test/foo_test.cpp src/foo.o

有什么方法可以在不丢失依赖关系的情况下覆盖 test/ 中对象的隐式规则?

您可以在每个目标的基础上定义或修改 make 变量(参见 GNU make documentation):

$(TEST_OBJS): CXX_FLAGS += -Itest

备注:

  • 您不应该使用相同的 CXX_FLAGS 进行编译和链接。选项不同。例如,您不会将 -I... 选项传递给链接器。请改用 LDFLAGS 进行链接。
  • 您的 Makefile 使用 CXXFLAGSCXX_FLAGS。你的问题有错别字?将选项传递给 C++ 编译器的标准 make 变量是 CXXFLAGS,而不是 CXX_FLAGS.