有没有一种定义自定义隐式GNU Make规则的方法?

3

我经常将dot(graphviz格式)文件制作成png文件。执行此操作的命令如下:

$ dot my_graph.dot -o my_graph.png -Tpng

然而,我希望能够使用类似 $ make my_graph.dot 的简短命令格式来自动生成我的PNG文件。

目前,我正在使用Makefile定义了以下规则,但是此次操作仅适用于包含该Makefile的目录。

%.eps: %.dot
    dot $<  -o $@ -Teps

是否可以定义自定义的隐式GNU Make配方? 这将允许上述配方在系统范围内可用。

如果不能,您会使用什么解决方案解决这些问题?

设置:

  • Fedora Linux与ZSH / Bash

2
我相信如果没有其他makefile存在,就没有任何可以配置为默认makefile的东西。您可以使用一个小脚本别名您的make命令,该脚本将检查当前目录中是否有makefile,如果不存在,则使用make -f somedir/Makefile指向默认的makefile。 - Klaus
命令 make my_graph.dot 会尝试从其他文件制作名为 my_graph.dot 的文件。使用 Makefile,您必须使用 make my_graph.eps - Bodo
3个回答

2
你可以在你的Shell启动文件中定义Shell函数,例如:
dotpng()
{
    echo dot ${1%.dot}.dot -o ${1%.dot}.png -Tpng;
}

这个函数可以像这样调用

dotpng my_graph.dot

或者

dotpng my_graph

如果文件名以.dot结尾,则代码${1%.dot}.dot会从文件名中删除.dot,并在函数参数中重新附加它,以允许使用my_graph.dotmy_graph


2

是否可以定义自定义的隐式GNU Make配方?

没有修改GNU Make源代码是不可能的。

如果不行,您会使用什么解决方案来解决这类问题?

我不喜欢全局修改系统,但您可以这样做:

  • Create a file /usr/local/lib/make/myimplicitrules.make with the content

      %.eps: %.dot
          dot $<  -o $@ -Teps
    
  • Use include /usr/local/lib/make/myimplicitrules.make in your Makefile.

我更倾向于使用Git子模块或类似的方法来共享项目之间的通用配置,而不是依赖全局配置。依赖全局环境会使您的程序难以测试和不可移植。

我更愿意使用shell函数,比如:

mymake() {
   make -f <(cat <<'EOF'
%.eps: %.dot
    dot $<  -o $@ -Teps
EOF
   ) "$@"
}
mymake my_graph.dot

感谢您的建议,如果我需要共享常见的Make规则或配置文件,我将在未来的项目中使用git子模块的想法! - Hugo REYMOND

1

GNU Make允许您使用MAKEFILES环境变量指定额外的Makefile文件。引用来自info'(make)MAKEFILES Variable':

默认目标从这些Makefile文件中(或由它们包含的任何Makefile文件)不会被选取,并且如果在'MAKEFILES'中列出的文件未找到,则不会出现错误。
如果您正在无指定Makefile文件的情况下运行'make',则在'MAKEFILES'中的一个Makefile文件可以做一些有用的事情,以帮助内置的隐式规则更好地工作。

例如,在当前目录中没有Makefile文件,并且以下`.mk`文件位于`make`的包含路径中(例如通过`MAKEFLAGS=--include-dir="$HOME"/.local/lib/make/`),您可以创建子目录gen/并通过运行来转换my_graph.dotdot/my_graph.dot:

MAKEFILES=dot.mk make gen/my_graph.png

为了进一步节省输入,我们很容易在会话环境中添加 MAKEFILES=dot.mk,但在启动文件中定义 MAKEFILES 可能会使事情变得完全不透明。因此,我更喜欢在命令行上看到 MAKEFILES=…
文件:dot.mk
include common.mk

genDir ?= gen/
dotDir ?= dot/
dotFlags ?= $(if $(DEBUG),-v)
Tvariant ?= :cairo:cairo

vpath %.dot $(dotDir)

$(genDir)%.png $(genDir)%.svg $(genDir)%.eps : %.dot | $(genDir).
    dot $(dotFlags) $< -o $@ -T'$(patsubst .%,%,$(suffix $@))$(Tvariant)'

包含的common.mk是您存储通用定义以管理目录创建、诊断等的位置,例如:
.PRECIOUS: %/. ## preempt 'unlink: ...: Is a directory'
%/. : ; $(if $(wildcard $@),,mkdir -p -- $(@D))

参考资料:

  • ?= = := … - info '(make)Reading Makefiles' (读取Makefile文件)
  • vpath - info '(make)Selective Search'(选择性搜索)
  • 仅限顺序先决条件(例如,| $(genDir).)- info '(make)Prerequisite Types'(先决条件类型)
  • .PRECIOUS - info '(make)Chained Rules'(链接规则)

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