使用包含空格的文件名的GNUMake最可靠的方法是什么?

我想用GNUMake来运行一个基于规则的makefile,它在目录结构(在Windows文件系统上)中build立一组C文件。

根目录,一些子目录和一些文件包含空格。

示例文件: "C:\Documents and Settings\<username>\My Documents\Test Dir\Build Me.c"

当文件path包含空格时,GNUMake不起作用。 我已经读过解决这个问题的可能方法(从我的文件名中删除空格,使用8.3格式,用?\\等replace空格),但没有一个是完美的(或者它们是什么?

有没有解决这个问题的银弹?

顺便说一句,我坚持与GNUMake,我不能使用不同的制造工具。

最简单的事情就是修复文件名。

如果没有这样的话,编写你的命令在文件名周围加双引号。 最简单和最安全的是把所有的文件名都放入宏中; 诀窍在于,你必须避免双引号,否则Make会想要吃掉自己。

所以:FN =“\”C:\ My Documents \ myfiles.c \“”FN2 =“C:\ My Documents \ myfile2.c”

或使用$(CC)$(CFLAGS)“$(FN2)”

这里的技巧是用echo回显你的命令行

 echo $(CC) $(CFLAGS) "$(FN2)" 

或使用make -d来获取make -d所有细节。

您可能需要对此进行一些破解,特别是您可能需要将逃生加倍

你可能能够逃离你的makefile中的空间,即:

 $(CC) $(CFLAGS) 'C:\Documents\ and\ Settings\<username>\My\ Documents\Test\ Dir\Build Me.c' 

我已经添加了单引号以防万一,但我不知道这是否工作,如果你使用Windows终端(而不是cygwin等)。

我在http://www.mail-archive.com/help-make@gnu.org/msg05201.html找到了一个很好的启发&#x3002; 我自己的测试应用程序包含一个从YouTube下载的WW2时代的Jazz FLV文件的目录以及一个我想要存储每个OGA音频版本的音频子目录。 当然,文件名包含空格。 然后我想运行ffmpeg2theora

这里是我一起黑客工作的GNUMake Makefile。 感谢这个网站上的所有提示以及上面提到的网站!

 sq = $(subst $(sp),?,$1) qs = $(subst ?,$(sp),$1) e := sp := $(e) $(e) FLVS := $(foreach file,var,$(call sq,$(wildcard *.flv))) FLVS := $(subst .flv?,.flv ,$(FLVS)) AUDIOS := $(patsubst %.flv,audio/%.oga,$(FLVS)) .PHONY: audios show audios: $(AUDIOS) $(AUDIOS) : $(FLVS) ffmpeg2theora --novideo -o "$(call qs,$@)" "$(call qs,$(notdir $(patsubst %.oga,audio/%.flv,$@)))" show: echo $(FLVS) echo $(AUDIOS) 

我通常使用的是Dana Sane的答案和Brian Yoder的答案。

您只需使用$(subst)函数来替换所有空格出现的空格。 例如:

 empty := space := $(empty) $(empty) program_files := $(subst $(space),\$(space),$(ProgramFiles)) 

(请注意,在Windows上使用某些旧版本的make时,还需要使用另一个$(subst)将路径反斜杠更改为斜杠)

如果空格只位于路径名的“根”部分,则可以在没有空白的路径上挂载该目录。 有多种方法可以做到这一点:从命令行(“net use”或“subst”)或从资源管理器(工具>地图网络驱动器)。 因此C:\ Documents and Settings \\ My Documents \ Test Dir“可能会变成X:\ BuildMe.c

但是,如果文件名中存在空格,或者在“root”编译目录下的目录中有空白,则可能没有任何完美的解决方案。 我已经使用了你提到的其他建议(8.3名称,用不同的字符替代空白),这些工作,但他们有自己的问题。

我只是在冒犯的字符串周围添加“单引号”: – '$(TARGET_DIR)'

例如:(这帮助我得到erlang.mk在Windows上正常工作!)

 app:: $(C_SRC_ENV) @mkdir -p priv/ $(c_src_verbose) $(CC) $(CFLAGS) $(C_SRC_DIR)/*.c -fPIC -shared -o $(C_SRC_OUTPUT) \ -I '$(ERTS_INCLUDE_DIR)' $(C_SRC_OPTS) 

'$(ERTS_INCLUDE_DIR)'现在可以正确扩展为'c:/Program Files/erl7.0/erts-7.0/include/'

使用make -d还有助于揭示无效路径