makefile在一次调用中编译多个源文件

makefile在一次调用中编译多个源文件,makefile,gnu-make,Makefile,Gnu Make,假设我有两个源文件,它们都包含一个头文件。 a、 c: b、 c: ab.h: 我想要一个可以在一次调用a.c和b.c中编译的makefile。如果ab.h是新的,或者a.c和b.c都是新的,那么我想要: gcc-c a.c b.c 触摸ab时间戳 否则,我只想重新编译过期的文件 这是一个很小的例子,我需要一个可伸缩的东西。我试图解决这个问题,但我不知道如何解决 这是一个使用C的示例,但我的实际用途是编译大型HDL项目。由于HDL编译器的调用有很高的开销,因此最好对多个文件调用一次该工具,而不是

假设我有两个源文件,它们都包含一个头文件。 a、 c:

b、 c:

ab.h:

我想要一个可以在一次调用a.c和b.c中编译的makefile。如果ab.h是新的,或者a.c和b.c都是新的,那么我想要: gcc-c a.c b.c 触摸ab时间戳 否则,我只想重新编译过期的文件

这是一个很小的例子,我需要一个可伸缩的东西。我试图解决这个问题,但我不知道如何解决

这是一个使用C的示例,但我的实际用途是编译大型HDL项目。由于HDL编译器的调用有很高的开销,因此最好对多个文件调用一次该工具,而不是对每个文件单独调用

我试过的是:

a.c: ab.h ;
b.c: ab.h ;

ab.timestamp: a.c b.c
  gcc -c $?
  touch ab.timestamp
这行不通,我需要这样的东西:

ab.timestamp: a.c b.c ab.h
  gcc -c a.c b.c
  touch ab.timestamp
这是我不想要的。我想要美元?指示需要重新编译的正确文件。我知道我可以使用$(if)和$(filter)函数来解决这个问题,但我希望有更无缝的东西

我正在使用GNU Make

谢谢,
Nachum

这是一个技巧,但它可能会起作用:

all: ab.timestamp

SOURCES = a.c b.c ab.h
a.o: a.c ab.h
b.o: b.c ab.h

CHANGED :=
%.o: %.c ; $(eval CHANGED += $<)

ab.timestamp: $(SOURCES) $(patsubst %.c,%.o,$(filter %.c,$(SOURCES)))
        gcc -c $(CHANGED)
        touch $@
all:ab.timestamp
来源=a.c b.c ab.h
a、 o:a.c ab.h
b、 o:b.c ab.h
更改:=

%.o:%.c;$(eval CHANGED+=$这是一个难题,但似乎可行。请触摸源文件以使其与标题保持最新:

a.c b.c: ab.h
    @touch $@

ab.timestamp: a.c b.c
    gcc -c $?
    touch ab.timestamp

为什么不是第一个版本的<代码> $>代码>工作?我创建了一个样例MaX文件,它为My。触摸Ab.h,然后制作。将考虑ab.时间戳到目前为止的B/C A.C和B.C不是新的。当然,因为你不从.H文件中创建一个.c文件。即使建立了时间戳,它也不会做WH。在您需要的时候,因为.h文件的时间戳比.c文件的时间戳要新,所以在您将.c文件修改为新文件之前,它总是会被认为是过时的。是的,这就是问题的关键。有没有办法实现我想要的。我看到在所需增强的列表中有一个对包含类型先决条件的请求e、 这就是我想要的。h将是.c文件的一个包含前提。你知道没有这样的增强,我怎么能做到这一点吗?我不认为你提到的增强对你有帮助。我想说的是,你想要的是不可能的,因为没有办法让make知道一个文件何时被正确地Make不保留自己的更新信息数据库:它依赖于文件系统修改时间,并且仅依赖于这些时间。因为您没有更改目标(.c)时间戳,一旦你改变了.h文件,下一次的运行仍然会考虑.c文件过期,然后运行,等等,直到.c文件mod时间以某种方式被更新。嗯……这似乎不起作用。或者说,它工作得太多了。如果只是<>代码> A.C./Cuth>已经改变了,它仍然编译两个源。它对我有用。在我的系统中。em,
gcc-c foo.c bar.c
将创建两个对象文件,
foo.o
bar.o
。这不会发生在您的系统上吗?在这种情况下,如果您触摸
a.c
,它应该只会注意到
a.o
已过期并尝试重新生成,并且只会将
a.c
添加到
已更改的
变量中。我错了。我在没有实际编译的情况下抄近路监视
更改了
,并中断了变量的实际构造。这个makefile可以工作。这正是我希望避免的复杂性…糟糕的是,没有无缝的方法来做到这一点。不可能有无缝的方法来支持每一个可能的用例如果你离开标准模型,你会遇到更多的接缝。对于makefiles来说,这一点与任何其他语言都一样。这可能会起作用,但像这样接触源文件会让人很不舒服。例如,许多编辑器会将时间戳的更改视为文件已被其他进程修改,并要求你重新加载它。如果在每次构建之后,你的编辑器的所有缓冲区都过时了,那就不好了。@Madcascient:我同意,它有缺点。我先这么做,是为了试着弄清楚我想要什么。但是出于前面提到的所有原因,我当然不想碰文件。
ab.timestamp: a.c b.c ab.h
  gcc -c a.c b.c
  touch ab.timestamp
all: ab.timestamp

SOURCES = a.c b.c ab.h
a.o: a.c ab.h
b.o: b.c ab.h

CHANGED :=
%.o: %.c ; $(eval CHANGED += $<)

ab.timestamp: $(SOURCES) $(patsubst %.c,%.o,$(filter %.c,$(SOURCES)))
        gcc -c $(CHANGED)
        touch $@
a.c b.c: ab.h
    @touch $@

ab.timestamp: a.c b.c
    gcc -c $?
    touch ab.timestamp