没有声明规则的 Makefile 依赖?
Makefile dependency without declaring a rule?
我有一个模式规则,可以将打字稿文件中的类型定义转换为 JSON 模式文件。进行这种转换的程序需要两个参数:
source file
的名称
- 要从该文件中提取的
typename
我决定将所需的类型名称编码为目标文件的名称。
<--------- Typename ---------> <------- source file ------->
BlockLanguageGeneratorDocument.json : block-language.description.ts
我定义了这个模式规则来进行转换:
%.json : %.ts
# $^ is the name of the input file
# $(notdir $(basename $@)) is the filename of the target file (without the .json suffix)
$(TYPESCRIPT_JSON_SCHEMA_BIN) --path $^ --type $(notdir $(basename $@)) > "$@.json"
遗憾的是,我设置为依赖项的 <typename>.json: <sourcefile>
规则是比模式规则更具体的规则,因此 模式规则永远不会执行 。所以我决定将转换包装在 define CONVERT_COMMAND
中,并在上述每个定义中简单地使用它:
BlockLanguageGeneratorDocument.json : block-language.description.ts
$(CONVERT_COMMAND)
虽然这确实有效,但重复让我觉得丑陋。有没有一种方法可以声明从一个文件到另一个文件的依赖关系,同时仍然更喜欢模式规则?
最小重现:运行 使用 make BlockLanguageGeneratorDocument.json Unrelated.json
并观察到 echo
永远不会执行。
block-language.description.ts :
touch $@
another.description.ts :
touch $@
%.json : %.ts
echo "generic target"
BlockLanguageGeneratorDocument.json : block-language.description.ts
Unrelated.json : another.description.ts
如果这有帮助:调试输出如下。
❯❯❯ make --debug=verbose BlockLanguageGeneratorDocument.json
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'Makefile'...
Reading makefile 'Makefile.json' (search path) (no ~ expansion)...
Reading makefile '../../Makefile.common' (search path) (no ~ expansion)...
Updating makefiles....
Updating goal targets....
Considering target file 'BlockLanguageGeneratorDocument.json'.
Considering target file 'block-language.description.ts'.
Finished prerequisites of target file 'block-language.description.ts'.
No need to remake target 'block-language.description.ts'.
Finished prerequisites of target file 'BlockLanguageGeneratorDocument.json'.
Prerequisite 'block-language.description.ts' is newer than target 'BlockLanguageGeneratorDocument.json'.
Must remake target 'BlockLanguageGeneratorDocument.json'.
Successfully remade target file 'BlockLanguageGeneratorDocument.json'.
make: 'BlockLanguageGeneratorDocument.json' is up to date.
很难在没有看到 minimal complete example 的情况下回答这个问题,但我想我明白了问题所在。此模式规则:
%.json : %.ts
...whatever...
使用 foo.ts
构建 foo.json
。 Make不会尝试用它来构建BlockLanguageGeneratorDocument.json
,因为没有BlockLanguageGeneratorDocument.ts
.
我想你要找的是这个:
%.json :
@echo do various things with $@ and $^
BlockLanguageGeneratorDocument.json : block-language.description.ts
请注意,第二条规则没有配方,它只是提供先决条件。
假设从依赖项到目标名称的映射定义明确,您可以编写该部分的脚本,将输出发送到 makefile——比如 deps.mk
——并将其包含在主 makefile 中。
名称映射似乎类似于...
<text-with-dashes>.description.ts --> <Capitalized text without dashes>.GeneratorDocument.json
以下 perl 脚本从其 arg 列表中读取每个 .ts
文件名并生成合适的依赖项...
#!/usr/bin/perl -w
# -*- perl -*-
use strict;
while (defined(my $file = shift(@ARGV))) {
my($d) = ($file =~ m,^(.*)\.description\.ts,);
my @d = split("-",$d);
s/(.)/\u\L/ for @d;
$d = join("",@d);
print "\nall: $d"."GeneratorDocument.json\n$d"."GeneratorDocument.json: $file\n\t$(CONVERT_COMMAND)\n";
}
如果我们将上面的脚本命名为 mapname.pl
那么...
./mapname.pl block-language.description.ts
应该给出输出...
all: BlockLanguageGeneratorDocument.json
BlockLanguageGeneratorDocument.json: block-language.description.ts
$(CONVERT_COMMAND)
现在您的主要 makefile 将是...
ALL_TS_FILES := $(wildcard *.description.ts)
MAPNAME := ./mapname.pl
all:
include deps.mk
deps.mk: $(ALL_TS_FILES) $(MAPNAME)
$(MAPNAME) $(ALL_TS_FILES) > $@.tmp
diff -q $@ $@.tmp || mv $@.tmp $@
我有一个模式规则,可以将打字稿文件中的类型定义转换为 JSON 模式文件。进行这种转换的程序需要两个参数:
source file
的名称
- 要从该文件中提取的
typename
我决定将所需的类型名称编码为目标文件的名称。
<--------- Typename ---------> <------- source file ------->
BlockLanguageGeneratorDocument.json : block-language.description.ts
我定义了这个模式规则来进行转换:
%.json : %.ts
# $^ is the name of the input file
# $(notdir $(basename $@)) is the filename of the target file (without the .json suffix)
$(TYPESCRIPT_JSON_SCHEMA_BIN) --path $^ --type $(notdir $(basename $@)) > "$@.json"
遗憾的是,我设置为依赖项的 <typename>.json: <sourcefile>
规则是比模式规则更具体的规则,因此 模式规则永远不会执行 。所以我决定将转换包装在 define CONVERT_COMMAND
中,并在上述每个定义中简单地使用它:
BlockLanguageGeneratorDocument.json : block-language.description.ts
$(CONVERT_COMMAND)
虽然这确实有效,但重复让我觉得丑陋。有没有一种方法可以声明从一个文件到另一个文件的依赖关系,同时仍然更喜欢模式规则?
最小重现:运行 使用 make BlockLanguageGeneratorDocument.json Unrelated.json
并观察到 echo
永远不会执行。
block-language.description.ts :
touch $@
another.description.ts :
touch $@
%.json : %.ts
echo "generic target"
BlockLanguageGeneratorDocument.json : block-language.description.ts
Unrelated.json : another.description.ts
如果这有帮助:调试输出如下。
❯❯❯ make --debug=verbose BlockLanguageGeneratorDocument.json
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'Makefile'...
Reading makefile 'Makefile.json' (search path) (no ~ expansion)...
Reading makefile '../../Makefile.common' (search path) (no ~ expansion)...
Updating makefiles....
Updating goal targets....
Considering target file 'BlockLanguageGeneratorDocument.json'.
Considering target file 'block-language.description.ts'.
Finished prerequisites of target file 'block-language.description.ts'.
No need to remake target 'block-language.description.ts'.
Finished prerequisites of target file 'BlockLanguageGeneratorDocument.json'.
Prerequisite 'block-language.description.ts' is newer than target 'BlockLanguageGeneratorDocument.json'.
Must remake target 'BlockLanguageGeneratorDocument.json'.
Successfully remade target file 'BlockLanguageGeneratorDocument.json'.
make: 'BlockLanguageGeneratorDocument.json' is up to date.
很难在没有看到 minimal complete example 的情况下回答这个问题,但我想我明白了问题所在。此模式规则:
%.json : %.ts
...whatever...
使用 foo.ts
构建 foo.json
。 Make不会尝试用它来构建BlockLanguageGeneratorDocument.json
,因为没有BlockLanguageGeneratorDocument.ts
.
我想你要找的是这个:
%.json :
@echo do various things with $@ and $^
BlockLanguageGeneratorDocument.json : block-language.description.ts
请注意,第二条规则没有配方,它只是提供先决条件。
假设从依赖项到目标名称的映射定义明确,您可以编写该部分的脚本,将输出发送到 makefile——比如 deps.mk
——并将其包含在主 makefile 中。
名称映射似乎类似于...
<text-with-dashes>.description.ts --> <Capitalized text without dashes>.GeneratorDocument.json
以下 perl 脚本从其 arg 列表中读取每个 .ts
文件名并生成合适的依赖项...
#!/usr/bin/perl -w
# -*- perl -*-
use strict;
while (defined(my $file = shift(@ARGV))) {
my($d) = ($file =~ m,^(.*)\.description\.ts,);
my @d = split("-",$d);
s/(.)/\u\L/ for @d;
$d = join("",@d);
print "\nall: $d"."GeneratorDocument.json\n$d"."GeneratorDocument.json: $file\n\t$(CONVERT_COMMAND)\n";
}
如果我们将上面的脚本命名为 mapname.pl
那么...
./mapname.pl block-language.description.ts
应该给出输出...
all: BlockLanguageGeneratorDocument.json
BlockLanguageGeneratorDocument.json: block-language.description.ts
$(CONVERT_COMMAND)
现在您的主要 makefile 将是...
ALL_TS_FILES := $(wildcard *.description.ts)
MAPNAME := ./mapname.pl
all:
include deps.mk
deps.mk: $(ALL_TS_FILES) $(MAPNAME)
$(MAPNAME) $(ALL_TS_FILES) > $@.tmp
diff -q $@ $@.tmp || mv $@.tmp $@