如果你想在Makefile里面直接写bash脚本,你需要做一些特殊处理,而不能直接粘贴复制你的bash脚本。如果你在target行后直接粘贴复制,你会遇到两个问题:
- 命令行要以tab为缩进
- $需要转义
如果你用gnu的make,你可以根据multi-line definition syntax来将你的脚本定义为一个变量,然后集合value
function来使用。
另外,你还需要告诉你的make将一个target作为一个shell, 而不是一行一个shell. 可参考defining a .ONESHELL
target.
下面,我们提到的这几个关键用法,进行讲解和实践
multi-line definition syntax
使用define关键字去声明多行变量,然后export其作为环境变量,然后在shell脚本中直接引用。如下:
export ANNOUNCE_BODY
all:
@echo "$$ANNOUNCE_BODY"
define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.
It can be downloaded from $(DOWNLOAD_URL).
etc, etc.
endef
需要注意:
$$ANNOUNCE_BODY作为一个被引用的shell的环境变量,而不是
$(ANNOUNCE_BODY)
, $()是make的语法,引用的是make的变量。- 一定要用引号将该变量包括,防止多行的字符串被shell自己转义
- 这种用法并不一定通用。还要根据你的平台进行测试。
value function
这个函数使得你可以直接使用一个变量的值,而不是一个展开后的值。如下:
FOO = $PATH
test_value_function:
@echo $(FOO)
@echo $(value FOO)
第一个输出为ATH,因为“$P”会被作为一个make变量展开,这个输出则为正确的PATH的值,因为value函数逼民了这种展开。
Using one shell
https://www.gnu.org/software/make/manual/html_node/One-Shell.html
有时,你希望你在target下多行shell可以作为一个shell运行。这样做的好处是:
- 提高makefile的性能
- 你希望多行直接可以共享信息。
.ONESHELL
可以帮助我们。如下:
.ONESHELL:
test_one_shell:
a=testing;
echo $$a
这里的ONESHELL并不一定就是shell.也可以指定为其他的语言。例如,perl.如下
.ONESHELL:
SHELL = /usr/bin/perl
.SHELLFLAGS = -e
show :
# Make sure "@" is not the first character on the first line
@f = qw(a b c);
print "@f\n";