【问题标题】:How do I validate a GNU Makefile parameter exists in a string如何验证字符串中是否存在 GNU Makefile 参数
【发布时间】:2020-05-18 17:20:47
【问题描述】:

我正在努力让这条规则发挥作用。它完全炸毁了我的整个 Makefile。

应该验证用户传递的version 的值是否存在于PYVERSION 变量中。

实际行为是复杂的,因为我尝试了很多不同的东西。我不是 GNU 专家,所以我尝试了 ${version}$(version)$version 以及 PYVERSION 的相同操作。我在此处发布的当前版本总是进入 else 块,与 version 输入无关。

PYVERSIONS := "3.5 3.6 3.7 3.8"

.PHONY: venv
venv:
    if test $(findstring ${version}, $(PYVERSIONS)); then
        /Library/Frameworks/Python.framework/Versions/${version}/bin/python3 -m venv venv
    else
        $(error Bad python version given (${version}) project only supports ${PYVERSIONS})
    fi;
  • make venv version=3.5 一样调用它应该会成功执行if 块并创建venv

  • make venv version=2.7 这样调用它应该会在 else 块中引发错误消息。

我试图关注这个post

更新

在@Beta 的帮助下,这是我要工作的最终解决方案。

PYVERSIONS := "3.6 3.7 3.8"
PYPATH := /Library/Frameworks/Python.framework/Versions

.PHONY: venv
venv:
    @if test $(findstring ${version}, $(PYVERSIONS)) ; \
    then \
      echo "Creating virtual environment for python ${version}"; \
      $(PYPATH)/${version}/bin/python3 -m venv venv; \
    else \
      echo "Unsupported python version (${version}). Project supports $(PYVERSIONS)"; \
    fi

【问题讨论】:

  • 您的问题应该严格保持为一个问题。如果您想发布自己的答案,欢迎您这样做。

标签: bash makefile gnu-make


【解决方案1】:

这里实际上不同意@Beta。因为在你开始执行配方之前答案就已经知道了,$(error …) 是明确的方法。

现在,make 将整个配方存储为单个递归扩展变量。当 make 决定构建 venv 时(例如,您输入 make venv),它将扩展整个配方,然后将每个结果行一一传递给新的shell 的实例。

问题是,当 make 扩展你的食谱时, 它总是扩展$(error Bad python version given …),并且make甚至在调用shell之前就停止了。

我们如何解决这个问题?

PYVERSIONS := 3.6 3.7 3.8
PYPATH := /Library/Frameworks/Python.framework/Versions

pyversion = $(or $(filter ${version},${PYVERSION}),$(error $$version [${version}] must be exactly one of ${PYVERSIONS}))

.PHONY: venv
venv:
    echo "Creating virtual environment for python ${version}"
    $(PYPATH)/${pyversion}/bin/python3 -m venv venv

所以,

  • 你输入make venv
  • Make 扩展了配方
  • Make 扩展 pyversion
    • Make 扩展 $(filter ${version},3.6 3.7 3.8)
      • 如果您没有在命令行或环境中将 version 设置为三个祝福字符串之一, make 停在那里,然后用有用的信息 NICE
      • OTOH 如果设置得当,make 很高兴并开始执行配方

其他不错的特性:

  • 没有 shell 语法
  • python3 的退出代码返回给 make(恕我直言,您的原始配方中有一个大漏洞)。

make 中的东西总是比 shell 更好看。

【讨论】:

  • 我真的很喜欢这个。问你一个问题,如果调用venv 配方,是否只扩展pyversion?我的无制作大脑将此视为逐行执行,因此我希望在运行 make other-thing 并且没有设置版本时会引发错误。我确实对其进行了测试,它运行良好,它以某种方式知道在运行其他接收方/规则时忽略 pyversion。
  • 是的,这是正确的。配方仅在 make 想要执行它之前扩展。所有食谱都是如此。在上面勾勒的 makefile 中,每次扩展 ${pyversion} 时都会进行检查,如果不使用 ${pyversion} 则永远不会进行检查。只是强调一下,检查是在不打扰 shell 的情况下完成的。
【解决方案2】:

您正在混合使用 shell 语法和 Make 语法。

如果你想用 shell 条件来处理这个问题,你必须把整个事情放在配方中的一行(因为每一行都在它自己的子 shell 中执行):

venv:
    if test $(findstring ${version}, $(PYVERSIONS)) ; then echo $(version)/bin/python3 venv; else  echo bad version $(version); fi

或者你可以用反斜杠换行:

venv:
    if test $(findstring ${version}, $(PYVERSIONS)) ; \
  then \
   echo $(version)/bin/python3 venv; \
  else \
   echo bad version $(version); \
  fi

(注意只有一个TAB,在if前面。)

如果你想在规则中使用 Make 条件:

venv:
ifeq ($(findstring ${version}, $(PYVERSIONS)),)
    echo bad version $(version);
else
    echo echo $(version)/bin/python3 venv;
endif

如果你想使用 Maker error 命令,你就有问题了。 Make 将在执行任何规则之前评估条件,因此如果您使用 error,那么如果没有给出有效的版本号,Make 将抛出错误即使 venv 不是目标。它可以使用error,但是很痛苦,所以要先判断效果是否物有所值。

【讨论】:

  • 你摇滚@Beta。我暂时无法让您的解决方案起作用,因为我没有阅读最后一部分:/ 并且仍然尝试使用 Make error。用完整的解决方案更新我的问题。
猜你喜欢
  • 1970-01-01
  • 2017-11-27
  • 2021-07-09
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 2014-06-13
  • 1970-01-01
  • 2019-03-18
相关资源
最近更新 更多