我正在尝试在 Make 目标中运行 Python 代码片段,但在尝试弄清楚这些东西在 Make 中如何工作时遇到了困难。
到目前为止,这是我的尝试:
define BROWSER_PYSCRIPT
import os, webbrowser, sys
try:
from urllib import pathname2url
except:
from urllib.request import pathname2url
webbrowser.open("file://" + pathname2url(os.path.abspath(sys.argv[1])))
endef
BROWSER := $(shell python -c '$(BROWSER_PYSCRIPT)')
我想在如下目标中使用 $(BROWSER):
docs:
#.. compile docs
$(BROWSER) docs/index.html
这真的是一个坏主意吗?
答案1
有关的:https://stackoverflow.com/q/649246/4937930
您无法像在单个配方中那样调用多行变量,而是会扩展到多个配方并导致语法错误。
一个可能的解决方法是:
export BROWSER_PYSCRIPT
BROWSER := python -c "$$BROWSER_PYSCRIPT"
docs:
#.. compile docs
$(BROWSER) docs/index.html
答案2
Yaegashi 的方法会起作用,但为其提供动态值并不容易。解析 Makefile 时会评估“export”命令,并将 shell 环境变量设置为配方。然后在执行“docs”配方期间评估环境变量。
如果您的代码片段需要填充任何与目标相关的变量,我建议采用如下方法:
快速方法
如果您只需要运行几句俏皮话,这种模式会非常有效。
run_script = python -c \
"import time ;\
print 'Hello world!' ;\
print '%d + %d = %d' %($1,$2,$1+$2) ;\
print 'Running target \'%s\' at time %s' %('$3', time.ctime())"
test:
$(call run_script,4,3,$@)
奇特的方法
如果您想使用奇怪的字符和函数、for 循环或其他多行结构,这里有一个可以完美工作的奇特模式。
#--------------------------- Python Script Runner ----------------------------#
define \n
endef
escape_shellstring = \
$(subst `,\`,\
$(subst ",\",\
$(subst $$,\$$,\
$(subst \,\\,\
$1))))
escape_printf = \
$(subst \,\\,\
$(subst %,%%,\
$1))
create_string = \
$(subst $(\n),\n,\
$(call escape_shellstring,\
$(call escape_printf,\
$1)))
python_script = printf "$(call create_string,$($(1)))" | python
#------------------------------- User Scripts --------------------------------#
define my_script
def good_times():
print "good times!"
import time
print 'Hello world!'
print '%d + %d = %d' %($2,$3,$2+$3)
print 'Runni`ng $$BEEF \ttarget \t\n\n"%s" at time %s' %('$4', time.ctime())
good_times()
endef
#--------------------------------- Recipes -----------------------------------#
test:
$(call python_script,my_script,1,2,$@)