530

就像make clean删除 makefile 生成的所有文件一样,我想对 CMake 做同样的事情。很多时候,我发现自己手动浏览了删除文件cmake_install.cmake和文件夹CMakeCache.txt的目录CMakeFiles

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

4

23 回答 23

599

CMake 3.X

CMake 3.X 提供了一个“干净”的目标。

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

来自 3.0.2 的 CMake 文档:

--clean-first  = Build target 'clean' first, then build.
                 (To clean only, use --target 'clean'.)

CMake 2.X

cmake cleanCMake 版本 2.X中没有

我通常将项目构建在单个文件夹中,例如“build”。所以如果我想make clean,我可以rm -rf build

与根“CMakeLists.txt”位于同一目录中的“build”文件夹通常是一个不错的选择。要构建您的项目,您只需将 CMakeLists.txt 的位置作为参数提供给 cmake。例如:cd <location-of-cmakelists>/build && cmake ..。(来自@ComicSansMS)

于 2012-03-13T08:23:38.630 回答
91

CMake 官方常见问题解答指出:

一些使用 GNU 自动工具创建的构建树有一个“make distclean”目标,用于清理构建并删除 Makefile 和生成的构建系统的其他部分。CMake 不会生成“make distclean”目标,因为 CMakeLists.txt 文件可以运行脚本和任意命令;CMake 无法准确跟踪作为运行 CMake 的一部分生成的文件。提供 distclean 目标会给用户一种错误的印象,即它会按预期工作。(CMake 确实会生成一个“make clean”目标来删除编译器和链接器生成的文件。)

仅当用户执行源内构建时,才需要“make distclean”目标。CMake 支持源内构建,但我们强烈鼓励用户采用源外构建的概念。使用与源代码树分离的构建树将阻止 CMake 在源代码树中生成任何文件。因为 CMake 不会更改源代码树,所以不需要 distclean 目标。可以通过删除构建树或创建单独的构建树来开始新的构建。

于 2014-09-16T14:21:00.023 回答
85

在 Git 无处不在的这些日子里,您可能会忘记 CMake 和 use git clean -d -f -x,这将删除所有不受源代码控制的文件。

于 2014-08-14T21:25:40.880 回答
59

我用谷歌搜索了半个小时,我想出的唯一有用的东西就是调用该find实用程序:

# Find and then delete all files under current directory (.) that:
#  1. contains "cmake" (case-&insensitive) in its path (wholename)
#  2. name is not CMakeLists.txt
find . -iwholename '*cmake*' -not -name CMakeLists.txt -delete

此外,请务必在此之前make clean调用(或您正在使用的任何 CMake 生成器)。

:)

于 2012-08-21T13:12:04.423 回答
39

你可以使用类似的东西:

add_custom_target(clean-cmake-files
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

// clean-all.cmake
set(cmake_generated ${CMAKE_BINARY_DIR}/CMakeCache.txt
                    ${CMAKE_BINARY_DIR}/cmake_install.cmake
                    ${CMAKE_BINARY_DIR}/Makefile
                    ${CMAKE_BINARY_DIR}/CMakeFiles
)

foreach(file ${cmake_generated})

  if (EXISTS ${file})
     file(REMOVE_RECURSE ${file})
  endif()

endforeach(file)

我通常会创建一个“make clean-all”命令,在前面的示例中添加对“make clean”的调用:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

不要尝试将“干净”目标添加为依赖项:

add_custom_target(clean-all
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
   DEPENDS clean
)

因为“干净”不是 CMake 中的真正目标,这不起作用。

此外,您不应将此“clean-cmake-files”用作任何依赖项:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   DEPENDS clean-cmake-files
)

因为,如果你这样做,所有 CMake 文件将在 clean-all 完成之前被删除,并且 make 会在搜索“CMakeFiles/clean-all.dir/build.make”时抛出错误。因此,在任何情况下,您都不能在“anything”之前使用 clean-all 命令:

add_custom_target(clean-all
   COMMAND ${CMAKE_BUILD_TOOL} clean
   COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)

那也行不通。

于 2012-12-05T00:08:56.580 回答
33

简单地为我发行rm CMakeCache.txt作品。

于 2014-06-22T14:53:05.857 回答
18

也许它有点过时了,但是由于这是您在 google 时的第一次点击cmake clean,我将添加以下内容:

由于您可以使用指定的目标在构建目录中启动构建

cmake --build . --target xyz

你当然可以跑

cmake --build . --target clean

clean在生成的构建文件中运行目标。

