允许在 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_REV‌​15.o
$(info [$OBJECTS])

AFAICS 在 make 中您需要注意的唯一特殊字符是 $#

$ 总是引入宏扩展。 解决方法是将所有美元翻倍: $$ 扩展为名为@9​​87654326@ 的变量的值,即$

# 开始评论。 替换为\#

# This works
OBJECTS := D:/PR/9354/lib_15_\#$$@%&/submodels/win32-gcc/CONS00_ABHI_REV‌​15.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_REV‌​15.o
QUOTED := $(patsubst %,'%',$OBJECTS)

.PHONY: all
all:
    echo $QUOTED

给予

$ make --warn
echo 'D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV‌​15.o'
D:/PR/9354/lib_15_#$@%&/submodels/win32-gcc/CONS00_ABHI_REV‌​15.o

嘘。

编辑

最简单的当然是避开make的解析器, 并且只需使用$(file …) 读取不受干扰的文件名。

$ cat names
D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV‌​15.o

$ cat Makefile
OBJECTS := $(file < names)

.PHONY: all
all:
        echo $(patsubst %,'%',$OBJECTS)

$ make
echo 'D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV‌​15.o'
D:/PR/9354/lib_15_#$@%&/submodels:=/win32-gcc/CONS00_ABHI_REV‌​15.o

正如@Vroomfondel 指出的那样,该名称甚至包括有问题的:=

【讨论】:

另外$ 是make 的宏扩展字符(在显示的情况下$@ 指的是正在执行的规则的目标)所以你必须加倍小心。您应该使用\$$@ 正确展开它。 根据出现特殊字符的行的类型,:= 也可能造成问题(例如某些 $(eval ) 构造)

以上是关于允许在 make 文件中使用通配符的主要内容,如果未能解决你的问题,请参考以下文章

GNU Make 和通配符 - 缺少文件

Makefile入门: 用最美味的例子

makefile的使用

使用Azure功能启用CORS通配符子域

Linux(centos)下安装卸载命令rpm,make install使用方法

使用通配符配置文件签署应用程序的问题