寻找一个'cmake clean'命令来清除CMake输出


419

正如make clean删除makefile产生的所有文件一样,我也想对CMake进行同样的操作。我经常会发现自己手动遍历目录,删除了cmake_install.cmakeCMakeCache.txtCMakeFiles文件以及文件夹。

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

Answers:


487

没有cmake clean

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

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


101
这被称为“超出源代码构建”,应该是首选方法。它避免了名称冲突之类的问题
-Arne

17
+1(针对源外版本)。当构建多个体系结构时,这一点至关重要。例如,您不能使用源内构建来构建64位和32位二进制文​​件,因为这需要两个单独的CMake缓存层次结构。
ComicSansMS 2012年

9
您可以将文件夹放置在所需的任何位置,但是通常将构建文件夹与根CMakeLists.txt放在同一目录中。要构建,只需将cmake的CMakeLists.txt位置作为参数即可。例如:cd <location-of-cmakelists>/build && cmake ..
ComicSansMS 2012年

64
确实应该干净整洁。曾经使用过cmake的每个人,即使他们习惯于不在源代码中进行构建,都无意中在错误的目录中运行了cmake,并且手动清理屁股是一个巨大的痛苦。
pavon,2015年

24
@DevSolar但是反过来是不正确的;仅仅因为文件不受版本控制并不意味着它是由cmake生成的并且可以安全删除。挑选出需要保留的未版本化文件以及正在处理的文件,这是一件很麻烦的事情,特别是当许多cmake文件被复制/以类似的方式命名到您的文件时。
pavon 2015年

84

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

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

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


最初,正如GNU autotools所介绍和使用的那样,“ distclean”目标旨在使源树准备好进行tar创建并创建tar分发。这样的tar文件用户可以下载并解压缩,然后运行“ configure”和“ make”,无需使用自动工具(aclocal,automake,autoconf等)。无需安装cmake即可构建的源。但是,当生成器是单目标生成器(如“ make”目标)时,这将不起作用,因为使用cmake进行配置的时间是
Carlo Wood

...运行cmake。进行无法配置的分发,甚至不进行平台测试等,都是没有用的。因此,不存在cmake的“ distclean”目标。最终用户的计算机上必须存在cmake 。
卡罗·伍德

63

在当今Git到处都是,您可能会忘记CMake并使用git clean -d -f -x,这将删除所有不在源代码控制下的文件。


14
-x虽然那个选择。那是git交易的绝招。虽然我个人还是做干先运行,git clean -d -f -x -n。我偶尔会在项目文件夹处于git受控状态的情况下保存用于项目的便捷文件,但这不是我想与其他人共享的内容,因此我不会git add在项目中共享它。如果我不小心添加一个-e <pattern>选项,这会把这种文件吹走。关于这一点,如果git有一个.gitcleanignore文件会很好。:)
CivFan 2015年

1
您可以尝试使用@CivFan chattr +i $filename(需要root权限,此后不允许修改文件)。这样,即使git尝试这样做,git也将无法删除该文件rm -f
Ruslan

3
前提是源代码内建,这是要自己避免的。
斯拉瓦

这是一个简单的解决方案(我不记得那些标志的含义,但这只是一个开发机器,哈哈)。
matanster

1
嗯,但是用户忘记了的新添加的文件git add呢?
yugr

50

我在Google上搜索了大约半小时,而我想到的唯一有用的方法是调用该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的生成您正在使用什么)之前这一点。

:)


36
如果您正在使用的目录受版本控制,我建议您不要使用此方法:当我使用svn尝试此方法时,它删除了一些存储库工作文件。
bcumming

8
可能还有其他与cmake匹配的文件,因此这实际上不是通用方法。这应该这样做:rm -rf CMakeFiles; rm -rf CMakeCache.txt; rm -rf cmake_install.cmake;
honza_p 2014年

1
我将删除-exec rm -rf {} \ +并仅使用-delete。
Edgar Aroutiounian

3
投票无效,因为此命令可能会删除一些用户文件。我确实喜欢honza_p命令,而不是更长,更简单,风险更低。
Adrien Descamps

