Shell 如何将命令的输出分配给Makefile变量

Shell 如何将命令的输出分配给Makefile变量,shell,makefile,Shell,Makefile,我需要有条件地执行一些make规则,只有在安装的Python大于某个版本(比如2.5)的情况下 我想我可以做一些事情,比如执行: python -c 'import sys; print int(sys.version_info >= (2,5))' 然后在ifeqmake语句中使用输出('1'如果正常,'0'否则) 在一个简单的bash shell脚本中,它只是: MY_VAR=`python -c 'import sys; print int(sys.version_info >

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

我想我可以做一些事情,比如执行:

python -c 'import sys; print int(sys.version_info >= (2,5))'
然后在
ifeq
make语句中使用输出('1'如果正常,'0'否则)

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

MY_VAR=`python -c 'import sys; print int(sys.version_info >= (2,5))'`
但这在Makefile中不起作用

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

all:
    @echo MY_VAR IS $(MY_VAR)

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

使用Make
shell
内置的类似于
MY\u VAR=$(shell echo which)


将作业包装在
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)

我正在写一个答案来增加解决问题的实际语法的可见性。不幸的是,有些人可能认为琐碎的事情可能会成为一个非常令人头痛的问题,因为有些人正在寻找一个合理问题的简单答案

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

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

如果你把上面的文字复制粘贴到Makefile中,你会得到这个吗?可能不会。您可能会遇到如下错误:


原因:虽然我个人使用的是正版标签,但堆栈溢出(试图提供帮助)会将我的标签转换为许多空格。你,沮丧的互联网公民,现在复制这个,认为你现在有我使用的相同文本。make命令现在读取空格,并发现“all”命令的格式不正确。因此,复制上面的文本,粘贴它,然后将“@echo”之前的空格转换为一个选项卡,希望这个示例最终对您有用。

下面是一个更复杂的示例,其中包含管道和变量赋值:

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)

使用GNU Make,您可以使用
shell
eval
存储、运行和分配任意命令行调用的输出。下面的示例与那些使用
:=
的示例之间的区别在于
:=
赋值只发生一次(当遇到时)并且永远发生。使用
=
设置的递归扩展变量有点“懒惰”;对其他变量的引用一直保留到引用变量本身为止,并且每次引用变量时都会进行后续的递归扩展,这对于生成“一致的、可调用的代码段”来说是可取的。有关更多信息,请参阅

# Generate a random number.
# This is not run initially.
GENERATE_ID = $(shell od -vAn -N2 -tu2 < /dev/urandom)

# Generate a random number, and assign it to MY_ID
# This is not run initially.
SET_ID = $(eval MY_ID=$(GENERATE_ID))

# You can use .PHONY to tell make that we aren't building a target output file
.PHONY: mytarget
mytarget:
# This is empty when we begin
    @echo $(MY_ID)
# This recursively expands SET_ID, which calls the shell command and sets MY_ID
    $(SET_ID)
# This will now be a random number
    @echo $(MY_ID)
# Recursively expand SET_ID again, which calls the shell command (again) and sets MY_ID (again)
    $(SET_ID)
# This will now be a different random number
    @echo $(MY_ID)
#生成一个随机数。
#这不是最初运行的。
GENERATE_ID=$(shell od-vAn-N2-tu2
小心这样的食谱

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)留在配方内部。

在下面的示例中,我将Makefile文件夹路径存储到
LOCAL\u PKG\u DIR
,然后在目标中使用
LOCAL\u PKG\u DIR
变量

生成文件:

LOCAL_PKG_DIR := $(shell eval pwd)

.PHONY: print
print:
    @echo $(LOCAL_PKG_DIR)
终端输出:

$ make print
/home/amrit/folder
从制造手册

shell赋值运算符“!=”可用于执行shell脚本并将>变量设置为其输出。该操作符首先计算右侧,然后将>结果传递给shell执行。如果执行结果以>换行结束,则删除该换行;所有其他换行将替换为空格。然后将>结果字符串放入命名的递归扩展变量中。例如:

hash!=printf'\043'

文件列表!=找到-名称“*.c”


命令周围奇怪的回勾符号用于在Makefile中为我执行其他脚本。shell不是标准的Make内置命令。这是一个GNU内置的。添加有关转义
$
的重要说明。此简单示例有效。它还可用于shell命令管道。但您必须在shell命令中使用$$来表示$。虽然这个问题有点老了,但最好执行我的_VAR:=$(shell…),否则每次计算我的_VAR时,它都会再次执行$(shell…);打印int(sys.version_info>=(2,5))”。您会得到“意外标记附近的语法错误”。我不明白怎么会有人
target:
    export MY_ID=$(GENERATE_ID); \
    ./my_shell_script;
LOCAL_PKG_DIR := $(shell eval pwd)

.PHONY: print
print:
    @echo $(LOCAL_PKG_DIR)
$ make print
/home/amrit/folder