以下命令根据 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\>)
仍然没有输出。
您必须对哈希进行转义两次才能在函数内使用它:一次用于 Make,另一次用于 shell。
也就是说,
FILE = $(shell echo \\\#include\ \<ham/hamsterdb.h\>)
请注意三个反斜杠,而不是人们所期望的两个。需要第三个反斜杠,因为否则第一个反斜杠会转义第二个反斜杠,并且哈希值仍然不会转义。
另一种可能的解决方案是仅转义 Make 的哈希值并使用 Bash 单引号来防止将哈希值解释为 shell 注释。这也消除了转义空格的需要,
<
和>
:
FILE = $(shell echo '\#include <ham/hamsterdb.h>')
您需要多引用一点:
FILE=$(shell echo \\\#include\<ham/hamsterdb.h\> ...
^^^
为
make
本身引用一次,为 shell 引用第二次(shell 需要“看到”\#
)。
与 GNU Make 4.4.1 一样,上述和接受的解决方案对我不起作用,因为
make
抛出一个错误,不允许在哈希符号之前使用反斜杠。
所以我解决了它:
define HASH
#
endef
FILE = $(shell echo '$(HASH)include <ham/hamsterdb.h>')