2012-03-13 405 views
259

就像make clean删除makefile生成的所有文件一样,我想用CMake来做同样的事情。我经常发现自己手动浏览目录,删除文件,如cmake_install.cmakeCMakeCache.txt,以及CMakeFiles文件夹。寻找'cmake clean'命令来清除cmake输出

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

回答

298

没有cmake clean

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

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

+70

这就是所谓的“出源码编译的”,应该去的首选方式。它避免了名称冲突和类似 – arne 2012-03-13 08:48:43

+12

+1外源构建。这在构建多种体系结构时变得至关重要。例如,不能使用源内版本构建64位和32位二进制文​​件,因为这需要两个独立的CMake缓存层次结构。 – ComicSansMS 2012-03-13 09:22:15

+0

听起来不错。你能提供一些关于这个文件夹通常相对于你的顶级CMakeLists的位置的更多细节,以及如何在CMake中指定构建位置? – 2012-03-13 09:38:00

43

我GOOGLE了它像一个半小时,我来到了被调用find实用的唯一有用的东西:

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

另外,一定要调用make clean(或任何cmake的你使用的发电机)之前那。

:)

+23

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

+0

可爱!我将在bashrc或bash_profile中为此创建一个别名。 @Yuri:对所有这些参数意味着什么添加一个小的解释是很好的。 – Nav 2013-03-10 08:59:10

+6

可能有其他文件匹配* cmake *,所以这实际上不是一种通用的方法。这应该这样做:rm -rf CMakeFiles; rm -rf CMakeCache.txt; rm -rf cmake_install.cmake; – 2014-12-19 17:57:39

6

我同意乱源的版本是最好的答案。但是当你只是必须做一个在代码构建的时候,我已经写了可用的Python脚本here,其中:

  1. 流程“使清洁”
  2. 删除在顶级具体的cmake生成的文件如CMakeCache.txt
  3. 对于包含CMakeFiles目录的每个子目录,它将删除CMakeFiles,Makefile和cmake_install.cmake。
  4. 删除所有空的子目录。
28

您可以使用类似:

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) 

我通常会创建一个“使干净all”命令添加到前面的例子中调用“使清洁”:

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中不是真正的目标,所以这是行不通的。 此外,你不应该使用这个“干净的cmake-文件”为任何依赖性:

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

因为,如果你这样做,所有cmake的文件将被前擦除干净,全部完成后,使意志抛出一个搜索“CMakeFiles/clean-all.dir/build.make”的错误。其结果是,你不能“东西”之前在任何情况下使用清洁-all命令:

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

这也不起作用。

+0

有没有办法自动填充cmake_generated?也许,结合这与yuri.makarevich的答案?目前,这不会删除$ {CMAKE_BINARY_DIR}的子目录中的文件。 – foxcub 2014-02-01 00:11:58

+0

不适用于忍者或Visual Studio。我不会推荐这种方法。 – usr1234567 2017-11-09 08:40:55

1

如果你运行这个:

cmake . 

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

虽然这不是一个“干净”的本身,它不通过重新生成缓存“干净”了cmake的文件。

希望有所帮助。

-3

我用从上方zsxwing响应成功地解决了以下问题:

我有建立在多个主机源(在覆盆子PI的Linux板,VMware的Linux虚拟机上,等)

我有一个基于机器的这样的主机名创建TMP目录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 tmp dir and build parent which 
#  is a way of making cmake tmp files stay 
#  out of the way. 
# 
# Note2: to clean up cmake files, it is OK to 
#  "rm -rf" the tmp dirs 

echo 
echo Creating Makefiles with cmake ... 

cd $TMP_DIR 

cmake .. 

# run makefile (in tmp dir) 

echo 
echo Starting build ... 

make 

希望这有助于有人...

13

只需发出rm CMakeCache.txt作品对我来说太。

+1

只删除CMakeCache.txt中的相关变量也适用于我。 – Yorkwar 2016-01-19 11:55:29

+0

删除CMakeCache.txt,然后运行'cmake --build/build-path'导致'错误:无法加载缓存'。 – nenchev 2017-10-28 21:57:45

+0

@nenchev你需要再次运行'cmake/build-path'。 – Samaursa 2017-10-29 19:56:34

36

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

+7

虽然'-x'选项。这是'git'交易的一个很好的窍门。虽然我个人还是先做一个干运行,'git clean -d -f -x -n'。每隔一段时间,我都会在'git'控制下的项目文件夹中保存一个便利文件,但这不是我想与其他人共享的内容,所以我不会将它添加到项目中。如果我不小心添加“-e ”选项,这会将该类文件移开。在那个笔记上,如果'git'有'.gitcleanignore'文件,那将会很好。 :) – CivFan 2015-10-15 22:45:50

