寻找一个“cmake clean”命令来清除CMake输出。

616

就像make clean会删除Makefile生成的所有文件一样,我希望在CMake中也能做到同样的事情。经常需要手动浏览目录并删除类似cmake_install.cmakeCMakeCache.txtCMakeFiles等文件。

是否有像cmake clean这样的命令可以自动删除所有这些文件?理想情况下,这应该遵循当前目录下的CMakeLists.txt文件定义的递归结构。


5
针对 CMake 3.0 及更高版本的用户,您可以使用命令 cmake --build <build-dir> --target clean 来清除构建目录。 - Sean Francis N. Ballais
26个回答

7
在使用CMake生成构建文件时,如果您传递了-D参数并且不想删除整个build/目录,则可以执行以下操作:
只需删除构建目录中的CMakeFiles/目录即可。
rm -rf CMakeFiles
cmake --build .

这会导致CMake重新运行,生成构建系统文件。您的构建也将从头开始。


不仅仅这样还不够,必须删除CMakeCache.txt文件(就像找到的库一样)。 - Pierre
"rm" 不是可移植的。它在命令提示符中失败。是的,PowerShell、WSL 和类似 Cygwin 的环境可以提供解决方法。但我更喜欢我的工具能够更加可移植。使用 rez 作为解决方案。https://github.com/mcandre/rez - mcandre

6

CMake 3.X

CMake 3.0及以上版本提供了一个“clean”目标,该目标可以删除任何工件,例如目标文件、库文件、可执行文件、生成的文件等。

cmake --build C:/foo/build/ --target clean

你也可以清理构建,然后运行构建。只需一个命令。

cmake --build C:/foo/build --clean-first

然而,这不会清理像CMakeCache.txt或相关的CMakeFiles/目录之类的东西。您可能希望这样做。您只需要删除构建文件夹即可。

# Just delete the build folder
rm C:/foo/build -rf

# You can also just let git delete the build folder as well
git clean -d -f -x

CMake 3.24

现在在CMake 3.24中,您可以对构建树进行全新的配置。这将删除任何现有的CMakeCache.txt文件和相关的CMakeFiles/目录,并从头开始重新创建它们。

通常情况下,您需要在以下情况下执行此操作:

  • 您想要清除CMakeCache.txt中缓存的变量
  • 您想要更改编译器
  • 与CMake缓存相关的任何其他操作
cmake -B C:/foo/build --fresh

5
尝试使用以下命令: cmake --clean-first CMakeLists.txt文件路径 -B 输出目录
--clean-first:首先清除构建目标,然后构建。 (仅清除请使用--target clean。)

那个屏幕截图只显示了文本。但是你却对它进行了截图,这会破坏任何使用屏幕阅读器的人的答案。请删除该图片,并复制/粘贴文本,并花费1分钟来正确格式化该输入。 - GhostCat
你说的"use --target clean"是什么意思?$ cmake --target clean CMake错误:未知参数--target CMake错误:运行“cmake --help”以获取所有支持的选项。 - shirish

4

当然,对于Unix Makefiles,使用源外构建是首选的方法,但如果您正在使用其他生成器,如Eclipse CDT,则它更喜欢您在源内构建。在这种情况下,您需要手动清除CMake文件。请尝试以下操作:

find . -name 'CMakeCache.txt' -o -name '*.cmake' -o -name 'Makefile' -o -name 'CMakeFiles' -exec rm -rf {} +

如果你使用了shopt -s globstar启用了globstar,那么可以尝试这种更好的方法:

rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles

昨天我的选择是将repo克隆到一个新文件夹中,更新CMakeLists.txt以从子文件夹“build”构建。这比那些命令花费了更长的时间,但我只需要做一次 :) - Tien Do

3
我最近发现的一个解决方案是将外部构建概念与Makefile包装器相结合。
在我的顶层CMakeLists.txt文件中,我包含以下内容以防止源内构建:
if ( ${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR} )
    message( FATAL_ERROR "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there. You may need to remove CMakeCache.txt." )
endif()

然后,我创建了一个顶层Makefile,并包含以下内容:
# -----------------------------------------------------------------------------
# CMake project wrapper Makefile ----------------------------------------------
# -----------------------------------------------------------------------------

SHELL := /bin/bash
RM    := rm -rf
MKDIR := mkdir -p

all: ./build/Makefile
    @ $(MAKE) -C build

./build/Makefile:
    @  ($(MKDIR) build > /dev/null)
    @  (cd build > /dev/null 2>&1 && cmake ..)

