Makefile shell调用中的哈希导致意外行为

qqrboqgw  于 11个月前  发布在  Shell
关注(0)|答案(3)|浏览(121)

下面的命令根据g认为的位置打印特定C头的绝对路径。

echo \#include\<ham/hamsterdb.h\> | g++ -M -x c++-header - | grep hamsterdb.hpp | sed -e 's/-:  //' -e 's/ \\//'

字符串
在我的系统上,输出如下:/usr/local/include/ham/hamsterdb.hpp
当我试图在Makefile中运行这个命令来设置一个变量时,我遇到了一个问题:

FILE=$(shell echo \#include\<ham/hamsterdb.h\> | g++ -M -x c++-header - | grep hamsterdb.hpp | sed -e 's/-:  //' -e 's/ \\//')

.PHONY spec

spec:
    @echo $(FILE)


这会输出一个新的行。我认为是hash('#')字符扰乱了make;如果我像这样重写FILE=...行:

FILE=$(shell echo \#include\<ham/hamsterdb.h\>)


输出仍然是零。

blpfk2vs

blpfk2vs1#

为了在函数中使用它,你必须转义哈希两次:一次用于Make,另一次用于shell。
也就是说,

FILE = $(shell echo \\\#include\ \<ham/hamsterdb.h\>)

字符串
请注意三个反斜杠,而不是预期的两个。第三个反斜杠是必要的,因为否则第一个反斜杠会转义第二个反斜杠,而哈希仍然是未转义的。

UPD。

另一种可能的解决方案是只对Make的hash进行转义,并使用Bash单引号来防止将hash解释为shell注解。这也消除了对空格、<>进行转义的需要:

FILE = $(shell echo '\#include <ham/hamsterdb.h>')

5cg8jx4n

5cg8jx4n2#

你只需要多引用一点:

FILE=$(shell echo \\\#include\<ham/hamsterdb.h\> ...
                  ^^^

字符串
引用一次make本身,第二次引用shell(shell需要“看到”\#)。

bf1o4zei

bf1o4zei3#

与GNU Make 4.4.1一样,上述已被接受的解决方案对我不起作用,因为make抛出了一个错误,即它不允许在哈希符号前使用反斜杠。
所以我解决了它:

define HASH
#
endef

FILE = $(shell echo '$(HASH)include <ham/hamsterdb.h>')

字符串

相关问题