+1

@CivFan你可以尝试使用'chattr + i $ filename'(需要root权限,不允许在此之后修改文件)。这样git将无法删除该文件,即使它试图像'rm -f'那样做。 – Ruslan 2015-10-18 14:26:18

+1

这假定源内构建,这是要避免它本身。 – Slava 2017-07-19 09:52:38

43

CMake official FAQ状态:

Some build trees created with GNU autotools have a "make distclean" target that cleans the build and also removes Makefiles and other parts of the generated build system. CMake does not generate a "make distclean" target because CMakeLists.txt files can run scripts and arbitrary commands; CMake has no way of tracking exactly which files are generated as part of running CMake. Providing a distclean target would give users the false impression that it would work as expected. (CMake does generate a "make clean" target to remove files generated by the compiler and linker.)

A "make distclean" target is only necessary if the user performs an in-source build. CMake supports in-source builds, but we strongly encourage users to adopt the notion of an out-of-source build. Using a build tree that is separate from the source tree will prevent CMake from generating any files in the source tree. Because CMake does not change the source tree, there is no need for a distclean target. One can start a fresh build by deleting the build tree or creating a separate build tree.

+2

感谢您解释*为什么*。 – Vorac 2016-02-02 21:27:24

-1

在许多情况下make rebuild_cache是非常有用的。它触发一个完整的配置运行,这将重建所有依赖于已更改变量的目标。

+0

这甚至不会重新运行路径查找和配置检查... – einpoklum 2018-02-27 11:33:28

-6

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

然后在主cmake的文件中添加下面的命令。

add_custom_target(clean-all 
rm -rf * 
) 

因此在编译时做

cmake .. 

和清洁做

make clean-all 
+9

好的方法来删除所有的项目,如果有人不小心将建立源内而不是源 – 2015-02-22 11:01:24

+3

是的。这种方法只能用于“源外建” – Natesh 2015-02-24 10:24:58

+3

糟糕的推荐。不应该以答案的形式存在。 – 2017-02-19 12:09:31

2

一个解决方案,我发现最近是乱源构建概念,一个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的变量)创建build目录。目录build是我们将执行我们的源代码构建的地方。我们所提供的参数-p确保mkdir不向我们喊着要努力创造可能已存在的目录。

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

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

总结,称这个Makefile的包装与make allmake相当于做:

mkdir build 
cd build 
cmake .. 
make 

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

最后一块的生成文件的评估,如果用户提供的目标是或不是distclean。如果没有,它会在调用目录之前将其更改为build。这是非常强大的,因为用户可以键入,例如,make clean,并生成文件将变换成cd build; make clean等效。

总之,这个Makefile包装,结合强制性外的源代码编译CMake的配置,让这个用户从来没有使用命令cmake互动。此解决方案还提供了一种优雅的方法,用于从build目录中删除所有CMake输出文件。

P.S.在Makefile中,我们使用前缀@抑制从shell命令的输出,并且前缀@-忽略从shell命令的错误。当使用rm作为distclean目标的一部分,如果不存在的文件的命令将返回一个错误(使用命令行与rm -rf build,他们可能已被删除已经,或者他们从来没有在第一时间产生的)。这个返回错误会强制我们的Makefile退出。我们使用前缀@-来防止这种情况发生。如果文件已被删除,这是可以接受的;我们希望我们的Makefile继续前进并删除剩下的部分。

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

最后,信贷,信贷到期。这个Makefile包装器是从C++ Application Project Template提供的Makefile改编的。如果您使用的是Windows,然后使用Cygwin这个脚本

#!/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 

+2

男人,这是如此不必要的复杂... – Slava 2017-07-19 09:54:18

0

我用这样的目的,这个shell脚本。

-1

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

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

你应该使用它的乱源建立。假设您有一个名为build/的目录用于此目的。那么你只需要在其中运行t-cmake-clean

1

在传递-D参数到cmake的生成生成文件时,并不愿意删除整个编译/目录下的情况。只需删除build目录中的CMakeFiles /目录即可。

rm -rf CMakeFiles/

cmake --build .

这将导致cmake的重新运行,并建立系统文件再生。你的构建也将从头开始。使用“出源”构建时(即您在build目录建立)

0

为了简化清洁,我使用下面的脚本

$ 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 

每当你需要清理的时候,你应该source这个脚本从build目录:

. cmake-clean-build