Makefile Sphinx的默认生成文件

Makefile Sphinx的默认生成文件,makefile,python-sphinx,Makefile,Python Sphinx,我试图理解由sphinx quickstart自动生成的Makefile。这是: SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXPROJ = myproj SOURCEDIR = source BUILDDIR = build .PHONY: help Makefile %: Makefile @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPH

我试图理解由
sphinx quickstart
自动生成的Makefile。这是:

SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
SPHINXPROJ    = myproj
SOURCEDIR     = source
BUILDDIR      = build

.PHONY: help Makefile

%: Makefile
    @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
让我困惑的是:

.PHONY: help Makefile
%: Makefile
我想我明白了:
  • %
    目标表示捕获任何内容(通配符)。例如,如果我键入
    makehtml
    %
    将捕获
    html
  • .PHONY Makefile
    意味着
    make
    不应在其目录中查找名为
    Makefile
    的文件,因此,不应检查文件的修改时间以确定是否运行规则
  • 我不明白: 为什么将
    Makefile
    列为目标
    %
    的先决条件。我的解释是:

    %
    捕获的目标规则应在
    生成文件
    更改时运行

    但这在上下文中没有任何意义。我所期望的是:

    当项目文档的源文件或API源文件发生更改时,
    %
    捕获的目标规则应运行

    目录结构
    .PHONY:foo
    的作用是,永远不能将
    foo
    视为最新版本。(但有关更详细的说明,请参见:主要用于非文件名的目标)

    如果您有
    bar:foo
    ,则
    bar
    目标的规则将始终在
    make bar
    上执行,因为目标依赖于
    foo
    ,但
    foo
    被视为从未更新过。这也可以通过声明
    bar
    target本身是假的来实现

    catch all
    %
    目标的问题在于Makefile所在的存储库包含存储库或与Sphinx builder同名的文件。例如,假设Makefile所在的存储库中有一个
    html
    或一个
    man
    :那么如果
    %
    没有依赖项,则
    make html
    将不起任何作用,因为
    html
    是一个没有依赖项的文件或存储库,因此永远不会得到更新

    因此,
    %
    被设置为依赖于Makefile伪目标,并且Makefile本身被声明为虚假的,因此它被认为永远不会是最新的。(*)即使repertory包含一个文件
    html
    ,那么
    makehtml
    也会被执行(编译目录中的
    html
    repertory已修改;Makefile repertory中的
    html
    将不被修改)

    (*)编辑:我忘记了确切的细节:Makefile始终被视为目标,请参阅。出于此处解释的原因,
    %
    被设置为依赖于Makefile,事实上,Makefile被声明为虚假的,以避免Makefile抱怨循环依赖性

    其想法是,Makefile不应该包含所有可能构建器的硬编码列表:否则它们可能会被单独宣布为虚假目标,但Sphinx维护人员在添加新构建器时将不得不担心使Makefile模板保持最新。当项目保持相同的Makefile但一个新的Sphinx版本添加了一个新的构建器


    sphinx quickstart现在创建的Makefile如果向sphinx添加新的生成器,则不必修改。当然,可以肯定的是,
    Makefile
    永远不会是生成器的名称…

    感谢您的明确解释,它非常有用。我想补充一点,“Makefile始终被视为目标”仅因为文件本身名为“Makefile”。如果将其重命名为例如“Makefile.test”并运行“make-f Makefile.test”,则目标确实是“Makefile.test”。如果使用catch all targets(如Sphinx的默认Makefile中的目标),请务必记住这一点。在我的示例中,我们是在CI中执行此操作的。通过将目标名称更改为“Makefile*”,解决了此问题。
    .
    ├── build
    ├── Makefile
    ├── source
    └── utils