Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Makefile 带make的静态模式和条件句_Makefile_Gnu Make - Fatal编程技术网

Makefile 带make的静态模式和条件句

Makefile 带make的静态模式和条件句,makefile,gnu-make,Makefile,Gnu Make,我对GNU Make 4.2.1有问题。似乎有一些互动 和之间的语法,我不太明白 上下文:我有一个由一组标记文件记录的项目,并且 我想将这些文件呈现为HTML,以便检查它们 在当地。目录结构最终应如下所示: some_project/ ├── README.md # entry page of documentation ├── doc/ # extra docs │ ├── foo.md │ ├── bar.md │ └── ...

我对GNU Make 4.2.1有问题。似乎有一些互动 和之间的语法,我不太明白

上下文:我有一个由一组标记文件记录的项目,并且 我想将这些文件呈现为HTML,以便检查它们 在当地。目录结构最终应如下所示:

some_project/
├── README.md       # entry page of documentation
├── doc/            # extra docs
│   ├── foo.md
│   ├── bar.md
│   └── ...         # and some more
└── doc_html/       # HTML rendering of the docs
    ├── Makefile    # the Makefile I am trying to write
    ├── index.html  # rendered from README.md
    ├── foo.html    # ............. doc/foo.md
    ├── bar.html    # ............. doc/bar.md
    └── ...         # etc.
source = $(info 1=$(1)) $(if $(findstring index.html,$(1)), \
    ../README.md, \
    $(patsubst %.html,../doc/%.md,$(1)) \
)
$(TARGETS): %.html: ../doc/%.md
        @echo some list of commands $< $@
如果没有index.html的特殊情况,我可以编写如下内容:

%.html: ../doc/%.md
    some list of commands $< $@
但是,它在静态规则中的行为不正常

$ make
make: *** No rule to make target '../doc/index.md', needed by 'index.html'.  Stop.
请注意,如果我从$TARGETS中删除index.html,则该规则确实有效

知道我做错了什么吗?

这一行:

$(TARGETS): %.html: $(call source,%.html)
无法工作,因为您正在使用文本字符串%.html的参数展开源宏。不能在先决条件列表中的宏中使用模式或自动变量:首先展开宏,然后再解析或展开模式

然而,在我看来,你让这条路变得比需要的更复杂了。如果您的大多数目标是以一种方式构建的,但也有一些是以不同的方式构建的,那么只需为大多数目标创建一个模式规则,并为某些目标编写明确的规则:

%.html: ../doc/%.md
        some list of commands $< $@

index.html : ../README.md
        commands to build index.html
您将看到它只打印一次,因为该规则仅扩展一次1=%.html

接下来会发生什么?这意味着您的宏将扩展为:

$(if $(findstring index.html,%.html), ../README.md, $(patsubst %.html,../doc/%.md,%.html))
再次使用文本字符串%.html。findstring始终返回空,因为在字符串%.html中找不到index.html,因此展开else子句:

$(patsubst %.html,../doc/%.md,%.html)
显然%.html与带有%词干的%.html匹配,因此进行替换并返回../doc/%.md。因此,在所有这些之后,您的规则如下所示:

some_project/
├── README.md       # entry page of documentation
├── doc/            # extra docs
│   ├── foo.md
│   ├── bar.md
│   └── ...         # and some more
└── doc_html/       # HTML rendering of the docs
    ├── Makefile    # the Makefile I am trying to write
    ├── index.html  # rendered from README.md
    ├── foo.html    # ............. doc/foo.md
    ├── bar.html    # ............. doc/bar.md
    └── ...         # etc.
source = $(info 1=$(1)) $(if $(findstring index.html,$(1)), \
    ../README.md, \
    $(patsubst %.html,../doc/%.md,$(1)) \
)
$(TARGETS): %.html: ../doc/%.md
        @echo some list of commands $< $@
这与您以前使用简单模式规则时所做的完全相同。

这一行:

