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

时间:2012-03-13 08:16:42

标签: cmake

就像make clean删除了makefile生成的所有文件一样,我想对CMake做同样的事情。我经常发现自己手动浏览目录,删除cmake_install.cmakeCMakeCache.txt以及CMakeFiles文件夹等文件。

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

22 个答案:

答案 0 :(得分:402)

没有cmake clean

我通常在像“build”这样的单个文件夹中构建项目。因此,如果我想make clean,我可以rm -rf build

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

答案 1 :(得分:70)

CMake official FAQ州:

  

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

     

“make distclean”目标只是   如果用户执行源内构建,则必需。 CMake支持   源内构建,但我们强烈建议用户采用这一概念   源外构建。使用与之分离的构建树   源树将阻止CMake生成任何文件   源树。因为CMake不会更改源树,所以有   不需要一个干净的目标。一个人可以开始新的建设   删除构建树或创建单独的构建树。

答案 2 :(得分:51)

我用谷歌搜索了半个小时,我想出的唯一有用的东西是调用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生成器)

:)

答案 3 :(得分:47)

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

答案 4 :(得分:29)

您可以使用以下内容:

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”时抛出错误。因此,您无法在任何上下文中的“任何”之前使用clean-all命令:

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

这也不起作用。

答案 5 :(得分:18)

简单地发布rm CMakeCache.txt也适用于我。

答案 6 :(得分:7)

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

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

答案 7 :(得分: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 -pbuild的变量。目录-p是我们执行源外构建的地方。我们提供参数mkdir以确保./build/Makefile不会因为尝试创建可能已存在的目录而尖叫。

目标build做的第二件事是将目录更改为cmake目录并调用all

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

总而言之,使用makemkdir build cd build cmake .. make 调用此Makefile包装器等同于:

distclean

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

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

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

P.S。在Makefile中,我们使用前缀@-来抑制shell命令的输出,使用前缀rm来忽略shell命令中的错误。当distclean作为rm -rf build目标的一部分使用时,如果文件不存在(可能已使用@-的命令行删除了它们,则该命令将返回错误,或者它们从来没有产生过。)此返回错误将强制我们的Makefile退出。我们使用前缀cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar"来防止这种情况发生。如果已经删除了文件,则可以接受;我们希望Makefile继续运行并删除其余部分。

需要注意的另一点是:如果使用可变数量的CMake变量来构建项目,则此Makefile可能无效,例如cmake ..。此Makefile假定您以一致的方式调用CMake,方法是键入cmake或提供{{1}}一致数量的参数(可以包含在Makefile中)。

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

答案 8 :(得分:3)

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

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

rm -rf CMakeFiles/
cmake --build .

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

答案 9 :(得分:3)

也许它有点过时了,但是因为这是谷歌cmake clean的第一次点击,我会添加:

由于您可以使用

在指定目标的构建目录中开始构建

cmake --build . --target xyz

你当然可以运行

cmake --build . --target clean

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

答案 10 :(得分:2)

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

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

如果您依次cd ..rm -rf build,然后依次mkdir buildcd build,那么输入的内容太多了。

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

答案 11 :(得分:2)

当然,对于Unix Makefile,源代码外构建是首选方法,但是如果您使用的是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

答案 12 :(得分:0)

这很老了,但是如果您完全删除了cmake-build-debug文件夹,则在使用cmake进行编译时,它会自动创建一个新的cmake-build-debug文件夹,其中包含您需要的所有内容。在CLion中效果特别好。

答案 13 :(得分:0)

B b; b.A::doSomething(); // calls A::doSomething() 通常会烹饪cmake,可以将Makefile添加到干净的电话中。

例如,

rm

答案 14 :(得分:0)

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

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

答案 15 :(得分:0)

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

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

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

答案 16 :(得分:0)

使用&#34;来源&#34;以简化清洁工作。构建(即你在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

答案 17 :(得分: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作为此脚本。

答案 18 :(得分:0)

如果你跑

cmake .

它将重新生成CMake文件。如果您将新文件添加到* .cc选择的源文件夹,则必须使用该文件。

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

答案 19 :(得分:-1)

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

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

您应该将用于源外构建。让我们假设您有一个名为build/的目录。然后你只需要在其中运行t-cmake-clean

答案 20 :(得分:-3)

我成功使用zsxwing's answer来解决以下问题:

我有源自多个主机(在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

答案 21 :(得分:-6)

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

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

add_custom_target(clean-all
    rm -rf *
)

因此在编译时

cmake ..

要清理干净:

make clean-all