我需要有条件地执行一些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中不起作用。

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


当前回答

我正在编写一个答案,以增加解决问题的实际语法的可见性。不幸的是,对于那些为合理问题寻找简单答案的人来说,一些在别人看来微不足道的东西可能会成为非常令人头痛的问题。

将以下内容放入“Makefile”文件中。

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

all:
    @echo MY_VAR IS $(MY_VAR)

您希望看到的行为如下(假设您最近安装了python)。

make
MY_VAR IS 1

如果将上面的文本复制并粘贴到Makefile中,会得到这个结果吗?可能不会。你可能会得到如下所示的错误:

Makefile:4: ***缺少分隔符。停止

原因:因为虽然我个人使用了一个真正的选项卡,Stack Overflow(试图提供帮助)将我的选项卡转换为一些空格。你,沮丧的网民,现在复制这个,认为你现在有了我使用的相同的文本。make命令现在读取空格并发现“all”命令的格式不正确。因此,复制上面的文本,粘贴它,然后将“@echo”前面的空白转换为一个制表符,这个例子应该,最后,希望对你有用。

其他回答

从制作手册

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)留在食谱内部。

下面是一个稍微复杂一点的例子,在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)

使用内置的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)