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

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


当前回答

With GNU Make, you can use shell and eval to store, run, and assign output from arbitrary command line invocations. The difference between the example below and those which use := is the := assignment happens once (when it is encountered) and for all. Recursively expanded variables set with = are a bit more "lazy"; references to other variables remain until the variable itself is referenced, and the subsequent recursive expansion takes place each time the variable is referenced, which is desirable for making "consistent, callable, snippets". See the manual on setting variables for more info.

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

其他回答

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

将以下内容放入“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”前面的空白转换为一个制表符,这个例子应该,最后,希望对你有用。

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

在下例中,我将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

With GNU Make, you can use shell and eval to store, run, and assign output from arbitrary command line invocations. The difference between the example below and those which use := is the := assignment happens once (when it is encountered) and for all. Recursively expanded variables set with = are a bit more "lazy"; references to other variables remain until the variable itself is referenced, and the subsequent recursive expansion takes place each time the variable is referenced, which is desirable for making "consistent, callable, snippets". See the manual on setting variables for more info.

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

小心这样的食谱

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