如何在Makefile中处理带空格的文件?

时间:2013-07-31 08:54:15

标签: makefile

因此,一些匿名开发人员决定使用在包含其源文件的文件夹名称中使用空格的荒谬惯例。我会更改这些文件夹而不是使用空格,但遗憾的是我不在这里制定规则,所以这不是一个选项(虽然我希望它是)。

LUAC            = luac

SRC_DIR         = .
SOURCE          =                                                      \
stupid/naming\ convention/a.lua                                        \
stupid/naming\ convention/very\ annoying/b.lua                         \

vpath .lua $(SRC_DIR)

OUT_DIR         = ../out/
OUTPUT          = $(patsubst %.lua, $(OUT_DIR)/%.luac, $(SOURCE))


all: $(OUTPUT)

$(OUT_DIR)/%.luac: %.lua
    $(LUAC) "$<"
    mv luac.out "$@"

.PHONY: all

简单的Makefile。它所要做的就是编译我拥有的所有Lua文件并将它们放入输出目录。

无论如何,我一直希望将SOURCE字符串拆分到文件夹中的空格中,所以我最终会得到一个漂亮的错误:

make: *** No rule to make target `stupid/naming ', needed by `all'.  Stop.

有没有办法在不重命名文件夹的情况下修复此问题?

提前致谢。

4 个答案:

答案 0 :(得分:3)

非常短,但IMO最终正确,答案是make(不仅仅是GNU make,而是所有POSIX风格的make实现)都不支持包含空格的路径名。如果你想使用make,你的“匿名开发者”根本就不能使用它们。如果他们坚持认为这是一个绝对的要求,你应该完全切换到另一个构建工具,它确实支持文件名中的空格。

是的,几乎可以创建一个可以处理包含空格的文件名的makefile,但是你必须从头开始重写所有的makefile,你将无法使用很多GNU的功能使你的makefile很长,难以阅读,难以维护。

告诉他们克服自己。或者,如果他们真的不能,尝试让他们在路径名中创建他们的工作区,名称中没有任何空格,然后创建一个包含指向真实工作空间的空格的符号链接(反过来说在所有情况下都不起作用)。

答案 1 :(得分:1)

Unfortunately, GNU Make's functions that deal with space-separated list do not respect the escaping of the space。唯一的例外是wildcard

编辑:

这是我的解决方法:

LUAC            = luac

SRC_DIR         = .
SOURCE          =                                                      \
stupid/naming\ convention/a.lua                                        \
stupid/naming\ convention/very\ annoying/b.lua                         \

vpath .lua $(SRC_DIR)


OUT_DIR         = ../out/
OUTPUT          = $(patsubst %.lua,%.luac,$(SOURCE))


all: $(OUTPUT)

%.luac: %.lua
    $(LUAC) "$<"
    mv luac.out "$@""

.PHONY: all

我试着先输出它:

%.luac: %.lua
    @echo "$<"
    @echo "$@""

输出如下:

stupid/naming convention/a.lua
../out/stupid/naming convention/a.luac
stupid/naming convention/very annoying/b.lua
../out/stupid/naming convention/very annoying/b.luac

答案 2 :(得分:0)

如果你看一下这篇优秀的文章:http://www.cmcrossroads.com/article/gnu-make-meets-file-names-spaces-them,作者认为这主要是一项艰巨的任务。但他的替代功能可以让你去,万一你真的无法避开空间。

将它放入你的makefile看起来像这样(对不起,如果我改变了你的一些路径,但这适用于我的Cygwin安装):

LUAC            = luac

s+ = $(subst \\ ,+,$1)
+s = $(subst +,\ ,$1) 

SRC_DIR  = .
SOURCE  := stupid/naming\\ convention/a.lua 
SOURCE := $(call s+,$(SOURCE)) 

vpath .lua $(SRC_DIR)

OUT_DIR         = out/
OUTPUT          = $(patsubst %.lua, $(OUT_DIR)/%.luac, $(SOURCE))

all: $(call +s,$(OUTPUT))

$(OUT_DIR)/%.luac: %.lua
    $(LUAC) "$<"
    mv luac.out "$@"

.PHONY: all

我知道这不是一个完整的答案,但也许鼓励它实际上是可能的。但我同意其他海报,如果你真的可以完全避免空间,你将有一个更轻松的生活!

答案 3 :(得分:0)

当您自动生成Makefile时,另一种有效的策略是该策略,它也用在Perl's ExtUtils::MakeMaker中:将格式设置为可在配方中使用的名称分开,而不是将其用作依赖项。这里的示例有一个THISFILE和一个THISFILEDEP

AWKWARD_DIR = sub dir
AWKWARD_DIRDEP = sub\ dir
THISFILE = $(AWKWARD_DIR)/d1
THISFILEDEP = $(AWKWARD_DIRDEP)/d1
AWKWARD_DIR_EXISTS = $(AWKWARD_DIR)/.exists
AWKWARD_DIR_EXISTSDEP = $(AWKWARD_DIRDEP)/.exists
TARGET = $(AWKWARD_DIR)/t1
TARGETDEP = $(AWKWARD_DIRDEP)/t1
MAKEFILE = spacemake.mk

$(TARGETDEP): $(THISFILEDEP) $(AWKWARD_DIR_EXISTSDEP)
        cat "$(THISFILE)" >"$(TARGET)"

$(THISFILEDEP): $(AWKWARD_DIR_EXISTSDEP)
        echo "yo" >"$(THISFILE)"

$(AWKWARD_DIR_EXISTSDEP): $(MAKEFILE)
        @echo MAKEFILE = $(MAKEFILE)
        -mkdir "$(AWKWARD_DIR)"
        touch "$(AWKWARD_DIR_EXISTS)"

您可以通过将其放置在名为的文件中进行尝试。 spacemake.mk,然后与gmake -f spacemake.mk运行。