我想写一个看起来像这样的规则:
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.out
,make
将始终将foo.out
视为过期。
有没有办法写这种规则?
编辑:解释为什么我没有无条件地触摸foo.out
:
我正在与Vala合作。 Vala编译过程如下所示:
.vala
文件,生成一个.vapi
文件(类似于头文件)。.vala
文件,生成一个.c
文件(这需要单独的.vala
文件和每个 .vapi
文件编译器).c -> .o -> executable/library
流程。对于步骤#1和#2,Vala编译器仅在其内容已更改时才更新.vapi
/ .c
文件。这是为了防止不必要的.c -> .o
重新编译。
在makefile中:
.vapi
文件后.vala
文件发生更改,.vapi
文件已过期(不是.vapi
的最后一次文件被修改了。).c
或任何 .vala
文件发生更改,则.vapi
文件已过期文件(不是最后一次修改.c
文件)。答案 0 :(得分:1)
有一种技术大致相当于你想要在Kernighan& Pike 'The UNIX Programming Environment'(1984),与Yacc语法一起使用。
Yacc源文件可能是grammar.y
。 Yacc的默认输出文件是y.tab.c
和y.tab.h
。其他文件(特别是词法分析器)依赖于标题,但即使语法的C代码(动作),标题也不会经常改变。因此,只有当Yacc生成的标题不同时才能确保词法分析器使用的标题更改是明智的。解决这个问题的方法是让词法分析器包含x.tab.h
(不是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.vapi
和{{1需要filename.c
中代码服务的其他Vala源文件将自动包含filename.vala
。
你说:
在makefile中:
- 如果自上次Vala编译器重新生成
filename.vapi
文件后.vapi
文件发生更改,.vala
文件已过期(不是.vapi
的最后一次文件被修改了。)- 如果自上次Vala编译器重新生成{{1}后
.vapi
或任何.c
文件发生更改,则.vala
文件已过期文件(不是最后一次修改.vapi
文件)。
第一条规则就是普通的源/对象关系:
.c
其中(我猜).c
选项从Vala源生成标头(%.vapi: %.vala
$(VALAC) -h $*.vala
)文件,相应的-h
选项生成C源({{1文件。
第二条规则也是正常的源/对象关系:
.vapi
这表示如果-c
文件比.c
文件更新,则会从%.c: %.vala
$(VALAC) -c $*.vala
文件重新生成.c
文件。
此外,.vala
文件取决于它包含的.vala
文件:
.c
答案 1 :(得分: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.stamp
的时间戳更新为foo.out
的时间戳。从联机帮助页:
-r, --reference=FILE use this file's times instead of current time
答案 2 :(得分: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
%
这有用吗?
答案 3 :(得分:0)
我最后通过添加一个顶级规则来确保邮票始终可用,并且实际输出文件为空规则,从而解决了这个问题:
all: %.out.stamp
%.out: ;
从技术上讲,这并不是我所做的,因为我不是手工编写Makefile(我正在使用cmake)。在CMake术语中,我添加了一个自定义目标,该目标取决于所有.vapi.stamp
和.dep
(类似于.c.stamp
)文件。从.c
文件构建可执行文件/库的CMake目标取决于此目标。