$(TARGETS): %.html: $(call source,%.html)
无法工作,因为您正在使用文本字符串%.html的参数展开源宏。不能在先决条件列表中的宏中使用模式或自动变量:首先展开宏,然后再解析或展开模式

然而,在我看来,你让这条路变得比需要的更复杂了。如果您的大多数目标是以一种方式构建的,但也有一些是以不同的方式构建的,那么只需为大多数目标创建一个模式规则,并为某些目标编写明确的规则:

%.html: ../doc/%.md
        some list of commands $< $@

index.html : ../README.md
        commands to build index.html
您将看到它只打印一次,因为该规则仅扩展一次1=%.html

接下来会发生什么?这意味着您的宏将扩展为:

$(if $(findstring index.html,%.html), ../README.md, $(patsubst %.html,../doc/%.md,%.html))
再次使用文本字符串%.html。findstring始终返回空,因为在字符串%.html中找不到index.html,因此展开else子句:

$(patsubst %.html,../doc/%.md,%.html)
显然%.html与带有%词干的%.html匹配,因此进行替换并返回../doc/%.md。因此,在所有这些之后,您的规则如下所示:

some_project/
├── README.md       # entry page of documentation
├── doc/            # extra docs
│   ├── foo.md
│   ├── bar.md
│   └── ...         # and some more
└── doc_html/       # HTML rendering of the docs
    ├── Makefile    # the Makefile I am trying to write
    ├── index.html  # rendered from README.md
    ├── foo.html    # ............. doc/foo.md
    ├── bar.html    # ............. doc/bar.md
    └── ...         # etc.
source = $(info 1=$(1)) $(if $(findstring index.html,$(1)), \
    ../README.md, \
    $(patsubst %.html,../doc/%.md,$(1)) \
)
$(TARGETS): %.html: ../doc/%.md
        @echo some list of commands $< $@

这与您以前使用简单模式规则时所做的完全相同。

这似乎是一个解决方案:

DOC_PAGES := $(wildcard ../doc/*.md)
TARGETS := index.html $(patsubst %.md,%.html,$(notdir $(DOC_PAGES)))

all: $(TARGETS)

.INTERMEDIATE: ../doc/index.md
../doc/index.md: ../README.md
    cp $< $@

%.html: ../doc/%.md
    @echo some list of commands $< $@

test:
    @echo $(TARGETS)
index.html通过模式规则查找../doc/index.md,导致配方复制../README.md


当make完成时,将删除.INTERMEDIATE特殊目标的先决条件。可选。

这似乎是一个解决方案:

DOC_PAGES := $(wildcard ../doc/*.md)
TARGETS := index.html $(patsubst %.md,%.html,$(notdir $(DOC_PAGES)))

all: $(TARGETS)

.INTERMEDIATE: ../doc/index.md
../doc/index.md: ../README.md
    cp $< $@

%.html: ../doc/%.md
    @echo some list of commands $< $@

test:
    @echo $(TARGETS)
index.html通过模式规则查找../doc/index.md,导致配方复制../README.md


当make完成时,将删除.INTERMEDIATE特殊目标的先决条件。可选。

谢谢,但我不太理解“解析前展开”的问题“:如果目标不包含index.html,则该规则会按预期工作。至于create_html变量,如果没有其他选择,我可能会退回到此解决方案,但如果有许多命令,我会发现它很笨拙。我将在回答中解释谢谢,但我不太理解“解析前展开”的问题“:如果目标不包含index.html,则规则会按预期工作。至于create_html变量,如果没有其他选择,我可能会回退到此解决方案,但如果有许多命令,我会发现它很笨拙。我将在回答中解释,特别感谢人们指出我以前回答中的错误。Encore!我担心这个intermediate copy会搞乱make是否需要重新呈现文件,但事实证明它处理得相当巧妙。采用了解决方案,将cp替换为ln-s。特别感谢人们指出了我之前回答中的错误。Encore!我担心这个中间副本会搞乱make Figulating whet她说,文件必须重新渲染,但事实证明它处理得相当巧妙。采用了解决方案,将cp替换为ln-s。