How can I get CMake to make a custom script? - cmake

I have a project that has the following folder structure:
src/
|
|- foo/config.ini
|- bar/config.ini
|- tool/
| | - myscript.sh
| | - CMakeLists.txt
|- cpp/
|- main.cpp
|- baz.cpp
|- CMakeLists.txt
Basically, I want to
Have a custom target make foo-target
I want foo-target to depend on my executable built in cpp/main.cpp
I want foo-target to somehow configure myscript.sh
myscript.sh is configured so that it knows where to find foo/config.ini (something like having the absolute path to the ini)
myscript.sh is also configured so that it knows where to find the executable built in cpp/main.cpp
I have looked into:
add_custom_command
add_custom_target
configure_file
Exporting variables to the environment (via add custom command)
But I just can't figure out how to! And could use some help!
Maybe there are other CMake commands that could help or maybe I am trying something silly that I shouldn't do, any help is appreciated!
For CMake version 3.4 and above
Edit:
Here is an example for myscript.sh
#!/bin/sh
CONFIG_INI=#CONFIG_INI_ABS_PATH#
EXE_PATH=#EXE_ABS_PATH#
echo "Config path is $CONFIG_INI"
echo "Exe path is $EXE_PATH"
As for the CMakeLists.txt under tools
set (CONFIG_INI_ABS_PATH ${PROJECT_SOURCE_DIR}/foo/config.ini)
set (EXE_ABS_PATH ${PROJECT_SOURCE_DIR}/cpp/myExe)
# This works, but how can I make it depend on myExe
# And how can I configure it "on command" (i.e. make foo-target)
configure_file(myscript.sh myscript.sh
USE_SOURCE_PERMISSIONS
#ONLY
)
# Can't figure out how to use this one
add_custom_command(OUTPUT myscript.sh
# COMMAND use sed to modify the bash script? by cahcing all #*# to what I want?
)
add_custom_target(foo-target
DEPENDS myExe # I know that I need this to make my target depend on "myExe"
)

Pass options as arguments to scripts:
#!/bin/sh
config_ini=$1
exe_path=$2
echo "Config path is $config_ini"
echo "Exe path is $exe_path"
Use generator expression to get path to file of executable. Assuming your script does not generate anything, you could:
add_executable(my_exe ...)
find_program(SHELL sh REQUIRED)
add_custom_target(foo-target
COMMENT "Print two lines"
COMMAND
${SHELL}
${CMAKE_CURRENT_SOURCE_DIR}/script.sh
${CMAKE_CURRENT_SOURCE_DIR}/foo/config.ini
$<TARGET_FILE:my_exe>
DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/script.sh
${CMAKE_CURRENT_SOURCE_DIR}/foo/config.ini
$<TARGET_FILE:my_exe>
VERBATIM
)
Do not use make target_name. Prefer to use cmake --build build_dir --target target_name, so that when you switch to a lot times faster Ninja you will not have to change your scripts.

Related

CMake add_custom_command ('POST_BUILD') 'DEPENDS' option is ignored

I have a library and a test projects on CMake, and I'm using this directory structure with two (project) CMakeLists.txt:
/
|- CMakeLists.txt
|- include/libName
|- src/...
|
|- test/
|- CMakeLists.txt
|- src/...
The outer project list defines the library, like:
add_library(libName ${SRC} ${INCLUDE})
And adds 'test' as subdirectory:
add_subdirectory(test)
The test project list defines the executable and a test, like:
add_executable(NameTest ${SRC})
target_link_libraries(NameTest libName)
add_test(NAME NameTest COMMAND NameTest)
The problem
I'm trying to build and execute the test program when the library is built. If any test fails, I want the build of the library fail too.
This is what I have (inside the outer lists file):
add_custom_command(
TARGET libName
POST_BUILD
COMMAND CTEST_OUTPUT_ON_FAILURE=1 ctest
DEPENDS NameTest # <- This is driving me crazy!
)
This command ignores completely if the target 'NameTest' is built, if there is a file with that name, or if not. I can't notice any difference if the whole 'DEPENDS' option is removed.
I even modified like:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Bip! Bip! Bip!"
DEPENDS this_is_not_an_existent_file_nor_target
)
And the command is triggered anyway. I'm not very sure about if this is the option I need, so:
Why is this not working?
How can I achieve my real purpose?
Thank you.
Edit: ctest will execute every test (add_test), but the NameTest executable (yet listed) must be built before calling it! Now would be built after the library, but before the 'POST_BUILD' custom command. It fails, of course.
I want CMake realize NameTest is necessary for running that custom command.
Edit: I find useful the Angew's answer, so I accepted his answer and refined it a little bit:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target NameTest --config $<CONFIG>
COMMAND ${CMAKE_CTEST_COMMAND} -C $<CONFIG> --output-on-failure
)
Thank you!
1. Why is this not working?
Because you're mixing options from two distinct signatures of add_custom_command. DEPENDS comes from the form which is used to generate a file. TARGET and POST_BUILD are from the form which adds pre/post build commands to existing targets.
See the documentation of add_custom_command for more details on the two uses.
2. How can I achieve my real purpose?
I believe the following should do what you want to:
add_custom_command(
TARGET libName
POST_BUILD
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target NameTest --config $<CONFIG>
COMMAND CTEST_OUTPUT_ON_FAILURE=1 ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target test --config $<CONFIG>
)