1
@AdrienDescamps:除了它仍然在子目录中保留与cmake相关的垃圾。我在做rm -rf CMakeFiles ; rm -rf */CMakeFiles ; rm -rf */*/CMakeFiles ; rm -rf */*/*/CMakeFiles,但仍然没有做……
SF。

35

您可以使用类似:

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文件将在清除所有文件之前被擦除,并且make将在搜索“ CMakeFiles / clean-all.dir / build.make”时引发错误。因此,在任何上下文中的“任何内容”之前,您都不能使用clean-all命令:

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

那也不行。


有没有一种方法可以自动填充cmake_generation?也许,将其与yuri.makarevich的答案结合起来?当前,这不会删除$ {CMAKE_BINARY_DIR}子目录中的文件。
foxcub 2014年

不适用于Ninja或Visual Studio。我不推荐这种方法。
usr1234567

23

只是rm CMakeCache.txt为我发行作品。


1
我也只删除CMakeCache.txt中的相关变量。
约克战争'16

删除CMakeCache.txt,然后运行“ cmake --build / build-path”会导致“错误:无法加载缓存”。
nenchev

1
@nenchev,您需要cmake /build-path再次运行。
Samaursa

@Samaursa cmake --build在需要时重新运行cmake,此方法会中断构建目录,并引起cmake抱怨。我的答案进一步告诉您删除CMakeFiles /目录,这将导致干净的重建和cmake自动重新运行。
nenchev

2
@nenchev我明白你的意思,我同意。
Samaursa '17

9

也许这有点过时了,但是由于这是您在Google上搜索时的第一笔点击 cmake clean,因此我将添加以下内容:

由于您可以使用以下指定目标在构建目录中开始构建:

cmake --build . --target xyz

你当然可以跑

cmake --build . --target clean

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


8

我同意外包的构建是最好的答案。但是对于有时候您只需要进行源代码构建的时候,我在这里编写了一个Python脚本,该脚本:

  1. 运行“使干净”
  2. 删除顶级目录中特定的CMake生成的文件,例如CMakeCache.txt
  3. 对于每个包含CMakeFiles目录的子目录,它将删除CMakeFiles,Makefile和cmake_install.cmake。
  4. 删除所有空的子目录。

感谢那。我想在您的脚本中添加一行,以便在由于先前的清理而make没有任何内容Makefile的情况下(例如,使该脚本成为幂等)而静音。只需if os.path.isfile(os.path.join(directory,'Makefile')):在第24行之前添加以下行(适当间隔):就在刚添加的行之后args = [缩进函数主体的其余部分。make ... clean如果Makefile要清除的当前目录中存在a,则仅执行a 。否则,脚本是完美的!
Michael Goldshteyn

4

我最近发现的一个解决方案是将源代码外生成概念与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 all或调用此Makefile包装器make等效于:

mkdir build
cd build
cmake ..
make 

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

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

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

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

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

最后,在应收信贷的地方信贷。这个Makefile包装器是从C ++ Application Project Template提供的Makefile改编而来的。


4

当然,对于Unix Makefile,源代码外构建是首选方法,但是如果您正在使用其他生成器(例如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

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

4

尝试使用:cmake --clean-first-CMakeLists.txt文件的路径-B output-dir

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


该屏幕截图仅显示文本。但是,您对其进行了截屏,从而打破了任何配备屏幕阅读器的人的答案。请放下该图片,然后复制/粘贴文本,然后花1分钟时间正确格式化输入内容。
GhostCat

3

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

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

rm -rf CMakeFiles/
cmake --build .

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


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

好安全。由于您可能已在文件管理器中打开了构建目录,因此建议将cd .. ; rm ; mkdir ; cd序列替换为cd .. ; rm -rf build/*
MostafaFarzán19年

0

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

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

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


0

如果你跑

cmake .

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

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


它不清洁WRT。编译状态:如果已编译1200个文件中的500个,则在“ cmake”之后。它将继续处理最后700个文件。
彼得·莫滕森

0

为此,我使用以下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。


0

有趣的是,看到这个问题得到了如此多的关注和复杂的解决方案,这确实显示了使用cmake缺乏干净方法的痛苦。

好吧,您可以肯定cd build要做的工作,然后rm -rf *在需要清洁时进行处理。但是,rm -rf *鉴于许多人通常不知道他们所在的目录,这是一个危险的命令。

如果您是cd ..rm -rf build然后是mkdir build,那么cd build就是太多的输入。

因此,一个好的解决方案是不使用build文件夹,并告诉cmake路径:
配置:cmake -B build
build:cmake --build build
清理:rm -rf build
重新创建build文件夹:您甚至不需要mkdir build,只需配置它,cmake -B build然后cmake即可创建


0

cmake主要是一个厨师Makefile,一个可以添加rm清洁假

例如,

[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

-1

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

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

您应该将其用于源代码外的构建。假设您有一个build/为此目的而命名的目录。然后,您只需t-cmake-clean要从内部运行即可。


-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

-8

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

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

add_custom_target(clean-all
    rm -rf *
)

因此在编译时

cmake ..

并进行清洁:

make clean-all

11
如果有人意外构建源代码而不是源代码之外的方法,删除所有项目的好方法

3
是。此方法应仅与“源代码外生成”一起使用
Natesh 2015年

6
糟糕的建议。不应该作为答案存在。
安妮·范·罗苏姆

@AnnevanRossum同意
zevarito
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.