如何使用带有反向链接的Makefile构建HTML?

如何使用带有反向链接的Makefile构建HTML?,makefile,Makefile,我试图静态地构建HTML文件,该文件需要一个标记文件和一个名为“whatlinkshere”的元文件来演示其功能 我相信通过生成一个Makefile,首先生成所有“whatlinkshere”文件,可以有效地完成这项工作。我不认为这可以并行完成,因为生成这些文件的程序需要附加到whatlinkshere文件中,并且可能存在我不太确定如何解决的竞争条件 生成“whatlinkshere”文件后,如果编辑了标记文件,例如foo.mdwn指向bar.mdwn,则只需再次分析foo.mdwn以查看“wh

我试图静态地构建HTML文件,该文件需要一个标记文件和一个名为“whatlinkshere”的元文件来演示其功能

我相信通过生成一个Makefile,首先生成所有“whatlinkshere”文件,可以有效地完成这项工作。我不认为这可以并行完成,因为生成这些文件的程序需要附加到whatlinkshere文件中,并且可能存在我不太确定如何解决的竞争条件

生成“whatlinkshere”文件后,如果编辑了标记文件,例如foo.mdwn指向bar.mdwn,则只需再次分析foo.mdwn以查看“whatlinkshere”更改。最后,只需要重建foo.html和bar.html

我正在努力以自己的方式实现这一目标

INFILES=$(shell find.-name“*.mdwn”)
OUTFILES=$(填充:.mdwn=.html)
LINKFILES=$(填充:.mdwn=.whatlinkshere)
全部:$(外部文件)
#这些都需要在处理HTML之前完成
$(链接文件):$(填充)
@创建反向链接$@
@触碰$@
@开始运行反向链接$<
%.html:%.mdwn%.whatlinkshere
@回音部$^
@cmark$^>$@

当前的问题是第一次运行时没有生成*.whatlinkshere**。我的解决方法是*.mdwn中的i的
;不要运行反向链接;完成
。此外,如前所述,在编辑文件后,不会按照我的要求进行重建。有些事情出了可怕的问题。我错过了什么?

