如何定义批量和单独构建的 Makefile 规则

问题描述 投票:0回答:1

我有一个使用 dmake v4.1 作为现有工具的 makefile。有一条规则可以使用 % 规则从另一种文件类型构建一种文件类型,如下所示:

%.html : %.docx
  <recipe lines>

此规则采用 Word 文档并运行脚本将其转换为 HTML。但是,由于许多 IS 基础设施规则超出了我的控制范围,因此单独对多个文件运行此规则要慢得多。处理转换的脚本能够处理多个文件,并使用一次 MS Word 启动来处理所有文档。我想尝试找到一种方法来创建支持此功能的 makefile 规则,同时保留单独转换文件的规则。

我曾考虑过修改构建脚本和转换脚本以预先启动MS Word,然后使用现有实例进行文件转换,但如果可能的话,我想尽量避免这种情况。目前,这是我的规则的示例:

FILE_LIST = a.html b.html c.html

all .PHONY : $(FILE_LIST)
  
%.html : %.docx
  $(CONVERT_DOC) $<

我尝试过为批量转换制定单独的规则,如下所示(其中 DOCX_FILE_LIST 只是更改了扩展名的 FILE_LIST):

group_convert .PHONY : $(DOCX_FILE_LIST)
  $(CONVERT_DOC) $^

但是,应该评估过时先决条件列表的

$^
宏似乎总是评估完整的文件列表(可能是因为
group_convert
标记有
.PHONY
)。有可能实现我想要做的事情吗?

makefile dmake
1个回答
0
投票

我尝试过为批量转换制定单独的规则,如下所示(其中 DOCX_FILE_LIST 只是 FILE_LIST 更改了扩展名):

group_convert .PHONY : $(DOCX_FILE_LIST)
  $(CONVERT_DOC) $^

然而,似乎应该评估过时先决条件列表 > 的

$^
宏始终评估为完整文件列表(可能 > 因为
group_convert
标有
.PHONY
)。

我假设

.PHONY
dmake
具有与 GNU
make
相同的意义。 然而,如果它对 dmake

没有特殊意义的话,最终不会有太大变化。

在这种情况下,
group_convert 而不是
,在该示例中标有 
.PHONY
。  相反,
$(DOCX_FILE_LIST)
 扩展中的每个文件都标记为 
.PHONY

。 无论哪种方式的重要性在于,虚假目标始终被认为就其先决条件而言已经过时,无论该名称的文件是否存在或其时间戳是什么。

但是,这可能与您的问题没有多大关系。  由于您似乎打算将 
group_convert 标记为虚假文件,因此我认为实际上不存在这样的文件,并且构建系统也不会创建这样的文件。
就是为什么它的所有先决条件总是被认为比它更新。  永远记住 
make

本身不保留任何状态。 它对于自上次运行以来文件是否已更改没有绝对的意义。 它对目标相对于其先决条件是否过时的分析始终是相对的。

有可能实现我想要做的事情吗?

是的。  您可以让 
make

创建一个标记文件,其目的只是为了记住上次文档转换的时间戳。 您可以使用类似于您已有的规则来做到这一点:
group_convert.timestamp: $(DOCX_FILE_LIST)
    $(CONVERT_DOC) $^
    touch $@

请注意,目标
group_convert.timestamp

不得标记为虚假。 该文件实际上是由构建创建的,它的时间戳用于判断哪些文档需要转换。

但是,有一些警告:
  • 用于判断文件陈旧性的时间戳与辅助文件相关联,而不是与实际的输出文件相关联。 因此,其中一个 .docx 文件有可能在运行该配方期间被修改,在这种情况下,它不会被拾取为要转换的文件,但它的时间戳太旧而无法拾取它用于后续运行的转换。

  • 您可以通过首先更新时间戳来避免这种情况,但这会更糟,因为这样,如果文件转换过程失败或在中间中断(更可能的事件),那么不会丢失任何文件该转换将在后续转换上进行转换,直到再次修改为止。


另一种更复杂的方法是使用每个文件的规则来评估哪些 HTML 文件相对于其 DOCX 源已过期,但将结果收集在文件中而不是立即更新(这相对于

make

的正常操作模式,但可以使其工作)。  然后要有一个 .PHONY 
group_convert
 目标。  让它使用先前创建的文件的内容来控制哪些文档需要转换。  这可能看起来像这样:

CONVERT_FILE = newer_docx_files FILE_LIST = a.html b.html c.html .PHONY: $(CONVERT_FILE) group_convert # This target is phony, so it is always out of date: $(CONVERT_FILE): echo -n > $(CONVERT_FILE) $(MAKE) $(MAKEFLAGS) $(FILE_LIST) # This target is phony, so it is always out of date: group_convert: $(CONVERT_FILE) to_convert=$$(<$<); \ test -n "$${to_convert}" && $(CONVERT_DOC) $${to_convert} # This rule is a lie. It does not actually create .html files from corresponding # .docx files, but it *does* capture the result of the staleness analysis to control # whether the .html file is built later. %.html : %.docx echo '$<' >> $(CONVERT_FILE)
    
© www.soinside.com 2019 - 2024. All rights reserved.