【问题标题】:makefile compile multiple source files in one callmakefile 一次调用编译多个源文件
【发布时间】:2013-06-19 21:43:59
【问题描述】:

假设我有 2 个源文件,它们都包含一个头文件。 交流:

#include "ab.h"

int a() {
    return RETURN_VAL;
}

b.c:

#include "ab.h"

int b() {
    return !RETURN_VAL;
}

ab.h:

#define RETURN_VAL (0)

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

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

这是一个使用 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 和 $( 过滤器函数来解决这个问题,但我希望得到更无缝的东西。

我正在使用 GNU Make。

谢谢, 那胡姆

【问题讨论】:

  • 为什么带有$? 的第一个版本不起作用?它以什么方式失败?我创建了一个示例 makefile,它对我有用。
  • 触摸 ab.h,然后制作。 make 会认为 ab.timestamp 是最新的 b/c a.c 和 b.c 不是新的。
  • 好吧,当然,因为您不会从 .h 文件创建 .c 文件。即使 make 构建了时间戳,它也不会执行您想要的操作,因为由于 .h 文件的时间戳比 .c 文件更新,因此它总是被认为是过时的,直到您将 .c 文件修改为更新。
  • 是的,这就是问题的重点。有没有办法完成我想要的。我看到在所需的增强列表中有一个包含类型先决条件的请求。那会做我想要的。 .h 将是 .c 文件的包含先决条件。你知道如果没有这样的增强,我怎么能做到这一点?
  • 我认为您提到的增强功能不会对您有所帮助。我想说的是,你想要的是不可能的,因为 make 无法知道文件何时正确更新。 Make 不保留自己的更新信息数据库:它依赖于文件系统修改时间,并且仅依赖于那些。由于您没有更改目标 (.c) 时间戳,因此一旦更改 .h 文件,下一次运行 make 仍将认为 .c 文件已过期。然后运行,等等,直到 .c 文件 mod 时间以某种方式更新。

标签: makefile gnu-make


【解决方案1】:

这是一个技巧,但它可能会奏效:

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 发生了变化,它仍然会重新编译这两个源。
  • 它对我有用。在我的系统上,gcc -c foo.c bar.c 将创建两个目标文件,foo.obar.o。这不会发生在您的系统上吗?在这种情况下,如果您触摸a.c,它只会注意到a.o 已过期并尝试重建它,这只会将a.c 添加到CHANGED 变量中。
  • 我错了。我在没有实际编译的情况下,偷偷监控CHANGED,打乱了变量的实际构造。这个 makefile 有效。
  • 而这正是我希望避免的复杂性......真糟糕,没有无缝的方法可以做到这一点。
  • 不可能有无缝的方式来支持所有可能的用例。您离标准模型越远,您遇到的接缝就越多。与任何其他语言相比,makefile 的真实性不亚于任何其他语言。
【解决方案2】:

这是一个组合,但它似乎工作。触摸源文件以使它们与标题一起更新:

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

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

【讨论】:

  • 这可能有效,但像这样接触源文件是一件很糟糕的事情。例如,许多编辑器会将时间戳的更改视为文件已被其他进程修改并要求您重新加载它。如果在每次构建之后,所有编辑器的缓冲区都过期了,那就不好了。
  • @MadScientist:我同意,它有缺点。
  • 我首先这样做,试图弄清楚我想要什么。但当然,出于已经提到的所有原因,我不想触摸文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多