在 makefile 规则中提取匹配项的一部分

Ian*_*Ian 5 makefile

我有一个生成文件,它在不同的地方生成一堆版本的图像:

website/img/logo_256.png
website/img/logo_152.png
/tmp/logo_64.png
Run Code Online (Sandbox Code Playgroud)

等等( /tmp/ 生成是为了以后我可以使用这些文件来生成多分辨率.ico,其细节并不重要)。

我想要一个表格规则

logo_%.png: ${SRC}
        convert $^ -thumbnail $*x$* $@
Run Code Online (Sandbox Code Playgroud)

但是,也$*引入了匹配的目录,所以我得到了以下形式的命令:

convert logo_1024.png -thumbnail /tmp/64x/tmp/64 /tmp/logo_64.png
Run Code Online (Sandbox Code Playgroud)

这是不正确的(我需要48x48,不是/tmp/48x/tmp/48)。

或者我可以写

/tmp/logo_%.png: ${SRC}
        convert $^ -thumbnail $*x$* $@
website/img/logo_%.png: ${SRC}
        convert $^ -thumbnail $*x$* $@
Run Code Online (Sandbox Code Playgroud)

这看起来很丑。

我确信有一些方法可以分解和模式匹配$@以获得我想要的东西,但我不是 makefile 专家,所以这需要一些研究。

什么是最简单的方法来做到这一点?

Eta*_*ner 4

参见GNU Make手册中自动变量的后半部分:

\n\n
Of the variables listed above, four have values that are single file names, and three have values that are lists of file names. These seven have variants that get just the file\'s directory name or just the file name within the directory. The variant variables\' names are formed by appending \xe2\x80\x98D\xe2\x80\x99 or \xe2\x80\x98F\xe2\x80\x99, respectively. These variants are semi-obsolete in GNU make since the functions dir and notdir can be used to get a similar effect (see Functions for File Names). Note, however, that the \xe2\x80\x98D\xe2\x80\x99 variants all omit the trailing slash which always appears in the output of the dir function. Here is a table of the variants:\n\n\xe2\x80\x98$(@D)\xe2\x80\x99\n    The directory part of the file name of the target, with the trailing slash removed. If the value of \xe2\x80\x98$@\xe2\x80\x99 is dir/foo.o then \xe2\x80\x98$(@D)\xe2\x80\x99 is dir. This value is . if \xe2\x80\x98$@\xe2\x80\x99 does not contain a slash.\n\n\n\xe2\x80\x98$(@F)\xe2\x80\x99\n    The file-within-directory part of the file name of the target. If the value of \xe2\x80\x98$@\xe2\x80\x99 is dir/foo.o then \xe2\x80\x98$(@F)\xe2\x80\x99 is foo.o. \xe2\x80\x98$(@F)\xe2\x80\x99 is equivalent to \xe2\x80\x98$(notdir $@)\xe2\x80\x99.\n\n\n\xe2\x80\x98$(*D)\xe2\x80\x99\n\xe2\x80\x98$(*F)\xe2\x80\x99\n    The directory part and the file-within-directory part of the stem; dir and foo in this example.\n\n\n\xe2\x80\x98$(%D)\xe2\x80\x99\n\xe2\x80\x98$(%F)\xe2\x80\x99\n    The directory part and the file-within-directory part of the target archive member name. This makes sense only for archive member targets of the form archive(member) and is useful only when member may contain a directory name. (See Archive Members as Targets.)\n\n\n\xe2\x80\x98$(<D)\xe2\x80\x99\n\xe2\x80\x98$(<F)\xe2\x80\x99\n    The directory part and the file-within-directory part of the first prerequisite.\n\n\n\xe2\x80\x98$(^D)\xe2\x80\x99\n\xe2\x80\x98$(^F)\xe2\x80\x99\n    Lists of the directory parts and the file-within-directory parts of all prerequisites.\n\n\n\xe2\x80\x98$(+D)\xe2\x80\x99\n\xe2\x80\x98$(+F)\xe2\x80\x99\n    Lists of the directory parts and the file-within-directory parts of all prerequisites, including multiple instances of duplicated prerequisites.\n\n\n\xe2\x80\x98$(?D)\xe2\x80\x99\n\xe2\x80\x98$(?F)\xe2\x80\x99\n    Lists of the directory parts and the file-within-directory parts of all prerequisites that are newer than the target.\n
Run Code Online (Sandbox Code Playgroud)\n\n

编辑:

\n\n

根据@Ian\'s 评论的提示,我再次查看并意识到这不是一个完整的解决方案。完整的解决方案如下。

\n\n

上述F修饰符(和$(notdir)函数)将从目标文件名中删除路径。这是必要的一部分。

\n\n

需要额外的操作才能从目标中仅提取数字分量,例如/some/path/logo_64.png.

\n\n

$(basename)函数将去除后缀(按照意愿$(patsubst %.png,%,$@)$(@:%.png=)以更具体的方式)。

\n\n

结合我们从/some/path/logo_64.png到得到的结果logo_64。此时的处理在很大程度上取决于数据的外观以及可以对其做出哪些断言。如果logo_是静态前缀,则简单的$(patsubst logo_%,%,...)将起作用(就像以前一样,匹配的替换引用也将起作用)。

\n\n

如果不能保证这一点,但可以保证尺寸将是最后一个下划线分隔的组件,则$(lastword $(subst _, ,...))可以使用。

\n