distclean:
    @  ($(MKDIR) build > /dev/null)
    @  (cd build > /dev/null 2>&1 && cmake .. > /dev/null 2>&1)
    @- $(MAKE) --silent -C build clean || true
    @- $(RM) ./build/Makefile
    @- $(RM) ./build/src
    @- $(RM) ./build/test
    @- $(RM) ./build/CMake*
    @- $(RM) ./build/cmake.*
    @- $(RM) ./build/*.cmake
    @- $(RM) ./build/*.txt

ifeq ($(findstring distclean,$(MAKECMDGOALS)),)
    $(MAKECMDGOALS): ./build/Makefile
    @ $(MAKE) -C build $(MAKECMDGOALS)
endif

默认目标all可通过键入make来调用,它会调用目标./build/Makefile

目标./build/Makefile的第一件事是使用变量$(MKDIR)创建build目录,该变量代表mkdir -p。目录build是我们进行源外编译的地方。我们提供参数-p以确保mkdir不会因尝试创建可能已经存在的目录而报错。

目标./build/Makefile的第二件事是更改到build目录并调用cmake

回到all目标,我们调用$(MAKE) -C build,其中$(MAKE)是自动生成的代表make的Makefile变量。make -C在执行任何操作之前都会更改目录。因此,使用$(MAKE) -C build等同于执行cd build; make

总之,使用make allmake调用此Makefile包装器相当于执行:

mkdir build
cd build
cmake ..
make 

目标 distclean 会调用 cmake ..,然后执行 make -C build clean,最后从build目录中删除所有内容。我相信这正是您在问题中请求的。
Makefile 的最后一部分评估用户提供的目标是否是 distclean。如果不是,则会在调用之前更改到build目录。这非常强大,因为用户可以键入例如 make clean,而 Makefile 将把它转换成等同于 cd build; make clean 的命令。
总之,此 Makefile 包装器与必须采用 CMake 配置的源之外构建结合使用,使得用户永远不必与命令 cmake 进行交互。这种解决方案还提供了一种优雅的方法来从build目录中删除所有 CMake 输出文件。
P.S. 在 Makefile 中,我们使用前缀 @ 来抑制 shell 命令的输出,并使用前缀 @- 来忽略 shell 命令中的错误。当使用 rm 作为 distclean 目标的一部分时,如果文件不存在(可能已经使用命令行和 rm -rf build 删除了它们,或者它们从未生成),则该命令将返回错误。这个返回值将强制我们的 Makefile 退出。我们使用前缀 @- 来防止这种情况。如果文件已被删除,则可以接受;我们希望我们的 Makefile 继续运行并删除其余部分。
还有一件事要注意:如果您使用变量数量的 CMake 变量来构建项目,例如 cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar",则此 Makefile 可能无法正常工作。此 Makefile 假定您以一致的方式调用 CMake,即通过键入 cmake .. 或通过提供一致数量的参数来调用 cmake (您可以将其包含在您的 Makefile 中)。
最后,功劳归于源——此 Makefile 包装器是从C++ 应用程序项目模板 提供的 Makefile 改编而来。

我建议永远不要使用 Makefile 作为元构建器。它真的很麻烦且容易出错。如果你想这么做,写一个脚本(例如 build.sh)就行了。 - Jérôme Pouiller

2
我用以下的shell脚本来实现此目的:
#!/bin/bash

for fld in $(find -name "CMakeLists.txt" -printf '%h ')
do
    for cmakefile in CMakeCache.txt cmake_install.cmake CTestTestfile.cmake CMakeFiles Makefile
    do
        rm -rfv $fld/$cmakefile
    done
done

如果你使用的是Windows系统,则可使用Cygwin来运行这个脚本。

2

清除cmake构建输出:

命令行:

$ rm -rf [folder that you builded the project]/
$ cmake --build .

Cmake:

cmake --build . --target clean

0
为了简化在“外部源代码”构建(即在build目录中构建)时进行清理,我使用以下脚本:
$ cat ~/bin/cmake-clean-build
#!/bin/bash

if [ -d ../build ]; then
    cd ..
    rm -rf build
    mkdir build
    cd build
else
    echo "build directory DOES NOT exist"
fi

每次需要清理时,您应该从build目录中获取此脚本的源代码:
. cmake-clean-build

安全又方便。如果你已经在文件管理器中打开了构建目录,我建议用cd .. ; rm -rf build/*替换cd .. ; rm ; mkdir ; cd序列。 - Mostafa Farzán

0

--新鲜(cmake版本3.24或更高)

可用于删除先前的缓存文件并重新创建构建树。


-1

如果你运行

cmake .

它将重新生成CMake文件。如果您向被*.cc选择的源文件夹添加新文件,则这是必需的。

虽然这不是一个完全的“清理”,但通过重新生成缓存,它确实可以“清理”CMake文件。


1
它不会清除编译状态:如果已经编译了1200个文件中的500个,在执行“cmake .”后,它将继续处理剩下的700个文件。 - Peter Mortensen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接