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

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


当前回答

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

其他回答

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

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

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

总而言之,使用make all或make调用这个Makefile包装器相当于这样做:

mkdir build
cd build
cmake ..
make 

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

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

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

P.S. In the Makefile, we use the prefix @ to suppress the output from a shell command, and the prefix @- to ignore errors from a shell command. When using rm as part of the distclean target, the command will return an error if the files do not exist (they may have been deleted already using the command line with rm -rf build, or they were never generated in the first place). This return error will force our Makefile to exit. We use the prefix @- to prevent that. It is acceptable if a file was removed already; we want our Makefile to keep going and remove the rest.

另一件需要注意的事情:如果你使用可变数量的CMake变量来构建项目,这个Makefile可能无法工作,例如,CMake ..-DSOMEBUILDSUSETHIS:字符串= " foo " -DSOMEOTHERBUILDSUSETHISTOO:字符串=“酒吧”。这个Makefile假设你以一致的方式调用CMake,或者输入CMake ..或者通过为cmake提供一致数量的参数(可以包含在Makefile中)。

最后,在该表扬的地方表扬。这个Makefile包装器改编自c++应用程序项目模板提供的Makefile。

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

有趣的是,这个问题得到了如此多的关注和复杂的解决方案,这确实表明了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即可。

为了简化使用“源外”构建时的清理(即在构建目录中构建),我使用以下脚本:

$ 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

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

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