cmake add_custom_target preserve directory

Imagine the following lines in a CMakeFiles.txt:
add_custom_target( target
cd bin
COMMAND echo "test" > README
)
make target will not work as expected, as it will not modify the file bin/README but rather the file ./README. I found out that, in order to make CMake modify bin/README, I have to write
COMMAND cd bin && echo "test" > README
which is time consuming and blows the CMakeLists up when used multiple times. I want a behavior that is much like the behaviour of shell scripts. How can I achieve this?
Use the WORKING_DIRECTORY directive:
add_custom_target( target
COMMAND echo "test" > README
WORKING_DIRECTORY bin
)
EDIT: Reversed COMMAND and WORKING_DIRECTORY order

.clang_complete and CMake?

I'm using CMake to genenerate my Makefile's however I cannot generate the .clang_complete using the standard
make CC='~/.vim/bin/cc_args.py gcc' CXX='~/.vim/bin/cc_args.py g++' -B
nothing gets generated...
the tree structure looks like so
Root
|
|_core
| |_src
| | |_main.cpp
| | |_CMakeLists.txt (1)
| |_inc
| |_CMakeLists.txt (2)
|
|_lib
| |_rtaudio
|
|_CMakeLists.txt (3)
CMakeLists.txt (1) file:
include_directories("${Dunkel_SOURCE_DIR}/core/inc")
include_directories("${Dunkel_SOURCE_DIR}/lib/")
link_directories("${Dunkel_SOURCE_DIR}/lib/rtaudio")
add_executable(Dunkel main.cpp)
target_link_libraries(Dunkel rtaudio)
CMakeLists.txt (2) file:
subdirs(src)
CMakeLists.txt (3) file:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(Dunkel)
SUBDIRS(core)
set(CMAKE_CXX_FLAGS "-g")
What am I doing wrong here?
Looks like contrary to make cmake doesn't expand tilde, hence it treats is as part of the path. To make it work as expected either use absolute path to the cc_args.py script or do two simple changes in the command:
Replace the tilde with $HOME.
Replace single quotes with double quotes.
After the changes your command should look like this:
CXX="$HOME/.vim/bin/cc_args.py g++" cmake ..
And it should work.
You should run (in your build directory)
CXX='~/.vim/bin/cc_args.py g++' cmake ..
and then run make as usual. Note that this will run the cc_args.py script every time you build the project with make, if you want to disable this, re-run cmake again.
The file .clang_complete will be created in the build directory, move it if needed.
See also Vim: Creating .clang_complete using CMake
It is important to use $HOME/.vim/bin/cc_args.py and not ~/.vim/bin/cc_args.py, because ~ might not get expanded when quoted.
Also, verify the presence of the python script with:
$ ls -l $HOME/.vim/bin/cc_args.py
-rwxr-xr-x 1 myself staff 2270 Sep 19 16:11 /home/myself/.vim/bin/cc_args.py
if not found, adjust the python script path as necessary.
Run make clean in the build dir.
As suggested by #xaizek, start with an empty build directory (assuming the build directory is a subdir of the source dir):
CXX="$HOME/.vim/bin/cc_args.py g++" cmake ..
followed by:
make
at this point, make will be building the project, but calling cc_args.py (which will call g++), instead of directly calling g++.
However this part for me is failing to work, and no .clang_complete file is created in the build directory or anywhere else.
In fact, there is no occurrence of "cc_args" in the generated CMakeCache.txt / Makefile, so I suspect CXX is not the correct variable name to pass to cmake.
When finished, copy .clang_complete to the parent dir.
Here is what worked for me
sudo chmod a+x $HOME/.vim/bin/cc_args.py
CXX="$HOME/.vim/bin/cc_args.py g++" sudo cmake ..
sudo make
and then ls -a shows my .clang_complete file but still emtyp though.

