允许在 make 文件中使用通配符
Posted
技术标签:
【中文标题】允许在 make 文件中使用通配符【英文标题】:Allow wild card characters in make file 【发布时间】:2017-11-21 05:54:32 【问题描述】:我有一个在 Windows 和 Linux 上运行的应用程序。 它有一个在运行时生成的 make 文件。 现在的问题是 make 文件指向具有特殊字符的文件夹路径,例如 @#$%!作为一些路径。
但是由于这些字符有不同的含义 Ex.$ 搜索它的定义 # 指评论
编译失败。
您对此有任何解决方案吗? 提前致谢
【问题讨论】:
目录中包含特殊字符的目录到底是什么?它是源文件、目标文件还是 makefile 本身?还有什么? 它包含对象文件 For Ex:OBJECTS = \ D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o \ 据我所知,在 make 中处理特殊字符非常乏味。当然我不能说 - 但我可以想象首先摆脱那些特殊字符会更容易。 顺便说一句:我看到你有 Windows 路径。不同的 make 二进制文件支持不同的路径。目前我不记得确切的区别,但你可能想看看 msys make 和 mingw make - 它们不一样。 Cygwin make 很可能不适合这种路径。 【参考方案1】:在数字前使用反斜杠,因此在它们之前使用 \,如下所示:\#
【讨论】:
会有很多像你建议的这样的组合。您是否有任何参考将列出所有转义序列的列表?还有一个疑问..这些转义序列在 windows 和 linux 中是否不同【参考方案2】:一旦 make 在其特殊含义是允许的解析解决方案的行中找到像 #
或 :
或 $
这样的文字字符,它将按原样解释它们。最好的办法是修改 makefile 的生成器,并重写路径名的输出过滤器,以将所有此类字符替换为它们的“已消除”引用序列。避免这种情况的另一种方法是预处理生成文件并替换有问题的外观,但我认为这比更改文件名输出要困难得多。
在任何情况下,您都需要在 makefile 中定义一些额外的变量,这些变量将用作引用结构:
space := $(strip) $(strip)#
comma := ,#
hash := \##
percent := %#
colon := :#
equal := =#
paropen := (#
parclose := )#
$
像往常一样被$$
转义。这让你现在可以定义各种讨厌的字符串:
evilstring := $(space)D$(colon)/PR/9354/lib_15_$(hash)$$@$(percent)&/etc...
虽然其他答案是正确的,在变量分配中只有 $
和 #
必须转义,但我不知道您的生成器是否会在其他地方插入文件名:
类似
D:\home\myfile.o:
或
\home\lib_1_&=@!\myfile.o:
因为目标名称可能会导致问题。
您可能想看看gmtt,它现在甚至具有全局匹配(例如$(call glob-match,$(shell uname -sr),Linux 4.[7-9].*)
),尽管这可能对您的问题没有帮助。
【讨论】:
【参考方案3】:如果您在 Makefile 中生成文字文件名:
# This won't work
OBJECTS := D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o
$(info [$OBJECTS])
AFAICS 在 make 中您需要注意的唯一特殊字符是 $
和 #
。
$
总是引入宏扩展。
解决方法是将所有美元翻倍:
$$
扩展为名为@987654326@ 的变量的值,即$
。
#
开始评论。
替换为\#
。
# This works
OBJECTS := D:/PR/9354/lib_15_\#$$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o
$(info [$OBJECTS])
如果您从$(wildcard ...)
的调用中获取文件名,请说,
您不必担心以上问题。
但是,你的 shell 肯定会被所有这些字符弄糊涂。
例如,$
导致 bash 上的参数扩展,&
在 bash 上在后台运行命令等。
这里最安全的做法是在调用 shell 之前引用所有文件名。
如果您的 shell 是 bash,则用单引号 '
将每个文件名括起来。
如果您使用的是 Windows shell (cmd),则必须使用双引号。
(如果你使用 cmd,你的生活将是地狱,因为它疯狂的引用规则。)
所以,假设 bash
$ cat Makefile
OBJECTS := D:/PR/9354/lib_15_\#$$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o
QUOTED := $(patsubst %,'%',$OBJECTS)
.PHONY: all
all:
echo $QUOTED
给予
$ make --warn
echo 'D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o'
D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV15.o
嘘。
编辑
最简单的当然是避开make的解析器,
并且只需使用$(file …)
读取不受干扰的文件名。
$ cat names
D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV15.o
$ cat Makefile
OBJECTS := $(file < names)
.PHONY: all
all:
echo $(patsubst %,'%',$OBJECTS)
$ make
echo 'D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV15.o'
D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV15.o
正如@Vroomfondel 指出的那样,该名称甚至包括有问题的:=
。
【讨论】:
另外$
是make 的宏扩展字符(在显示的情况下$@
指的是正在执行的规则的目标)所以你必须加倍小心。您应该使用\$$@
正确展开它。
根据出现特殊字符的行的类型,:
和 =
也可能造成问题(例如某些 $(eval )
构造)以上是关于允许在 make 文件中使用通配符的主要内容,如果未能解决你的问题,请参考以下文章