我需要有条件地执行一些make规则,只有当安装的Python大于某个版本(比如2.5)。

我想我可以做一些类似执行的事情:

python -c 'import sys; print int(sys.version_info >= (2,5))'

然后在ifeq make语句中使用输出(ok时为'1',否则为'0')。

在一个简单的bash shell脚本中,它只是:

MY_VAR=`python -c 'import sys; print int(sys.version_info >= (2,5))'`

但这在Makefile中不起作用。

有什么建议吗?我可以使用任何其他明智的解决办法来实现这一点。


当前回答

小心这样的食谱

target:
    MY_ID=$(GENERATE_ID);
    echo $MY_ID;

它做错了两件事。配方中的第一行在与第二行不同的shell实例中执行。在此期间,变量将丢失。第二个错误是没有转义$。

target:
    MY_ID=$(GENERATE_ID); \
    echo $$MY_ID;

这两个问题都已修复,变量可用。反斜杠将这两行合并在一个shell中运行,因此变量的设置和变量后记的读取是有效的。

我意识到原来的帖子说了如何将shell命令的结果转化为MAKE变量,而这个答案展示了如何将其转化为shell变量。但其他读者可能会受益。

最后一个改进是,如果使用者希望设置一个“环境变量”,那么您必须导出它。

my_shell_script
    echo $MY_ID

在makefile中需要这个吗

target:
    export MY_ID=$(GENERATE_ID); \
    ./my_shell_script;

希望这能帮助到别人。一般来说,应该避免做任何食谱之外的实际工作,因为如果有人使用带有“——dry-run”选项的makefile,只看看它会做什么,它不会有任何不良的副作用。每个$(shell)调用都在编译时计算,一些实际工作可能会意外地完成。如果可能的话,最好将实际工作(如生成id)留在食谱内部。

其他回答

从制作手册

shell赋值操作符` != '可用于执行shell脚本并将>变量设置为其输出。这个运算符首先计算右边的值,然后将结果>传递给shell执行。如果执行结果以>换行符结束,则删除该换行符;所有其他换行符都替换为空格。然后将>结果字符串放入命名的递归展开变量中。>的例子: = printf '\043' File_list != find。- name ' * . c '

小心这样的食谱

target:
    MY_ID=$(GENERATE_ID);
    echo $MY_ID;

它做错了两件事。配方中的第一行在与第二行不同的shell实例中执行。在此期间,变量将丢失。第二个错误是没有转义$。

target:
    MY_ID=$(GENERATE_ID); \
    echo $$MY_ID;

这两个问题都已修复,变量可用。反斜杠将这两行合并在一个shell中运行,因此变量的设置和变量后记的读取是有效的。

我意识到原来的帖子说了如何将shell命令的结果转化为MAKE变量,而这个答案展示了如何将其转化为shell变量。但其他读者可能会受益。

最后一个改进是,如果使用者希望设置一个“环境变量”,那么您必须导出它。

my_shell_script
    echo $MY_ID

在makefile中需要这个吗

target:
    export MY_ID=$(GENERATE_ID); \
    ./my_shell_script;

希望这能帮助到别人。一般来说,应该避免做任何食谱之外的实际工作,因为如果有人使用带有“——dry-run”选项的makefile,只看看它会做什么,它不会有任何不良的副作用。每个$(shell)调用都在编译时计算,一些实际工作可能会意外地完成。如果可能的话,最好将实际工作(如生成id)留在食谱内部。

使用内置的Make shell,比如MY_VAR=$(shell echo whatever)

me@Zack:~$make
MY_VAR IS whatever

me@Zack:~$ cat Makefile MY_VAR:= $(shell echo whatever) 全部: MY_VAR是$(MY_VAR)

在eval中包装任务对我来说是有效的。

# dependency on .PHONY prevents Make from 
# thinking there's `nothing to be done`
set_opts: .PHONY
  $(eval DOCKER_OPTS = -v $(shell mktemp -d -p /scratch):/output)

下面是一个稍微复杂一点的例子,在recipe中使用管道和变量赋值:

getpodname:
    # Getting pod name
    @eval $$(minikube docker-env) ;\
    $(eval PODNAME=$(shell sh -c "kubectl get pods | grep profile-posts-api | grep Running" | awk '{print $$1}'))
    echo $(PODNAME)