有什么方法可以将变量用作GNU Make中的规则和先决条件?

时间:2019-06-24 04:46:13

标签: c++ makefile gnu-make

我正在尝试以一种可以在一些变量中定义所有输入和输出的方式来设置我的Makefile,因此我只需要编写一条规则即可编译项目。这使我可以最小化Makefile代码,并且仍然可以控制项目中的内容。这是相关的代码段:


ROOT_OBJS= \
    $(B)/main.o \
    $(B)/src1.o

ROOT_SRC= \
    $(SRC)/main.cpp \
    $(SRC)/src1.cpp


$(TARGET) : $(ROOT_OBJS)
    $(LD) $(LD_FLAGS) $^ -o $@


$(ROOT_OBJS) : $(ROOT_SRC)
    $(CXX) $(CFLAGS) $< -o $@

除了第二条规则中的$<部分以外,这通常都有效,它始终使用main.cpp。有没有解决的办法,还是我会以错误的方式解决?

编辑:为澄清起见,这是我期望的输出:

g++ main.cpp -o main.o
g++ src1.cpp -o src1.o

这是我得到的输出:

g++ main.cpp -o main.o
g++ main.cpp -o src1.o

我知道这是因为$<拥有第一个依赖关系,我认为make会很聪明,因为.o行为正是我想要的。

$^不是我想要的。我希望gcc为每个cpp文件制作一个单独的目标文件。

1 个答案:

答案 0 :(得分:2)

$<始终以 first 为先决条件。由于您的规则扩展为

$(B)/main.o $(B)/src1.o : $(SRC)/main.cpp $(SRC)/src1.cpp
    $(CXX) $(CFLAGS) $< -o $@

$(SRC)/main.cpp始终是首要条件。 $(B)/main.o而言,$(SRC)/main.cppmake之间没有神奇的联系

如果您希望规则建立此连接,则必须将其编码为规则。有几种方法可以解决此问题。最直接的方法是为每个目标编写单独的规则:

$(B)/main.o : $(SRC)/main.cpp
    $(CXX) $(CFLAGS) $< -o $@
$(B)/src1.o : $(SRC)/src1.cpp
    $(CXX) $(CFLAGS) $< -o $@

您还可以使用如下模式规则:

$(B)/%.o : $(SRC)/%.cpp
    $(CXX) $(CFLAGS) $< -o $@

在这里,$<做正确的事情,因为$(SRC)/%.cpp是用模式参数化的,因此它将扩展到正确的源文件。

您拥有的最大枪支是生成各个规则:

STEMS := main src1

$(foreach stem,$(STEMS), \
    $(eval $(B)/$(stem).o: $(SRC)/$(stem).cpp ; $(CXX) $(CFLAGS) $< -o $@))

这里,我使用$(STEMS)内部函数调用遍历$(foreach)中的所有单词,并使用$(eval)函数调用每次迭代生成一个规则。 仅此一种GNU Make语法,其他make实现可能没有这些功能。但是,这是告诉make要做什么的最通用,最灵活的方法。 GNU Make的函数调用语法已经完成,因此您可以执行任何计算以得出正确的规则。但是,可读性会受到影响,因此请谨慎使用。