makefile中的Shell变量替换

brgchamk  于 2023-01-13  发布在  Shell
关注(0)|答案(1)|浏览(191)

我希望在Makefile中有命令,允许我在docker-composite.yaml中分别更改服务的目标到给定的命令参数。我有这样的东西:

example:
    @[[ "$${target:-dev}" == @(dev|test|release) ]] || exit 1
    yq -y -i '.services."$(service)".build.target = "$(target)"' docker-compose.yaml

这几乎完成了工作,但我有这个参数是可选的。它应该回退到“dev”时,没有提供。在第二行有验证,检查是否给定的目标有允许的值。如果目标没有在命令中指定,它应该回退到“dev”,它的工作。但当我尝试类似的语法,它不工作在第三行。我尝试了不同的组合,如

yq -y -i '.services."$(service)".build.target = "$(target:-dev)"' docker-compose.yaml
yq -y -i '.services."$(service)".build.target = "${target:-dev}"' docker-compose.yaml
yq -y -i '.services."$(service)".build.target = "${{target:-dev}}"' docker-compose.yaml
yq -y -i '.services."$(service)".build.target = "$(${target:-dev})"' docker-compose.yaml
// etc

但在大多数情况下,我得到的是空字符串而不是“dev”,这是怎么回事?

xeufq47z

xeufq47z1#

$(target)是一个make变量,而不是一个 shell 变量。Make变量不能使用像${foo:-bar}这样的shell构造来操作。
如果你想做类似的事情,你必须使用make构造。如果你想限制自己使用GNU make,你可以用途:

$(or $(target),dev)

如果你想完全可移植,你可以把make变量转换成shell变量,然后使用shell构造,如下所示:

target='$(target)'; yq -u -i ".services.\"...\".build.target = \"$${target:-dev}\"" ...

顺便说一句,我应该指出:make总是在运行recipe时调用/bin/sh,除非你通过设置SHELL来特别请求它使用不同的shell。

@[[ "$${target:-dev}" == @(dev|test|release) ]] || exit 1

使用了一系列bash特有的特性,这些特性绝对不能移植到POSIX shell。(例如,你在Red Hat类型的系统上),这是可行的,但是如果你试图在/bin/sh是一个严格的POSIX shell的系统上运行它,比如dash(例如,如果您使用的是包含Ubuntu的Debian类型的系统),它将失败。
如果makefile需要在bash而不是POSIX sh中运行的方法,则需要添加:

SHELL := /bin/bash

或类似于它。

相关问题