就像make clean
删除 makefile 生成的所有文件一样,我想对 CMake 做同样的事情。很多时候,我发现自己手动浏览了删除文件cmake_install.cmake
和文件夹CMakeCache.txt
的目录CMakeFiles
。
是否有类似cmake clean
自动删除所有这些文件的命令?CMakeLists.txt
理想情况下,这应该遵循当前目录文件中定义的递归结构。
就像make clean
删除 makefile 生成的所有文件一样,我想对 CMake 做同样的事情。很多时候,我发现自己手动浏览了删除文件cmake_install.cmake
和文件夹CMakeCache.txt
的目录CMakeFiles
。
是否有类似cmake clean
自动删除所有这些文件的命令?CMakeLists.txt
理想情况下,这应该遵循当前目录文件中定义的递归结构。
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 clean
CMake 版本 2.X中没有
我通常将项目构建在单个文件夹中,例如“build”。所以如果我想make clean
,我可以rm -rf build
。
与根“CMakeLists.txt”位于同一目录中的“build”文件夹通常是一个不错的选择。要构建您的项目,您只需将 CMakeLists.txt 的位置作为参数提供给 cmake。例如:cd <location-of-cmakelists>/build && cmake ..
。(来自@ComicSansMS)
一些使用 GNU 自动工具创建的构建树有一个“make distclean”目标,用于清理构建并删除 Makefile 和生成的构建系统的其他部分。CMake 不会生成“make distclean”目标,因为 CMakeLists.txt 文件可以运行脚本和任意命令;CMake 无法准确跟踪作为运行 CMake 的一部分生成的文件。提供 distclean 目标会给用户一种错误的印象,即它会按预期工作。(CMake 确实会生成一个“make clean”目标来删除编译器和链接器生成的文件。)
仅当用户执行源内构建时,才需要“make distclean”目标。CMake 支持源内构建,但我们强烈鼓励用户采用源外构建的概念。使用与源代码树分离的构建树将阻止 CMake 在源代码树中生成任何文件。因为 CMake 不会更改源代码树,所以不需要 distclean 目标。可以通过删除构建树或创建单独的构建树来开始新的构建。
在 Git 无处不在的这些日子里,您可能会忘记 CMake 和 use git clean -d -f -x
,这将删除所有不受源代码控制的文件。
我用谷歌搜索了半个小时,我想出的唯一有用的东西就是调用该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 生成器)。
:)
你可以使用类似的东西:
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”时抛出错误。因此,在任何情况下,您都不能在“anything”之前使用 clean-all 命令:
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
那也行不通。
简单地为我发行rm CMakeCache.txt
作品。
也许它有点过时了,但是由于这是您在 google 时的第一次点击cmake clean
,我将添加以下内容:
由于您可以使用指定的目标在构建目录中启动构建
cmake --build . --target xyz
你当然可以跑
cmake --build . --target clean
clean
在生成的构建文件中运行目标。
我同意外源构建是最好的答案。但是在您必须进行源代码构建的时候,我已经编写了一个可用的 Python 脚本here,它:
我最近发现的一个解决方案是将外源构建概念与 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 变量make
。make -C
在做任何事情之前更改目录。因此,使用$(MAKE) -C build
相当于做cd build; make
。
总而言之,用make all
or调用这个 Makefile 包装器make
相当于:
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 输出文件的优雅方法。
PS 在 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++ Application Project Template提供的 Makefile 。
如果您-D
在生成构建文件时将参数传递到 CMake 并且不想删除整个 build/ 目录:
只需删除构建目录中的 CMakeFiles/ 目录即可。
rm -rf CMakeFiles/
cmake --build .
这会导致 CMake 重新运行,并重新生成构建系统文件。您的构建也将从头开始。
当然,源代码外构建是 Unix Makefiles 的首选方法,但如果您使用另一个生成器,例如 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
尝试使用:cmake --clean-first path-of-CMakeLists.txt-file -B output-dir
--clean-first:先构建目标clean,然后再构建。
(仅清洁,使用 --target clean。)
有趣的是,这个问题得到了如此多的关注和复杂的解决方案,这确实表明没有使用 cmake 的干净方法很痛苦。
好吧,你绝对cd build_work
可以做你的工作,然后rm -rf *
在你需要清洁的时候做一个。但是,rm -rf *
鉴于许多人通常不知道他们在哪个目录中,这是一个危险的命令。
如果你cd ..
,rm -rf build_work
然后mkdir build_work
, 然后cd build_work
, 那只是打字太多了。
所以一个好的解决方案是离开构建文件夹并告诉 cmake 路径:
配置:cmake -B build_work
构建:cmake --build build_work
安装:cmake --install build_work
清理:rm -rf build_work
重新创建构建文件夹:你甚至不需要mkdir build_work
,只需配置它cmake -B build_work
。
我为此目的使用以下 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 编写此脚本。
为了简化使用“外源”构建(即在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 .
它将重新生成 CMake 文件。例如,如果您将新文件添加到由 *.cc 选择的源文件夹,则这是必需的。
虽然这本身不是“干净”的,但它确实通过重新生成缓存来“清理”CMake 文件。
如果您有自定义定义并希望在清理之前保存它们,请在构建目录中运行以下命令:
sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt
然后创建一个新的构建目录(或删除旧的构建目录并重新创建它),最后cmake
使用上面脚本获得的参数运行。
cmake
大多是做厨师的Makefile
,一个可以rm
加到干净的PHONY。
例如,
[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()
我在我的 shell rc 文件 ( .bashrc
, .zshrc
) 中有这个:
t-cmake-clean() {
local BUILD=$(basename $(pwd))
cd ..
rm -rf $BUILD
mkdir $BUILD && cd $BUILD
}
您应该仅将它用于源外构建。假设您有一个build/
为此目的命名的目录。然后你只需t-cmake-clean
要从里面跑。
我使用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
创建一个临时构建目录,例如build_cmake
. 因此,您的所有构建文件都将位于此文件夹中。
然后在您的主 CMake 文件中添加以下命令。
add_custom_target(clean-all
rm -rf *
)
因此在编译时做
cmake ..
并清洁:
make clean-all