shell 如何将命令的输出赋给Makefile变量

dwbf0jvd  于 12个月前  发布在  Shell
关注(0)|答案(8)|浏览(158)

我需要有条件地执行一些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中不起作用。
有什么建议吗?我可以使用任何其他合理的变通方法来实现这一点。

ha5z0ras

ha5z0ras1#

像在MY_VAR=$(shell echo whatever)中一样使用Make shell内置

me@Zack:~$make
MY_VAR IS whatever

字符串

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

all:
    @echo MY_VAR IS $(MY_VAR)

tcomlyy6

tcomlyy62#

小心这样的食谱

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

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

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


这两个问题都已修复,变量可以使用。反斜杠将两行合并在一个shell中运行,因此变量的设置和变量后的阅读都可以工作。
最后一个改进,如果消费者希望设置一个“环境变量”,那么您必须导出它。

my_shell_script
    echo $MY_ID


在makefile中需要这个

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


一般来说,应该避免在recipes之外做任何真实的工作,因为如果有人使用带有“--dry-run”选项的makefile,只看到它会做什么,它不会有任何不希望的副作用。每个$(shell)调用都在编译时进行评估,并且可能会意外地完成一些真实的工作。最好尽可能将真实的工作留在recipes内部。

q3aa0525

q3aa05253#

使用GNU Make,您可以使用shelleval来存储、运行和分配来自任意命令行调用的输出。用=设置的递归扩展变量有点“懒惰”;对其他变量的引用一直保持到变量本身被引用为止,并且 * 每次引用变量时都会发生随后的递归扩展 *,这对于制作“一致的,可调用的片段”是理想的。请参阅设置变量手册以获取更多信息。

# 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)

字符串

zf9nrax1

zf9nrax14#

把作业 Package 在一个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)

字符串

p4tfgftt

p4tfgftt5#

这里有一个更复杂的例子,在配方中有管道和变量赋值:

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)

字符串

jucafojl

jucafojl6#

我写一个答案来增加解决问题的实际语法的可见性。不幸的是,对于那些寻找合理问题的简单答案的人来说,一些人可能认为微不足道的东西可能会成为一个非常头痛的问题。
将以下内容放入“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: *** missing separator. Stop
原因:因为虽然我个人使用了一个真正的标签,堆栈溢出(试图提供帮助)将我的标签转换为多个空格。你,沮丧的互联网公民,现在复制这个,以为你现在有我使用的相同文本。make命令,现在读取空格,发现“all”命令格式不正确。所以复制上面的文本,粘贴它,然后将“@echo”前面的空格转换为制表符,希望这个例子最终能为您所用。

epggiuax

epggiuax7#

在下面的示例中,我将Makefile文件夹路径存储到LOCAL_PKG_DIR,然后在目标中使用LOCAL_PKG_DIR变量。
Makefile:

LOCAL_PKG_DIR := $(shell eval pwd)

.PHONY: print
print:
    @echo $(LOCAL_PKG_DIR)

字符串
端子输出:

$ make print
/home/amrit/folder

nbnkbykc

nbnkbykc8#

从制造手册上
shell赋值运算符“!=”可以用来执行shell脚本,并将>变量设置为输出。该运算符首先计算右侧,然后将>结果传递给shell执行。如果执行结果以>换行符结束,则删除该换行符;所有其他的换行符都被替换为空格。然后,>结果字符串被放置到命名的递归扩展变量中。例如:
第一个月
file_list != find . -name '*.c'
source

相关问题