于 2018-06-11T09:18:09.117 回答
9

我同意外源构建是最好的答案。但是在您必须进行源代码构建的时候,我已经编写了一个可用的 Python 脚本here,它:

  1. 运行“清理”
  2. 删除顶层目录中特定的 CMake 生成的文件,例如 CMakeCache.txt
  3. 对于每个包含 CMakeFiles 目录的子目录,它会删除 CMakeFiles、Makefile、cmake_install.cmake。
  4. 删除所有空子目录。
于 2012-09-19T04:33:08.693 回答
5

我最近发现的一个解决方案是将外源构建概念与 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是使用 来创建build目录$(MKDIR),它是mkdir -p. 该目录build是我们将执行我们的源代码外构建的地方。我们提供参数-p以确保mkdir不会因为试图创建可能已经存在的目录而对我们大喊大叫。

目标所做的第二件事./build/Makefile是将目录更改为build目录并调用cmake.

回到all目标,我们调用$(MAKE) -C build,其中$(MAKE)是为 自动生成的 Makefile 变量makemake -C在做任何事情之前更改目录。因此,使用$(MAKE) -C build相当于做cd build; make

总而言之,用make allor调用这个 Makefile 包装器make相当于:

mkdir build
cd build
cmake ..
make 

目标distclean调用cmake .., 然后make -C build clean, 最后从build目录中删除所有内容。我相信这正是您在问题中所要求的。

Makefile 的最后一部分评估用户提供的目标是否是distcleanbuild如果没有,它将在调用它之前将目录更改为。这非常强大,因为用户可以键入,例如,make cleanMakefile 会将其转换为cd build; make clean.

总之,这个 Makefile 包装器与强制的源外构建 CMake 配置相结合,使用户永远不必与命令交互cmakebuild此解决方案还提供了一种从目录中删除所有 CMake 输出文件的优雅方法。

PS 在 Makefile 中,我们使用前缀@来抑制 shell 命令的输出,并使用前缀@-来忽略 shell 命令的错误。当rm作为distclean目标的一部分使用时,如果文件不存在,该命令将返回错误(它们可能已经使用带有 的命令行被删除rm -rf build,或者它们从一开始就没有生成)。这个返回错误将强制我们的 Makefile 退出。我们使用前缀@-来防止这种情况。如果文件已经被删除是可以接受的;我们希望我们的 Makefile 继续运行并删除其余部分。

另一件需要注意的事情:如果您使用可变数量的 CMake 变量来构建项目,则此 Makefile 可能不起作用,例如,cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar". 此 Makefile 假定您以一致的方式调用 CMake,通过键入cmake ..或提供cmake一致数量的参数(可以包含在 Makefile 中)。

最后,信用到期。这个 Makefile 包装器改编自C++ Application Project Template提供的 Makefile 。

于 2015-04-16T15:02:07.373 回答
5

如果您-D在生成构建文件时将参数传递到 CMake 并且不想删除整个 build/ 目录:

只需删除构建目录中的 CMakeFiles/ 目录即可。

rm -rf CMakeFiles/
cmake --build .

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

于 2017-10-28T21:56:11.510 回答
5

当然,源代码外构建是 Unix Makefiles 的首选方法,但如果您使用另一个生成器,例如 Eclipse CDT,它更喜欢您构建源代码。在这种情况下,您需要手动清除 CMake 文件。试试这个:

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

或者,如果您使用 启用了 globstar ,请shopt -s globstar尝试使用这种不那么恶心的方法:

rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles
于 2018-08-13T10:06:33.017 回答
5

尝试使用:cmake --clean-first path-of-CMakeLists.txt-file -B output-dir

--clean-first:先构建目标clean,然后再构建。
(仅清洁,使用 --target clean。)

于 2019-06-21T12:50:36.603 回答
5

有趣的是,这个问题得到了如此多的关注和复杂的解决方案,这确实表明没有使用 cmake 的干净方法很痛苦。

好吧,你绝对cd build_work可以做你的工作,然后rm -rf *在你需要清洁的时候做一个。但是,rm -rf *鉴于许多人通常不知道他们在哪个目录中,这是一个危险的命令。

如果你cd ..,rm -rf build_work然后mkdir build_work, 然后cd build_work, 那只是打字太多了。

所以一个好的解决方案是离开构建文件夹并告诉 cmake 路径:
配置:cmake -B build_work
构建:cmake --build build_work
安装:cmake --install build_work
清理:rm -rf build_work
重新创建构建文件夹:你甚至不需要mkdir build_work,只需配置它cmake -B build_work

