3

我想写一个看起来像这样的规则:

foo.out: (out of date if foo.in is newer than foo.out.stamp)
    # update foo.out if and only if the new foo.out has different contents
    # than the old foo.out (a change to foo.in may or may not change foo.out)
    && touch foo.out.stamp

我不能这样做:

foo.out.stamp: foo.in
    # update foo.out if and only if the new foo.out has different contents
    # than the old foo.out (a change to foo.in may or may not change foo.out)
    && touch foo.out.stamp

foo.out: foo.out.stamp

因为如果foo.in更改,但配方foo.out.stamp不变foo.outmake将始终foo.out视为已过期。

有没有办法写这种规则?

编辑:解释为什么我不无条件触摸foo.out

我正在和瓦拉一起工作。Vala 编译过程如下所示:

  1. 对于每个.vala文件,生成一个.vapi文件(类似于头文件)。
  2. 对于每个.vala文件,生成一个.c文件(这需要将单个.vala文件和每个 .vapi文件都提供给编译器)
  3. 继续典型.c -> .o -> executable/library过程。

对于第 1 步和第 2 步,Vala 编译器仅在.vapi/.c文件的内容已更改时才更新它。这是为了防止不必要的.c -> .o重新编译。

在 makefile 术语中:

  • 如果文件自上次 Vala 编译器重新生成文件(不是上次修改文件)后已更改.vapi,则该文件已过期。.vala.vapi.vapi
  • 如果自上次 Vala 编译器重新生成文件(不是上次修改文件)以来该文件或任何.c文件已更改,则该文件已过期。.vala .vapi.c.c
4

4 回答 4

1

有一种技术大致相当于您在 Kernighan & Pike的“The UNIX Programming Environment”(1984 年)中想要使用的技术,用于 Yacc 语法。

Yacc 源文件可能是grammar.y. Yacc 的默认输出文件是y.tab.cy.tab.h. 其他文件(尤其是词法分析器)依赖于标头,但即使语法(动作)的 C 代码更改,标头也不会经常更改。因此,确保词法分析器使用的标头仅在 Yacc 生成的标头不同时才更改是明智的。处理这个问题的方法是让词法分析器包含x.tab.h(not ),并且只有在存在差异时才y.tab.h复制y.tab.h旧的。x.tab.h

x.tab.h: y.tab.h
   -cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h

这在您的上下文中更难应用,因为您似乎无法控制可以以相同方式使用的文件名 - 该filename.vala文件生成filename.vapiand filename.c,而其他需要代码服务的 Vala 源文件filename.vala将自动包含filename.vapi.


你说:

在 makefile 术语中:

  • 如果文件自上次 Vala 编译器重新生成文件(不是上次修改文件)后已更改.vapi,则该文件已过期。.vala.vapi.vapi
  • 如果自上次 Vala 编译器重新生成文件(不是上次修改文件)以来该文件或任何.c文件已更改,则该文件已过期。.vala .vapi.c.c

第一条规则只是正常的源/对象关系:

%.vapi: %.vala
    $(VALAC) -h $*.vala

其中(我猜)该-h选项从 Vala 源代码生成头.vapi文件( ),而相应的-c选项生成 C 源代码(.c)文件。

第二条规则也是正常的源/对象关系:

%.c: %.vala
    $(VALAC) -c $*.vala

这表示如果文件比.c文件更新,则从文件重新生成文件。此外,该文件取决于它包含的文件:.vala.vala.c.c.vapi

file1.c:  file2.vapi file3.vapi file4.vapi ...
于 2012-07-19T13:49:07.080 回答
0

请检查以下是否适合您:

foo.out.stamp: foo.in
    # if the new foo.out has different contents than the old foo.out
    update foo.out && touch foo.out.stamp
    #else
    touch -r foo.out foo.out.stamp

foo.out: foo.out.stamp

的第二次调用将的时间戳更新为的touch时间戳。从手册页:foo.out.stampfoo.out

-r, --reference=FILE
      use this file's times instead of current time
于 2012-07-18T22:21:24.177 回答
0

以下似乎与您对.vapa.vali文件之间关系的描述相匹配:

% cat Makefile
VFILES=A B

.PRECIOUS: $(VFILES:=.vapi)

%.vapi: %.vala
    touch $@

%.c: %.vala $(VFILES:=.vapi)
    echo "$^" >$@

%.o: %.c
    touch $@

all: A.o
% ls
A.vala      B.vala      Makefile
% make A.o
touch A.vapi
touch B.vapi
echo "A.vala A.vapi B.vapi" >A.c
touch A.o
rm A.c
% make B.o
echo "B.vala A.vapi B.vapi" >B.c
touch B.o
rm B.c
% touch A.vala
% make B.o    
touch A.vapi
echo "B.vala A.vapi B.vapi" >B.c
touch B.o
rm B.c
% make A.o
echo "A.vala A.vapi B.vapi" >A.c
touch A.o
rm A.c
% ls -lt
total 24
-rw-r--r--  1 norman  wheel    0 19 Jul 00:11 A.o
-rw-r--r--  1 norman  wheel    0 19 Jul 00:11 A.vapi
-rw-r--r--  1 norman  wheel    0 19 Jul 00:11 B.o
-rw-r--r--  1 norman  wheel    6 19 Jul 00:11 A.vala
-rw-r--r--  1 norman  wheel    0 19 Jul 00:10 B.vapi
-rw-r--r--  1 norman  wheel    6 19 Jul 00:10 B.vala
-rw-r--r--  1 norman  wheel  141 19 Jul 00:09 Makefile
% 

那样有用吗?

于 2012-07-18T23:13:35.450 回答
0

我最终通过添加一个顶级规则来解决这个问题,以确保邮票总是可以做的,并为真正的输出文件设置空规则:

all: %.out.stamp

%.out: ;

从技术上讲,这并不是我所做的,因为我不是手动编写 Makefile(我正在使用 cmake)。在 CMake 术语中,我添加了一个自定义目标,该目标依赖于所有.vapi.stampand .dep(类似于 a .c.stamp)文件。从文件构建可执行文件/库的 CMake 目标.c取决于此目标。

于 2012-07-19T20:15:48.550 回答