run a shell command (ctags) in cmake and make

I'm coding a c++ project in vim.
I'd like to run a ctags command (ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .) to generate references when I run make.
I think the way to do it is to use add_custom_command but I get confused on how to integrate it into CMakeLists.txt .
The most basic way to do this is:
set_source_files_properties( tags PROPERTIES GENERATED true)
add_custom_command ( OUTPUT tags
COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} )
add_executable ( MyProjectOutput tags )
The first line tells CMake that tags will be generated. The add_custom_command is CMake will generate tags when needed, and finally, some target needs to depend on tags. The default working directory is in the build tree, so WORKING_DIRECTORY must be set to your source tree. This is equivalent a Makefile entry:
tags:
ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
MyProjectOutput: tags
# Whatever here...
New solution:
I think CMake changed since the previous answer was given.
Here is the lines I added in my CMakeLists.txt (tested with version 2.8.12):
# Add "tags" target and make my_project depending on this target.
set_source_files_properties(tags PROPERTIES GENERATED true)
add_custom_target(tags
COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q .
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
add_dependencies(my_project tags)
And it works perfectly now!
Daniel's and Creak's answers got me started, but I ended up with a more complex solution that I thought I'd share:
# Add a top-level "tags" target which includes all files in both
# the build and source versions of src/*.
set_source_files_properties(tags PROPERTIES GENERATED true)
add_custom_target(tags
COMMAND ctags -R --c++-kinds=+p --fields=+iaS --extra=+q
${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ln -sf ${CMAKE_CURRENT_BINARY_DIR}/tags ${CMAKE_BINARY_DIR}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
# ...but only make it a dependency of the project if the ctags program
# is available, else it will fail to build on Windows.
find_program(CTAGS_PATH ctags)
if(CTAGS_PATH)
message(STATUS "Found ctags: ${CTAGS_PATH}")
add_dependencies(MyProjecct tags)
endif(CTAGS_PATH)
It does several things that the simpler solutions do not:
It only adds "tags" as a dependency of the primary build product (MyProject) if there is actually a ctags program on the system. We don't want to break the build just because this is Windows, or because ctags simply hasn't been installed yet on the build system.
It extracts symbols from source files in both the build and source directories. This matters in a couple of cases.
First, you might be using configure_file() and come from an Autotools background, so you've named your true source files *.in, which means ctags -R won't scan them. You need it to scan the generated versions in the build directory. For example, you might have src/mainheader.h.in in your source tree, with the project version number automatically subbed into it as build/src/mainheader.h.
Second, some of your "source" files might be generated by other tools. In my current project, I have a couple of C++ header files that are generated by Perl scripts. I want symbols from both the generated headers and the Perl scripts in the tags file.
It works in a subdirectory.
In the project I'm working on right now, the primary build product is made from src/* relative to the project root, and I only want symbols from that subtree in the tags file. I don't want it to include symbols from the unit tests, the examples, or the utility scripts.
Because it is designed to run in a subdirectory, it creates a symlink to the src/tags file in the top of the build directory, so that vi -t TagName works. (I'm assuming here that if ctags exists, ln does, too.)

Looking for a 'cmake clean' command to clear up CMake output

Just as make clean deletes all the files that a makefile has produced, I would like to do the same with CMake. All too often I find myself manually going through directories removing files like cmake_install.cmake and CMakeCache.txt, and the CMakeFiles folders.
Is there a command like cmake clean to remove all these files automatically? Ideally this should follow the recursive structure defined within the current directory's CMakeLists.txt file.
CMake 3.X
CMake 3.X offers a 'clean' target.
cmake --build C:/foo/build/ --target clean
From the CMake docs for 3.0.2:
--clean-first = Build target 'clean' first, then build.
(To clean only, use --target 'clean'.)
CMake 2.X
There is no cmake clean in CMake version 2.X
I usually build the project in a single folder like "build". So if I want to make clean, I can just rm -rf build.
The "build" folder in the same directory as the root "CMakeLists.txt" is usually a good choice. To build your project, you simply give cmake the location of the CMakeLists.txt as an argument. For example: cd <location-of-cmakelists>/build && cmake ... (From #ComicSansMS)
In these days of Git everywhere, you may forget CMake and use git clean -d -f -x, that will remove all files not under source control.
CMake official FAQ states:
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.
I googled it for like half an hour and the only useful thing I came up with was invoking the find utility:
# 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
Also, be sure to invoke make clean (or whatever CMake generator you're using) before that.
:)
You can use something like:
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)
I usually create a "make clean-all" command adding a call to "make clean" to the previous example:
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
Don't try to add the "clean" target as a dependence:
add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
DEPENDS clean
)
Because "clean" isn't a real target in CMake and this doesn't work.
Moreover, you should not use this "clean-cmake-files" as dependence of anything:
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
DEPENDS clean-cmake-files
)
Because, if you do that, all CMake files will be erased before clean-all is complete, and make will throw you an error searching "CMakeFiles/clean-all.dir/build.make". In consequence, you can not use the clean-all command before "anything" in any context:
add_custom_target(clean-all
COMMAND ${CMAKE_BUILD_TOOL} clean
COMMAND ${CMAKE_COMMAND} -P clean-all.cmake
)
That doesn't work either.
Simply issuing rm CMakeCache.txt works for me too.
Maybe it's a little outdated, but since this is the first hit when you google cmake clean, I will add this:
Since you can start a build in the build dir with a specified target with
cmake --build . --target xyz
you can of course run
cmake --build . --target clean
to run the clean target in the generated build files.
Starting with CMake 3.24, there exists the --fresh command line option which rebuilds the entire build tree every time:
--fresh
New in version 3.24.
Perform a fresh configuration of the build tree. This removes any
existing CMakeCache.txt file and associated CMakeFiles/ directory, and
recreates them from scratch.
https://cmake.org/cmake/help/latest/manual/cmake.1.html#options
I agree that the out-of-source build is the best answer. But for the times when you just must do an in-source build, I have written a Python script available here, which:
Runs "make clean"
Removes specific CMake-generated files in the top-level directory such as CMakeCache.txt
For each subdirectory that contains a CMakeFiles directory, it removes CMakeFiles, Makefile, cmake_install.cmake.
Removes all empty subdirectories.
It's funny to see this question gets so many attentions and complicated solutions, which indeed shows a pain to not have a clean method with cmake.
Well, you can definitely cd build_work to do you work, then do a rm -rf * when you need to clean. However, rm -rf * is a dangerous command given that many people are often not aware which dir they are in.
If you cd .., rm -rf build_work and then mkdir build_work and then cd build_work, that's just too much typing.
So a good solution is to just stay out of the build folder and tell cmake the path:
to configure: cmake -B build_work
to build: cmake --build build_work
to install: cmake --install build_work
to clean: rm -rf build_work
to recreate build folder: you don't even need mkdir build_work, just configure it with cmake -B build_work.
In the case where you pass -D parameters into CMake when generating the build files and don't want to delete the entire build/ directory:
Simply delete the CMakeFiles/ directory inside your build directory.
rm -rf CMakeFiles/
cmake --build .
This causes CMake to rerun, and build system files are regenerated. Your build will also start from scratch.
try to use:
cmake --clean-first path-of-CMakeLists.txt-file -B output-dir
--clean-first: Build target clean first, then build.
(To clean only, use --target clean.)
Of course, out-of-source builds are the go-to method for Unix Makefiles, but if you're using another generator such as Eclipse CDT, it prefers you to build in-source. In which case, you'll need to purge the CMake files manually. Try this:
find . -name 'CMakeCache.txt' -o -name '*.cmake' -o -name 'Makefile' -o -name 'CMakeFiles' -exec rm -rf {} +
Or if you've enabled globstar with shopt -s globstar, try this less disgusting approach instead:
rm -rf **/CMakeCache.txt **/*.cmake **/Makefile **/CMakeFiles
A solution that I found recently is to combine the out-of-source build concept with a Makefile wrapper.
In my top-level CMakeLists.txt file, I include the following to prevent in-source builds:
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()
Then, I create a top-level Makefile, and include the following:
# -----------------------------------------------------------------------------
# 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
The default target all is called by typing make, and invokes the target ./build/Makefile.
The first thing the target ./build/Makefile does is to create the build directory using $(MKDIR), which is a variable for mkdir -p. The directory build is where we will perform our out-of-source build. We provide the argument -p to ensure that mkdir does not scream at us for trying to create a directory that may already exist.
The second thing the target ./build/Makefile does is to change directories to the build directory and invoke cmake.
Back to the all target, we invoke $(MAKE) -C build, where $(MAKE) is a Makefile variable automatically generated for make. make -C changes the directory before doing anything. Therefore, using $(MAKE) -C build is equivalent to doing cd build; make.
To summarize, calling this Makefile wrapper with make all or make is equivalent to doing:
mkdir build
cd build
cmake ..
make
The target distclean invokes cmake .., then make -C build clean, and finally, removes all contents from the build directory. I believe this is exactly what you requested in your question.
The last piece of the Makefile evaluates if the user-provided target is or is not distclean. If not, it will change directories to build before invoking it. This is very powerful because the user can type, for example, make clean, and the Makefile will transform that into an equivalent of cd build; make clean.
In conclusion, this Makefile wrapper, in combination with a mandatory out-of-source build CMake configuration, make it so that the user never has to interact with the command cmake. This solution also provides an elegant method to remove all CMake output files from the build directory.
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.
Another thing to note: This Makefile may not work if you use a variable number of CMake variables to build your project, for example, cmake .. -DSOMEBUILDSUSETHIS:STRING="foo" -DSOMEOTHERBUILDSUSETHISTOO:STRING="bar". This Makefile assumes you invoke CMake in a consistent way, either by typing cmake .. or by providing cmake a consistent number of arguments (that you can include in your Makefile).
Finally, credit where credit is due. This Makefile wrapper was adapted from the Makefile provided by the C++ Application Project Template.
I use the following shell script for such purposes:
#!/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
If you are using Windows then use Cygwin for this script.
Clear the cmake build output:
Command line:
$ rm -rf [folder that you builded the project]/
$ cmake --build .
Cmake:
cmake --build . --target clean
To simplify cleaning when using "out of source" build (i.e. you build in the build directory), I use the following script:
$ 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
Every time you need to clean up, you should source this script from the build directory:
. cmake-clean-build
CMake 3.X
CMake 3.0 and above offers a 'clean' target. This removes any artifacts like object files, library files, executables, generated files, etc.
cmake --build C:/foo/build/ --target clean
You can also clean the build, then run the build. In 1 command.
cmake --build C:/foo/build --clean-first
However, this WON'T cleanup things like the CMakeCache.txt or the associated CMakeFiles/ directory. Which you may want to do. You just have to delete the build folder.
# 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
Now in CMake 3.24 you can perform a fresh configuration of the build tree. This removes any existing CMakeCache.txt file and associated CMakeFiles/ directory, and recreates them from scratch.
Generally you want to do this when:
You want to clear cached variable in CMakeCache.txt
You want to change compilers
Any other operations related to CMake caching
cmake -B C:/foo/build --fresh
If you run
cmake .
it will regenerate the CMake files. Which is necessary if you add a new file to a source folder that is selected by *.cc, for example.
While this isn't a "clean" per se, it does "clean" up the CMake files by regenerating the caches.
This is pretty old, but if you completely remove the cmake-build-debug folder, when you compile using cmake it should automatically create a new cmake-build-debug folder with everything you need. Works especially well in CLion.
If you have custom defines and want to save them before cleaning, run the following in your build directory:
sed -ne '/variable specified on the command line/{n;s/.*/-D \0 \\/;p}' CMakeCache.txt
Then create a new build directory (or remove the old build directory and recreate it) and finally run cmake with the arguments you'll get with the script above.
cmake mostly cooks a Makefile, one could add rm to the clean PHONY.
For example,
[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
Here is what I use. It's wrapped in a function, It's cross platform and it demonstrated how to find matching filenames or folder names, in case you wanted to make any easy adjustments. This function runs every time I build my scripts and has worked flawlessly for my needs.
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()
I used zsxwing's answer successfully to solve the following problem:
I have source that I build on multiple hosts (on a Raspberry Pi Linux board, on a VMware Linux virtual machine, etc.)
I have a Bash script that creates temporary directories based on the hostname of the machine like this:
# 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
Create a temporary build directory, for example, build_cmake. Hence all your build files will be inside this folder.
Then in your main CMake file add the below command.
add_custom_target(clean-all
rm -rf *
)
Hence while compiling do
cmake ..
And to clean do:
make clean-all