makefile规则构建多个目标而没有中间文件

时间:2013-04-03 20:12:09

标签: gnu-make

我难以想出一个makefile规则,有几个可执行文件,每个可执行文件依赖于它各自的源文件。所有人都有一个共同的库,每个程序都有一个源文件:a.c编译并与库链接,生成可执行文件a等。

LIB_C_FILES = f1.c f2.c f3.c
LIB_H_FILES = f1.h f2.h f3.h
TARGETS = a b c
CFLAGS = -g -O0 -DDEBUG

.PHONY : all clean

.c.o:
    g++ -c $(CFLAGS) -o $@ $<

all:    $(TARGETS)

${TARGETS} : lib.a ${@:%=%.c}
        g++ $(CFLAGS) ${@:=.c} -o $@ lib.a

lib.a:  ${LIB_C_FILES:.c=.o}  $(LIB_H_FILES)
        ar r $@ $?

库部分工作正常。当可执行文件不存在时,它也可以正常工作。但是当其中一个独立源文件被修改时,它会显示make: Nothing to be done for 'all'.

我不明白让目标a在列表中单独依赖源a.c的正确方法。我错过了什么?

2 个答案:

答案 0 :(得分:3)

为了完整性:只要您可以将所有${TARGETS}与make(noddy)模式匹配匹配,就可以使用普通的旧静态模式规则执行您想要的操作。

${TARGETS}: %: %.C lib.a
    g++ ${CFLAGS} $< -o $@ lib.a

lib.a: ...
    ar ...

.SECONDEXPANSION更具可读性,可能更兼容?

答案 1 :(得分:2)

首先,我假设fio.a是一个拼写错误(你可能意味着lib.a)。

其次,我认为棘手的部分是你的$ {@:%=%。c}先决条件。 AFAIK,$ @不能以这种方式使用。

我认为您可以使用.SECONDEXPANSION获取您正在寻找的行为。

尝试:

.SECONDEXPANSION:
${TARGETS} : lib.a $$(patsubst %,%.c,$$@)

可能有一种旧式的替换方式来执行此操作,但我发现patsubst行比$ {@:%=%。c}更具可读性。

(我应该补充一点,这适用于Gnu make 3.82.YMMV与旧版本的Gnu make,或[天堂禁止]非Gnu版本的make。)