为什么 Bash-in-Makefile 表达式不起作用?

Why Bash-in-Makefile expression doesn't work?

直接粘贴到我的 shell,下面尝试了 3 个正则表达式中的每一个并起作用(参见 *.{jpg,png,gis.tif}):

for file in ./output/India/*.{jpg,png,gis.tif}; do echo $file; openssl base64 -in $file -out ./output/India/`basename $file`.b64; done;

作为 makefile 进程,它失败并且 returns :

task: 
  for file in ./output/India/*.{png,jpg,gis.tif} ; \
    do echo $$file ; openssl base64 -in $$file -out ./output/India/`basename $$file`.b64; \
  done

和returns:

47910543179104:error:02001002:system library:fopen:No such file or directory:bss_file.c:398:fopen('./output/India/*.{png,jpg,gis.tif}','r')

当 Bash 在 makefile 中时,为什么这个表达式不起作用?

make 默认使用 /bin/sh,它不支持大括号扩展。

通过在 makefile 中设置 SHELL 变量告诉 make 使用不同的 shell,不要在 make 规则中使用大括号扩展,或者 运行 一个脚本内联配方(哪个脚本可以是 bash/等 运行)。

系统提示我给出 make 如何为您完成繁重工作的草图。

因此,您想将 output/India/ 中的所有源文件(.jpg.png.gis.tif)转换为它们的 base64 编码等效项。素描:

.PHONY: all
all: # default target

dir := output/India/
exts := jpg png gis.tif
wildcards := $(addprefix ${dir}*.,${exts})
sources := $(wildcard ${wildcards})
targets := $(addsuffix .b64,${sources})

${targets}: %.b64: %
     openssl base64 -in $< -out $@

all: ${targets}
all: ; : $@ Success

这比需要的更冗长,通常我反对使用 $(wildcard …)。好吧。

那么我们这里的 shell 版本有什么优势呢?

  1. make -j5 将同时进行 5 次转换。如果你有四个 CPU 就好了
  2. 转换在出现第一个错误时停止(比如磁盘已满)
  3. 不会重新转换自上次转换后未更改的文件
  4. 没有狡猾的shell语法(尽管shmake的重要组成部分)

顺便说一句,未经测试。抱歉。