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

问题描述 投票:0回答:3

以下命令根据 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)

这将输出一个新行。我认为是散列(“#”)字符扰乱了 make;如果我像这样重写

FILE=...
行:

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

仍然没有输出。

shell g++ makefile echo
3个回答
16
投票

您必须对哈希进行转义两次才能在函数内使用它:一次用于 Make,另一次用于 shell。

也就是说,

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

请注意三个反斜杠,而不是人们所期望的两个。需要第三个反斜杠,因为否则第一个反斜杠会转义第二个反斜杠,并且哈希值仍然不会转义。

UPD。

另一种可能的解决方案是仅转义 Make 的哈希值并使用 Bash 单引号来防止将哈希值解释为 shell 注释。这也消除了转义空格的需要,

<
>

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

1
投票

您需要多引用一点:

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

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


0
投票

与 GNU Make 4.4.1 一样,上述和接受的解决方案对我不起作用,因为

make
抛出一个错误,不允许在哈希符号之前使用反斜杠。

所以我解决了它:

define HASH
#
endef

FILE = $(shell echo '$(HASH)include <ham/hamsterdb.h>')
© www.soinside.com 2019 - 2024. All rights reserved.