于 2020-05-25T07:36:59.093 回答
3

我为此目的使用以下 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 编写此脚本。

于 2016-07-12T16:18:04.807 回答
1

为了简化使用“外源”构建(即在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
于 2018-01-19T16:52:32.707 回答
0

如果你跑

cmake .

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

虽然这本身不是“干净”的,但它确实通过重新生成缓存来“清理”CMake 文件。

于 2012-12-20T19:14:12.513 回答
0

如果您有自定义定义并希望在清理之前保存它们,请在构建目录中运行以下命令:

sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt

然后创建一个新的构建目录(或删除旧的构建目录并重新创建它),最后cmake使用上面脚本获得的参数运行。

于 2018-08-06T13:28:11.897 回答
0

cmake大多是做厨师的Makefile,一个可以rm加到干净的PHONY

例如,

[root@localhost hello]# ls
CMakeCache.txt  CMakeFiles  cmake_install.cmake  CMakeLists.txt  hello  Makefile  test
[root@localhost hello]# vi Makefile
clean:
        $(MAKE) -f CMakeFiles/Makefile2 clean
        rm   -rf   *.o   *~   .depend   .*.cmd   *.mod    *.ko   *.mod.c   .tmp_versions *.symvers *.d *.markers *.order   CMakeFiles  cmake_install.cmake  CMakeCache.txt  Makefile
于 2020-05-26T11:19:01.040 回答
0

这已经很老了,但是如果你完全删除 cmake-build-debug 文件夹,当你使用 cmake 编译时,它应该会自动创建一个新的 cmake-build-debug 文件夹,里面有你需要的一切。在 CLion 中效果特别好。

于 2020-10-13T01:35:13.433 回答
0

这是我使用的。它包含在一个函数中,它是跨平台的,它演示了如何查找匹配的文件名或文件夹名称,以防您想进行任何简单的调整。这个函数在我每次构建脚本时都会运行,并且可以完美地满足我的需求。

function(DELETE_CACHE)
    if(CMAKE_HOST_WIN32)
        execute_process(COMMAND cmd /c for /r %%i in (CMakeCache.*) do del "%%i" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
        execute_process(COMMAND cmd /c for /d /r %%i in (*CMakeFiles*) do rd /s /q "%%i" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
    else()
        execute_process(COMMAND find . -name "CMakeCache.*" -delete WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
        execute_process(COMMAND "rm -rf `find . -type d -name CMakeFiles`" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
    endif()
endfunction()
于 2021-12-03T06:43:43.377 回答
-1

我在我的 shell rc 文件 ( .bashrc, .zshrc) 中有这个:

t-cmake-clean() {
    local BUILD=$(basename $(pwd))
    cd ..
    rm -rf $BUILD
    mkdir $BUILD && cd $BUILD
}

您应该将它用于源外构建。假设您有一个build/为此目的命名的目录。然后你只需t-cmake-clean要从里面跑。

于 2017-01-13T11:17:35.727 回答
-3

我使用zsxwing的回答成功解决了以下问题:

我有在多个主机上构建的源代码(在 Raspberry Pi Linux 板上、在 VMware Linux 虚拟机上等)

我有一个 Bash 脚本,它根据机器的主机名创建临时目录,如下所示:

# Get hostname to use as part of directory names
HOST_NAME=`uname -n`

# Create a temporary directory for cmake files so they don't
# end up all mixed up with the source.

TMP_DIR="cmake.tmp.$HOSTNAME"

if [ ! -e $TMP_DIR ] ; then
  echo "Creating directory for cmake tmp files : $TMP_DIR"
  mkdir $TMP_DIR
else
  echo "Reusing cmake tmp dir : $TMP_DIR"
fi

# Create makefiles with CMake
#
# Note: switch to the temporary dir and build parent 
#       which is a way of making cmake tmp files stay
#       out of the way.
#
# Note 2: to clean up cmake files, it is OK to
#        "rm -rf" the temporary directories

echo
echo Creating Makefiles with cmake ...

cd $TMP_DIR

cmake ..

# Run makefile (in temporary directory)

echo
echo Starting build ...

make
于 2013-07-06T19:32:22.227 回答
-9

创建一个临时构建目录,例如build_cmake. 因此,您的所有构建文件都将位于此文件夹中。

然后在您的主 CMake 文件中添加以下命令。

add_custom_target(clean-all
    rm -rf *
)

因此在编译时做

cmake ..

并清洁:

make clean-all
于 2015-02-20T05:36:11.510 回答