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

正如make clean删除makefile生成的所有文件一样,我想对CMake做同样的事情。我经常发现自己手动地在目录中删除像cmake_install.cmakeCMakeCache.txt这样的文件,以及CMakeFiles文件夹。

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

611203 次浏览

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版本2中没有cmake clean。X

我通常在一个文件夹中构建项目,比如“build”。如果我想要make clean,我可以只需要rm -rf build

“build"与根目录相同的文件夹"CMakeLists.txt"通常是一个不错的选择。要构建你的项目,你只需要把CMakeLists.txt文件的位置作为参数给cmake。例如:cd <location-of-cmakelists>/build && cmake ..。(从@ComicSansMS)

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

:)

我同意外部构建是最好的答案。但是当你必须在源代码内构建的时候,我写了一个Python脚本在这里,它:

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

你可以这样使用:

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
)

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

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
)

这也不行。

如果你跑了

cmake .

它将重新生成CMake文件。如果您将一个新文件添加到由*选择的源文件夹中,这是必需的。比如Cc。

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

我使用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

简单地发布rm CMakeCache.txt对我也有用。

在Git无处不在的今天,你可能会忘记CMake而使用git clean -d -f -x,这将删除所有不在源代码控制下的文件。

# EYZ0状态:

一些用GNU autotools创建的构建树有一个&;make distclean&; 目标,该目标清除构建并删除makefile和其他 生成的构建系统的部分。CMake不会生成“make” distclean"因为CMakeLists.txt文件可以运行脚本和 任意命令;CMake没有办法精确地跟踪哪些文件 都是运行CMake时生成的。提供一个不明确的目标 会给用户一种错误的印象,以为它会像预期的那样工作。 (CMake会生成一个“make clean”;目标删除生成的文件 通过编译器和链接器)

A;make distclean"目标仅为 如果用户执行源内构建,则必须使用。CMake支持 内源构建,但是我们强烈鼓励用户采用这个概念 外部构建的。使用与。分离的构建树 源树将阻止CMake在 源树。因为CMake不改变源树,所以有 不需要明确的目标。可以通过。开始新的构建 删除构建树或创建一个单独的构建树

创建一个临时构建目录,例如,build_cmake。因此所有的构建文件都在这个文件夹中。

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

add_custom_target(clean-all
rm -rf *
)

因此,在编译时

cmake ..

和清洁做:

make clean-all

我最近发现的一个解决方案是将外部构建概念与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

通过键入make来调用默认目标all,并调用目标./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输出文件。

附注:在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++应用项目模板提供的Makefile。

为此,我使用以下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来执行此脚本。

在生成构建文件时,你将-D参数传递给CMake,并且不想删除整个构建/目录的情况下:

简单地删除构建目录中的CMakeFiles/目录。

rm -rf CMakeFiles/
cmake --build .

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

为了简化使用“源外”构建时的清理(即在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

也许这有点过时,但因为这是你谷歌cmake clean时的第一个热门,我将添加这个:

因为您可以使用指定的目标在生成目录中启动生成

# EYZ0

你当然可以跑

# EYZ0

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

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

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

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

当然,外部构建是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

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

.txt文件

——clean-first:先构建目标clean,然后构建 (只清洁,使用——target clean.)

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

好吧,你绝对可以cd build_work来做你的工作,然后在你需要打扫的时候做rm -rf *。然而,rm -rf *是一个危险的命令,因为许多人通常不知道他们在哪个目录中。

如果你输入cd ..rm -rf build_work,然后是mkdir build_work,然后是cd build_work,输入太多了。

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

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

这是一个非常旧的文件夹,但是如果你完全删除了cmake-build-debug文件夹,当你使用cmake编译时,它会自动创建一个新的cmake-build-debug文件夹,里面有你需要的所有东西。尤其适用于CLion。

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

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()

CMake 3.24开始,存在--fresh命令行选项,每次重新构建整个构建树:

# EYZ0

3.24新版功能。

执行构建树的新配置。这将删除任何 现有的CMakeCache.txt文件和关联的CMakeFiles/目录

https://cmake.org/cmake/help/latest/manual/cmake.1.html#options

清除cmake构建输出:

命令行:

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

Cmake:

cmake --build . --target clean

CMake 3。X

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

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

您还可以清理构建,然后运行构建。在1命令。

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中,你可以执行一个新的configuration构建树。这将删除任何现有的CMakeCache.txt文件和相关的CMakeFiles/目录,并从头开始重新创建它们。

一般情况下,你需要这样做:

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