How to Use CCache with CMake?
Solution 1
I personally have /usr/lib/ccache in my $PATH. This directory contains loads of symlinks for every possible name the compiler could be called from (like gcc and gcc-4.3), all pointing to ccache.
And I didn't even create the symlinks. That directory comes pre-filled when I install ccache on Debian.
Solution 2
As of CMAKE 3.4 you can do:
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
Solution 3
It is now possible to specify ccache as a launcher for compile commands and link commands (since cmake 2.8.0). That works for Makefile and Ninja generator. To do this, just set the following properties :
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache) # Less useful to do it for linking, see edit2
endif(CCACHE_FOUND)
It is also possible to set these properties only for specific directories or targets.
For Ninja, this is possible since version 3.4. For XCode, Craig Scott gives a workaround in his answer.
Edit : Thanks to uprego and Lekensteyn's comment, I edited the answer to check if ccache is available before using it as launcher and for which generators is it possible to use a compile launcher.
Edit2: @Emilio Cobos recommended to avoid doing that for the linking part as ccache doesn't improve linking speed and can mess with other types of cache like sccache
Solution 4
From CMake 3.1, it is possible to use ccache with the Xcode generator and Ninja is supported from CMake 3.4 onwards. Ninja will honour RULE_LAUNCH_COMPILE just like the Unix Makefiles generator (so @Babcool's answer gets you there for Ninja too), but getting ccache working for the Xcode generator takes a little more work. The following article explains the method in detail, focussing on a general implementation which works for all three CMake generators and making no assumptions about setting up ccache symlinks or the underlying compiler used (it still lets CMake decide the compiler):
https://crascit.com/2016/04/09/using-ccache-with-cmake/
The general gist of the article is as follows. The start of your CMakeLists.txt file should be set up something like this:
cmake_minimum_required(VERSION 2.8)
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
endif()
project(SomeProject)
get_property(RULE_LAUNCH_COMPILE GLOBAL PROPERTY RULE_LAUNCH_COMPILE)
if(RULE_LAUNCH_COMPILE AND CMAKE_GENERATOR STREQUAL "Xcode")
# Set up wrapper scripts
configure_file(launch-c.in launch-c)
configure_file(launch-cxx.in launch-cxx)
execute_process(COMMAND chmod a+rx
"${CMAKE_BINARY_DIR}/launch-c"
"${CMAKE_BINARY_DIR}/launch-cxx")
# Set Xcode project attributes to route compilation through our scripts
set(CMAKE_XCODE_ATTRIBUTE_CC "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_CXX "${CMAKE_BINARY_DIR}/launch-cxx")
set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_BINARY_DIR}/launch-c")
set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_BINARY_DIR}/launch-cxx")
endif()
The two script template files launch-c.in and launch-cxx.in look like this (they should be in the same directory as the CMakeLists.txt file):
launch-c.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "[email protected]"
launch-cxx.in:
#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "[email protected]"
The above uses RULE_LAUNCH_COMPILE alone for Unix Makefiles and Ninja, but for the Xcode generator it relies on help from CMake's CMAKE_XCODE_ATTRIBUTE_... variables support. The setting of the CC and CXX user-defined Xcode attributes to control the compiler command and LD and LDPLUSPLUS for the linker command is not, as far as I can tell, a documented feature of Xcode projects, but it does seem to work. If anyone can confirm it is officially supported by Apple, I'll update the linked article and this answer accordingly.
Solution 5
I didn't like to set a symlink from g++ to ccache. And CXX="ccache g++" didn't work for me as some cmake test case wanted to have just the compiler program without attributes.
So I used a small bash script instead:
#!/bin/bash
ccache g++ "[email protected]"
and saved it as an executable in /usr/bin/ccache-g++.
Then C configured cmake to use /usr/bin/ccache-g++ as C++ compiler.
This way it passes the cmake test cases and I feel more comfortable than having symlinks that I might forget about in 2 or 3 weeks and then maybe wonder if something doesn't work...
Related videos on Youtube
Comments
-
amit kumar 6 monthsI would like to do the following: If CCache is present in PATH, use "ccache g++" for compilation, else use g++. I tried writing a small my-cmake script containing
CC="ccache gcc" CXX="ccache g++" cmake $*but it does not seem to work (running make still does not use ccache; I checked this using CMAKE_VERBOSE_MAKEFILE on).
Update:
As per this link I tried changing my script to
cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*but cmake bails out complaining that a test failed on using the compiler ccache (which can be expected).
-
int3 about 13 yearsWhy don't you just symlink gcc to ccache? And if you're distributing this, I'd think that the user himself would have done the symlink if he had ccache installed and wanted it to be used.. -
amit kumar about 13 years@int3 Yes probably that would work (I was not aware that ccache has the compiler as an optional argument). However it would be cleaner to be more explicit.
-
-
Gui13 almost 12 yearsNote that this ccache path has to be placed before the path where your real compiler is in$PATHfor it to work. Something likeexport PATH = /usr/lib/ccache:$PATH -
cib over 8 years@Gui13: Better than updating the PATH would be to tell cmake explicitly where the gcc it should use is, e.g. cmake -DCMAKE_CXX_COMPILER=/usr/lib/ccache/bin/g++ -
1737973 over 7 yearsMany sites implicitly advice using doublequotes like in
find_program(CCACHE_FOUND "ccache"), I don't know which one is more portable, my mileage did perfectly fine without the need for the doublequotes. -
Lekensteyn about 7 yearsIt's worth noting that this currently only works for Makefile generators (as of cmake 3.3.2). See the manual page ofcmake-properties. -
cdunn2001 about 7 yearsAfterbrew install ccache, I have/usr/local/Cellar/ccache/3.2.1/libexec/. -
cdunn2001 over 5 yearsAnd-DCMAKE_CXX_COMPILER_LAUNCHER=ccache. These work beautifully! I do not know why cmake insists on findingclangfrom/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc(so the symlink trick does not work), rather than from$PATH, but your answer works anyway. -
Jörn Reimerdes almost 5 yearsI also needed theset(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}") set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")from the mentioned article. -
Craig Scott almost 5 yearsThanks for the reminder, I've updated the answer to include setting LD and LDPLUSPLUS. -
ilya b. over 4 yearsThis should be the best answer. No more messing with path variable and compiler symlinks!
-
purpleKarrot over 4 yearsIt is worth noting that this conflicts with the CTEST_USE_LAUNCHERS setting. Those properties are set here too: github.com/Kitware/CMake/blob/master/Modules/…
-
Chris Dodd almost 4 yearsI tried this, but it just gives me the error "ccache: error: Recursive invocation (the name of the ccache binary must be "ccache")". Looking at the verbose trace, it is trying to run "/usr/local/bin/ccache ccache /usr/bin/c++"... -
Alex over 3 yearsThanks I didn't know aboutupdate-ccache-symlinks, I was creatingc++link with a script for a project and it was working but not for another project (still don't know why, the link was fine),update-ccache-symlinkssolved. -
Trass3r over 3 yearsHow does it interact with RULE_LAUNCH_COMPILE? -
Craig Scott over 3 yearsccache does not support VS compilers, so you can't use it for that. There is a project called clcache which aims to provide the same functionality for VS, but I can't comment on how well it works. -
Hi-Angel about 3 yearsI think you may want to change the code to this one (except, remove text from inside ofendif()). The improvements are: 1. There's a configuration option to disable it, and 2. Turns out, colors disappear from GCC/Clang in Make backend when used this way. Theninjabackend works around it by adding-fdiagnostics-coloroption, so it's advisable to do so formakebackend too. -
hedayat 12 monthsThis one is the one always work; it works even if you are using a toolchain file and it specifies full path to the compiler (in which modifying system PATH doesn't help). Thanks!
-
Thuong Vo 7 monthsThis answer is very unclear. Where do you use this? in the configuration or the build stage? It's not the build stage, because -D isn't a valid option while building. The answer needs to add a full command at least.