Build 在Makefile中,如果另一个目标已过期,是否可能有一个目标已过期?
我想写一条如下的规则:Build 在Makefile中,如果另一个目标已过期,是否可能有一个目标已过期?,build,makefile,gnu-make,Build,Makefile,Gnu Make,我想写一条如下的规则: 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
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编译过程如下所示:
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
.vala
文件,生成一个.vapi
文件(类似于头文件).vala
文件,生成一个.c
文件(这需要将单个.vala
文件和每个.vapi
文件提供给编译器).c->.o->executable/library
过程.vapi
/.c
文件的内容已更改,则Vala编译器仅更新该文件。这是为了防止不必要的.c->.o
重新编译
在makefile中:
- 如果自上次vala编译器重新生成
文件(不是上次修改.vapi
文件)以来,.vapi
文件已更改,则.vapi
文件已过期.vapi
- 如果自上次vala编译器重新生成
文件(不是上次修改.c
文件)以来,.c
文件或任何.c
文件已更改,则.vapi
文件已过期.c
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
的时间戳。从手册页:
以下内容似乎与您对
.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
%
这行得通吗?有一种技术大致相当于您在Kernighan&Pike(1984)中希望使用的技术,与Yacc语法一起使用 Yacc源文件可能是
grammar.y
。Yacc的默认输出文件是y.tab.c
和y.tab.h
。其他文件(尤其是词法分析器)依赖于头文件,但是头文件并不经常改变,即使语法(操作)的C代码改变了头文件。因此,确保词法分析器使用的头只有在Yacc生成的头不同时才被更改是明智的。处理这个问题的方法是让词法分析器包括x.tab.h
(而不是y.tab.h
),并且仅当存在差异时,才在旧的x.tab.h
上复制一个新的y.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
和filename.c
,以及需要filename.Vala
中的代码服务的其他Vala源文件将自动包括filename.vapi
你说: 在makefile中:
- 如果自上次vala编译器重新生成
文件(不是上次修改.vapi
文件)以来,.vapi
文件已更改,则.vapi
文件已过期.vapi
- 如果自上次vala编译器重新生成
文件(不是上次修改.c
文件)以来,.c
文件或任何.c
文件已更改,则.vapi
文件已过期.c
%.vapi: %.vala
$(VALAC) -h $*.vala
%.c: %.vala
$(VALAC) -c $*.vala
其中(我猜,-h
选项从Vala源生成头文件(.vapi
),相应的-c
选项生成c源文件(.c
)
第二条规则也是正常的源/对象关系:
%.vapi: %.vala
$(VALAC) -h $*.vala
%.c: %.vala
$(VALAC) -c $*.vala
这表示如果.vala
文件比.c
文件更新,则.c
文件将从.vala
文件重新生成。
此外,.c
文件取决于它包括的.vapi
文件:
file1.c: file2.vapi file3.vapi file4.vapi ...
我最终解决了这个问题,添加了一个顶层规则,确保戳记始终处于待办状态,并为实际输出文件添加了空规则:
all: %.out.stamp
%.out: ;
从技术上讲,这并不完全是我所做的,因为我不是手工编写makefile(我正在使用cmake)。在CMake术语中,我添加了一个自定义目标,它依赖于所有
.vapi.stamp
和.dep
(类似于.c.stamp
)文件。从.c
文件构建可执行文件/库的CMake目标依赖于此目标。在第二个示例中:为什么不无条件地触摸foo.out
(或者,至少,如果没有发生错误)?实际上,我在我的一个项目中面临类似的问题。目前我只接受它,但我肯定希望看到一个解决方案。valac
的关键行为是:运行$(valac)--fast vapi=foo.vapi foo.vala
可能不会更改foo.vapi
的修改日期$(VALAC)-C foo.vala--使用fast vapi=*。vapi
可能不会更改foo.C
的修改日期。所以foo.vapi
/foo.c
永远过时。啊,我可能又误解了。如果问题是“可能不会更改修改日期,而且应该更改”,那么一个有用的模式可能是$(VALAC)--fast vapi=$@$<&&touch$@
,这将确保编译成功后,$@(=foo.vapi)会更新。但也许你已经试过了。这对你来说不起作用