如何在名称中带有标签的目录中编译(制作)?

How to compile (make) in a directory with a hashtag in its name?

(TL;底部的 DR)

我有一个 c++ 项目,我可以使用它成功编译

mkdir build && cd build
cmake ..
make

但是,因为我不想让我的云同步程序同步它,所以我将此文件夹命名为 build,而不是 _#build。这导致 make 输出这个:

/bin/sh: -c: line 0: unexpected EOF while looking for matching `"'
/bin/sh: -c: line 1: syntax error: unexpected end of file make: ***
[Makefile:190: cmake_check_build_system] Error 1

在对构建文件夹使用不同的名称进行试验后 - 例如 `~build~ 似乎可以工作 - 我注意到当 dirname 包含井号 (#) 符号时,cmake 的输出有一行不同。

-- Detecting CXX compile features - failed

没有主题标签,它说 "done" 而不是 "failed"。

对于这种特定情况,我只是告诉我的同步工具也忽略名为 "build" 的目录,并且只使用目录名 "build",但我仍然想知道如果我想保留名称中的标签。这是我的问题:我如何 运行 在名称中包含 # 的目录中成功创建?

请注意,这发生在 cygwin 上,我不确定这是否也会发生在本机 bash shell.

第一次编辑

按照 Patrick Kelly 的建议,我尝试将 Makefile 中路径中的所有出现从 _#build 替换为 _\#build。我是手动这样做的,并在确保没有其他事件发生后也使用 sed。 当我随后尝试 运行 make 时,这不起作用,所以我尝试只替换任何子文件夹中任何文件中出现的 _#build - 我认为不会有任何出现在路径之外。只是为了确保没有任何变化。所以我所做的是:

$ grep --null -l '_#build' -r . | xargs -0 sed -i 's/_#build/_\#build/g'

我真的不明白为什么我必须转义反斜杠,我认为单引号没有评估它。但无论如何,这也没有用。此命令的简短说明:grep 列出在任何子文件夹 (-r) 中找到的所有文件名 (-l),并用空字符 (--null) 分隔它们,以便 xargs 将 sed 应用于所有这些文件。 sed 命令本身会替换文件中所有出现的地方。

现在的问题:

make

Call Stack (most recent call first):
  /usr/share/cmake-3.6.2/Modules/CMakeSystemSpecificInformation.cmake:36 (include)
  CMakeLists.txt:5 (PROJECT)

-- Configuring incomplete, errors occurred!
See also "/cygdrive/c/Users/myUser/Documents/temp/_#build/CMakeFiles/CMakeOutput.log".
See also "/cygdrive/c/Users/myUser/Documents/temp/_#build/CMakeFiles/CMakeError.log".
make: *** [Makefile:190: cmake_check_build_system] Error 1

和 CMakeError.log 包含 "Run Build Command" 和 "Detecting CXX [-std=c++14] compiler features ..." 的以下内容(不粘贴整个内容)。 检测 CXX [-std=c++14] 编译器功能无法编译,输出如下:

Change Dir: /cygdrive/c/Users/myUser/Documents/temp/_\#build/CMakeFiles/CMakeTmp

Run Build Command:"/usr/bin/make.exe" "cmTC_1dcec/fast"
/usr/bin/make -f CMakeFiles/cmTC_1dcec.dir/build.make CMakeFiles/cmTC_1dcec.dir/build
make[1]: Entering directory '/cygdrive/c/Users/myUser/Documents/temp/_\#build/CMakeFiles/CMakeTmp'
make[1]: *** No rule to make target '/cygdrive/c/Users/myUser/Documents/temp/_', needed by 'CMakeFiles/cmTC_1dcec.dir/feature_tests.cxx.o'.  Stop.

很明显,我在太多地方插入了反斜杠,是吧? 简单的解决方案:我不需要更改 Makefile 中所有出现的地方。我必须更换的东西:

CMAKE_BINARY_DIR = "/cygdrive/c/Users/myUser/Documents/temp/_\#build"

我必须保留的内容:

all: cmake_check_build_system
    $(CMAKE_COMMAND) -E cmake_progress_start "/cygdrive/c/Users/myUser/Documents/temp/t/_#build/CMakeFiles" "/cygdrive/c/Users/myUser/Documents/temp/t/_#build/CMakeFiles/progress.marks"
    $(MAKE) -f CMakeFiles/Makefile2 all
    $(CMAKE_COMMAND) -E cmake_progress_start "/cygdrive/c/Users/Eric/Documents/temp/t/_#build/CMakeFiles" 0

此外,除了 Makefile 之外,无需更改任何其他文件。

TL;DR

Only change the line with CMAKE_BINARY_DIR to CMAKE_BINARY_DIR = "/cygdrive/c/Users/myUser/Documents/temp/_\#build"

因为我需要替换的路径是 Makefile 中的第一次出现,下面的 bash 命令帮我实现了自动化。

sed -i 's/_#build/_\#build/' Makefile

问题在于 make 使用 # 符号进行注释。当 cmake 创建您的 Makefile 时,生成的其中一行将为您设置构建目录。像这样:

CMAKE_BINARY_DIR = "/home/Patrick/TEMP/_#build"

但是由于 # 符号用于注释,并且 make 不使用您的 shell 所使用的所有相同转义规则,它会忽略该行的 build" 部分.这将创建一个未终止的字符串。没有 CMake 机制可以让您自动修复此问题。用户无法覆盖 CMakeLists.txt 文件中 CMAKE_BINARY_DIR 的定义。这是 cmake 生成和管理的特殊变量。所以使这项工作的唯一方法是在 运行 cmake 之后手动编辑 Makefile,并在 # 符号之前添加一个转义字符:

CMAKE_BINARY_DIR = "/home/Patrick/TEMP/_\#build"

如果您愿意在 cmake 命令后手动编辑,您可以让它工作。或者,如果您 真的 有动力,您可以编写自己的 shell 脚本来为您更改 Makefile,然后 运行 命令在 cmake 之后。类似于:

mkdir _#build && cd _#build
cmake ..
fix_makefile.sh
make