我想我终于明白你的问题了。如果我理解得很好:

  • 您有一堆
    *.mdwn
    源文件
  • 您可以使用
    反向链接.go
    实用程序从
    *.mdwn
    源文件生成
    *.whatlinkshere
    文件。但是此实用程序不会从
    foo.mdwn
    生成
    foo.whatlinkshere
    。它分析
    foo.mdwn
    ,搜索指向其中其他页面的链接,并为找到的
    bar
    的每个链接追加
    [foo](foo.html)
    bar.whatlinkshere
    的引用
  • 从每个
    foo.mdwn
    源文件中,您要使用以下内容构建相应的
    foo.html
    文件:

    $ cmark foo.mdwn foo.whatlinkshere
    
  • 你的规则:

    $(LINKFILES): $(INFILES)
        @echo Creating backlinks $@
        @touch $@
        @go run backlinks.go $<
    
    告诉make
    pageA.whatlinkshere
    pageB.whatlinkshere
    pageC.whatlinkshere
    都是通过一次执行以下命令生成的:

    for m in pageA.mdwn pageB.mdwn pageC.mdwn; do go run backlinks.go $m; done
    
    (make将
    $^
    扩展为所有先决条件,将
    $$m
    扩展为
    $m
    )。当然,我们希望自动计算
    pageA.w%e pageB.w%e pageC.w%e
    模式目标列表。这应该是:

    INFILES     := $(shell find . -name "*.mdwn")
    OUTFILES    := $(INFILES:.mdwn=.html)
    LINKFILES   := $(INFILES:.mdwn=.whatlinkshere)
    LINKPATTERN := $(INFILES:.mdwn=.w%e)
    
    .PHONY: all clean
    .PRECIOUS: $(LINKFILES)
    
    all: $(OUTFILES)
    
    # These need to be all made before the HTML is processed
    $(LINKPATTERN): $(INFILES)
        @echo Creating backlinks
        @rm -f $(LINKFILES)
        @touch $(LINKFILES)
        @for m in $^; do go run backlinks.go $$m; done
    
    %.html: %.mdwn %.whatlinkshere
        @echo Deps $^
        @cmark $^ > $@
    
    clean:
        rm -f $(LINKFILES) $(OUTFILES)
    
    注:

    • 我声明
      all
      clean
      是因为。。。他们就是这样
    • 我将
      whatlinkshere
      文件声明为,因为make将(其中一些)视为中间产物,如果没有此声明,make将在构建HTML文件后删除它们
    • whatlinkshere
      文件的配方中,我添加了
      rm-f$(LINKFILES)
      ,这样,如果配方被执行,我们将从干净的状态重新启动,而不是将新的内容连接到旧的(可能过时的)引用
    • $(LINKPATTERN)
      中的模式干可以是任何字符,但必须至少匹配一个字符。我使用了
      w%e
      ,但是
      whatlin%shere
      也可以。在你的案例中使用足够具体的东西。如果您有
      pageB.where
      文件,请选择
      whatlin%shere
      what%here
    此解决方案有一个缺点,但这是由于您的特殊设置:每次单个
    mdwn
    文件更改时,都必须重新分析(这是正常的),但任何
    whatlinkshere
    文件都可能受到影响。这是不可预测的,它取决于此源文件中已修改的链接。但更成问题的是,此分析的结果被添加到受影响的
    whatlinkshere
    文件中。与此源文件相关的旧内容不会被新内容替换,因此不会对其进行“编辑”。因此,如果只更改源文件中的注释,则其所有链接将再次附加到相应的
    whatlinkshere
    文件中(尽管它们已经存在)。这可能不是你想要的

    这就是为什么上述解决方案会在每次单个源文件更改时删除所有
    whatlinkshere
    文件并重新分析所有源文件。另一个负面后果是,所有HTML文件也必须重新生成,因为所有
    whatlinkshere
    文件都已更改(即使它们的内容没有真正更改,但make不知道这一点)。如果分析速度非常快,并且您有少量的
    mdwn
    文件,则应该可以。否则它是次优的,但由于您的特殊设置,不容易解决

    第二个选项使用递归生成、分离的反向链接文件和标记文件 然而,有一种可能性包括:

  • 使用一个
    whatlinkshere
    文件将每个from/to对的所有反向链接引用分离:
    foo.backlinks/bar。whatlinkshere
    包含对
    foo.mdwn
    中的
    bar
    的所有引用
  • 在第一次调用中使用递归make(当
    步骤
    make变量未设置时)更新所有需要更新的
    whatlinkshere
    文件,并使用第二次调用(
    步骤
    设置为2)生成需要更新的HTML文件
  • 使用空的虚拟文件标记已分析
    foo.mdwn
    文件:
    foo.backlinks/.done
  • 使用可以在其先决条件列表中引用模式规则的词干(并使用
    $
    退出第一次扩展)
  • 但它可能更难理解(和维护)

    注:

  • 因为这只适用于平面组织,所以我替换了
    $(shell find
    
    for m in pageA.mdwn pageB.mdwn pageC.mdwn; do go run backlinks.go $m; done
    
    INFILES     := $(shell find . -name "*.mdwn")
    OUTFILES    := $(INFILES:.mdwn=.html)
    LINKFILES   := $(INFILES:.mdwn=.whatlinkshere)
    LINKPATTERN := $(INFILES:.mdwn=.w%e)
    
    .PHONY: all clean
    .PRECIOUS: $(LINKFILES)
    
    all: $(OUTFILES)
    
    # These need to be all made before the HTML is processed
    $(LINKPATTERN): $(INFILES)
        @echo Creating backlinks
        @rm -f $(LINKFILES)
        @touch $(LINKFILES)
        @for m in $^; do go run backlinks.go $$m; done
    
    %.html: %.mdwn %.whatlinkshere
        @echo Deps $^
        @cmark $^ > $@
    
    clean:
        rm -f $(LINKFILES) $(OUTFILES)
    
    INFILES   := $(shell find . -name "*.mdwn")
    OUTFILES  := $(INFILES:.mdwn=.html)
    DONEFILES := $(patsubst %.mdwn,%.backlinks/.done,$(INFILES))
    
    .PHONY: all clean
    
    ifeq ($(STEP),)
    all $(OUTFILES): $(DONEFILES)
        $(MAKE) STEP=2 $@
    
    %.backlinks/.done: %.mdwn
        rm -rf $(dir $@)
        mkdir -p $(dir $@)
        cp $< $(dir $@)
        cd $(dir $@); go run ../backlinks.go $<; rm $<
        touch $@
    else
    all: $(OUTFILES)
    
    .SECONDEXPANSION:
    %.html: %.mdwn $$(wildcard *.backlinks/$$*.whatlinkshere)
        @echo Deps $^
        @cmark $^ > $@
    endif
    
    clean:
        rm -rf *.backlinks $(OUTFILES)
    
    INFILES     := $(wildcard *.mdwn)
    OUTFILES    := $(patsubst %.mdwn,%.html,$(INFILES))
    LINKFILES   := $(patsubst %.mdwn,%.whatlinkshere,$(INFILES))
    DONEFILES   := $(patsubst %.mdwn,.%.done,$(INFILES))
    
    .PHONY: all clean
    .PRECIOUS: $(LINKFILES)
    
    ifeq ($(STEP),)
    .NOTPARALLEL:
    
    all $(OUTFILES): $(DONEFILES)
        $(MAKE) STEP=2 $@
    
    .%.done: %.mdwn
        go run backlinks.go $<
        touch $@
    else
    all: $(OUTFILES)
    
    %.html: %.mdwn %.whatlinkshere
        @echo Deps $^
        @cmark $^ > $@
    
    %.whatlinkshere:
        touch $@
    endif
    
    clean:
        rm -f $(OUTFILES) $(LINKFILES) $(DONEFILES)