【问题标题】:How do I handle files with spaces in my Makefile?如何处理 Makefile 中带有空格的文件?
【发布时间】:2013-07-31 08:54:15
【问题描述】:

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

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.

有没有办法在不重命名文件夹的情况下解决这个问题?

提前致谢。

【问题讨论】:

标签: makefile


【解决方案1】:

非常简短但 IMO 最终正确的答案是 make(不仅仅是 GNU make,而是所有 POSIX 样式的 make 实现)不支持包含空格的路径名。如果您想使用 make,您的“匿名开发人员”根本无法使用它们。如果他们坚持这是绝对要求,您应该完全切换到不同的构建工具,它确实支持文件名中的空格。

是的,几乎可以创建一个可以处理包含空格的文件名的 makefile,但是您基本上必须从头开始重写所有 makefile,并且您将无法使用许多GNU make 的特性,因此您的 makefile 会很长、难以阅读且难以维护。

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

【讨论】:

  • 尽管我宁愿完全避免使用空格,但它根本不是一种选择:( ..你说的是“不同的构建工具”..你知道任何可以替代的构建工具吗?轻松处理空间?如果需要的话,我很乐意学习另一种构建工具。
  • 市面上有很多不同的构建工具,但我对它们不熟悉,所以我无法告诉你哪些流行/仍然受支持,哪些是可移植的,哪些处理空白在文件名中。还有一些功能方面的考虑(并行构建、递归/非递归、效率等)。您可以在 Google 上搜索“gnu make alternatives”等术语。我知道的一些术语包括 scons、cook、bras、ant。从字面上看,我只知道他们的名字。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    如果您查看这篇出色的文章: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
    

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

    【讨论】:

      【解决方案4】:

      当您自动生成 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 运行它。

      【讨论】:

        猜你喜欢
        • 2020-06-18
        • 2023-03-22
        • 2018-06-01
        • 1970-01-01
        • 2012-12-12
        • 1970-01-01
        • 2013-12-17
        • 2013-09-10
        相关资源
        最近更新 更多