如何记录一个Makefile?

24

有没有一种方法可以在Makefile中编写“标准”注释,以便稍后将它们提供给类似Doxygen的程序,以输出漂亮的(例如HTML或man)文档?我想要在某个地方清晰地概述我的主要目标,但不需要太花哨。

8个回答

59
以下是一个更简单的解决方案,不需要定义用户函数或将帮助文本聚合到规则所记录的位置。
# This is a regular comment, that will not be displayed

## ----------------------------------------------------------------------
## This is a help comment. The purpose of this Makefile is to demonstrate
## a simple help mechanism that uses comments defined alongside the rules
## they describe without the need of additional help files or echoing of
## descriptions. Help comments are displayed in the order defined within
## the Makefile.
## ----------------------------------------------------------------------

help:     ## Show this help.
    @sed -ne '/@sed/!s/## //p' $(MAKEFILE_LIST)

build:    ## Build something.

install:  ## Install something.

deploy:   ## Deploy something.

format:   ## Help comments are display with their leading whitespace. For
          ## example, all comments in this snippet are aligned with spaces.

运行 makemake help 会产生以下结果:

----------------------------------------------------------------------
This is a help comment. The purpose of this Makefile is to demonstrate
a simple help mechanism that uses comments defined alongside the rules
they describe without the need of additional help files or echoing of
descriptions. Help comments are displayed in the order defined within
the Makefile.
----------------------------------------------------------------------
help:     Show this help.
build:    Build something.
install:  Install something.
deploy:   Deploy something.
format:   Help comments are display with their leading whitespace. For
          example, all comments in this snippet are aligned with spaces.

6
太棒了。但是在复制时要小心,那些缩进的行必须使用制表符(Tab)。请参阅 https://dev59.com/SmQn5IYBdhLWcg3wTlsS - Peter Lada
为了使帮助文本对齐,请在@sed命令中添加| column -tl 2 - balki
@balki,你能否请展示一下带有 | column -tl 的完整命令? - Demetry Pascal
1
@DemetryPascal @sed -ne '/@sed/!s/## //p' $(MAKEFILE_LIST) | column -tl 2 参见:https://gitea.balki.me/balki/makepac/src/branch/main/Makefile#L10 - balki

10
在像这样的 makefile 文件中:
install: ## Do a
  @echo "foo"

start: ## Do b
  @echo "bar"

test: ## Do c
  @echo "baz"


help:
  @egrep -h '\s##\s' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m  %-30s\033[0m %s\n", $$1, $$2}'

输出结果为:

在此输入图片描述


惊人的 @Rose 这在 macOS 上运行得像魔法一样。 - Yassine ElBadaoui
这看起来非常不错,谢谢!我尝试用“tput setaf 3”替换硬编码的颜色,但没有成功。 - Eric Duminil
1
当Makefile包含其他 makefile 时,这个命令有一个缺陷,因为grep结果变成了 Makefile:target:## docs。可以通过更改awk分隔符为 FS =“:[^:]*?##” 来解决这个问题。 - Amnon

9

一个不错的点子是提供一个假的help目标,用于打印目标和选项的摘要。来自Linux内核的Makefile:

help:
        @echo  'Cleaning targets:'
        @echo  '  clean           - Remove most generated files but keep the config and'
        @echo  '                    enough build support to build external modules'
        @echo  '  mrproper        - Remove all generated files + config + various backup files'
        @echo  '  distclean       - mrproper + remove editor backup and patch files'
        @echo  ''
        @echo  'Configuration targets:'
        @$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
        @echo  ''

这种方式可能需要一些工作来维护文档,但是我发现这种方式很好地区分了面向“用户”的内容和面向Makefile本身的人员(行内注释)的内容。


也许我不够耐心,但我怀疑除了你提到的之外,没有其他东西了。非常感谢!! - J.N.
如果你想要一些自动化的东西,可以看看 make-help - gibatronic

8
我使用一个简短的Perl脚本编写了自己的解决方案,将帮助文档格式化为其他GNU工具的格式:
SCRIPT_VERSION=v1.0
SCRIPT_AUTHOR=John Doe

all:                ##@Build Build all the project 

clean:              ##@Cleaning Remove all intermediate objects

mrproper: clean     ##@Cleaning Remove all output and interemediate objects

HELP_FUN = \
    %help; while(<>){push@{$$help{$$2//'options'}},[$$1,$$3] \
    if/^([\w-_]+)\s*:.*\#\#(?:@(\w+))?\s(.*)$$/}; \
    print"$$_:\n", map"  $$_->[0]".(" "x(20-length($$_->[0])))."$$_->[1]\n",\
    @{$$help{$$_}},"\n" for keys %help; \

help: ##@Miscellaneous Show this help
    @echo -e "Usage: make [target] ...\n"
    @perl -e '$(HELP_FUN)' $(MAKEFILE_LIST)
    @echo -e "Written by $(SCRIPT_AUTHOR), version $(SCRIPT_VERSION)"
    @echo -e "Please report any bug or error to the author." 

这样就得到了这个结果:

$ make help
Usage: make [target] ...

Miscellaneous:
  help                Show this help

Build:
  all                 Build all the project

Cleaning:
  clean               Remove all intermediate objects
  mrproper            Remove all output and interemediate objects

Written by John Doe, version v1.0
Please report any bug or error to the author.

1
对 HELP_FUN 位的一点改进:将 if/^(\w+)\s*: 替换为 if/^([\w-_]+)\s*:,以允许类型为 "this-target" 或 "that_target" 的目标。 - th3n3rd
这太棒了!如何扩展以允许多行描述? - James Burton
@nowox,你能否将函数更改为返回排序后的结果? - Demetry Pascal

1

自文档的Makefile(约翰·格雷厄姆-卡明,2005年)允许您在每个规则旁边编写帮助文档。这是一种轻量级且非常巧妙的解决方案,至少适用于GNU Make。

这是一个略微修改过的版本(def-help-section有助于组织长列表的规则)。


1

这是我的版本,它还剥离了目标的依赖关系,并将帮助字符串对齐到一个均匀的列。

help:   ## Show this help.
    @sed -ne 's/^\([^[:space:]]*\):.*##/\1:\t/p' $(MAKEFILE_LIST) | column -t -s $$'\t'

image: src/*.s src/*.c src/**/*.c   ## Build the image
    riscv32-unknown-elf-gcc $^ -march=rv32i_zicsr -Wall -ggdb -O0 -o image -ffreestanding -nostdlib -lgcc

launch: ## Image Launch the image in renode
    renode --net vexriscv.resc --console

输出

help:    Show this help.
image    Build the image
launch:  Image Launch the image in renode

0

我为此目的编写了MakeHelp库。它允许您在每个规则上面编写规则文档。非常容易使用。

我发现它与其他自描述Makefiles不同,因为它没有重复性,并且允许多行文档和私有规则。


0
再举一个例子: 在命令行之前允许编写帮助信息。
您可以在帮助信息中使用“:”将其打印在单独的列中。
## Another help message with data: in a separate column
test::
    echo ""

## Print this help
help::
    @awk '/^## /{c=substr($$0,3);next}c&&/^[[:alpha:]][[:alnum:]_/-]+:/{print substr($$1,1,index($$1,":")),c}1{c=0}' $(MAKEFILE_LIST) | column -s: -t -W 2,3 -o " "

输出:

test       Another help message with data                           in a separate column
help       Print this help                                         

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接