Patchwork [v2] Enable ccache for cmake packages

login
register
mail settings
Submitter Luca Ceresoli
Date March 22, 2013, 10:55 p.m.
Message ID <1363992947-21417-1-git-send-email-luca@lucaceresoli.net>
Download mbox | patch
Permalink /patch/230289/
State Changes Requested
Headers show

Comments

Luca Ceresoli - March 22, 2013, 10:55 p.m.
Use the *_ARG1 CMake variables to let CMake use ccache without failing
in detecting the compiler.

Implementation based on an idea suggested by Samuel Martin.

Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
---

NOTE! This patch is not yet well tested and may be largely non-optimal.
Commit with care!

It was a bit tricky to implement, because the CMake-generated Makefiles
do call cmake without supplying the same commandline arguments that we
passed to the top-level cmake invocation.
The solution that I implemented for this issue is to use a tristate
variable, named USE_CCACHE, that Buildroot passes to cmake:
 - if set to ON, it triggers the configuration for ccache to be saved
   in the CMake cache;
 - if set to OFF, it triggers the no-ccache configuration to be saved
   in the CMake cache;
 - if it is not set, this means cmake is not being called directly by
   Buildroot; in this case it does not set any of the compiler CMake
   variables, thus using those previously cached.

Changed in v2:
 - totally reimplemented based on Samuel's suggestion;
 - added dependency on host-ccache for cmake packages if ccache is
   enabled.

 package/pkg-cmake.mk |   26 ++++++++++++++++++++++++--
 1 file changed, 24 insertions(+), 2 deletions(-)
Samuel Martin - March 23, 2013, 12:03 a.m.
Hi Lucas,

2013/3/22 Luca Ceresoli <luca@lucaceresoli.net>:
> Use the *_ARG1 CMake variables to let CMake use ccache without failing
> in detecting the compiler.
>
> Implementation based on an idea suggested by Samuel Martin.
>
> Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
> ---
>
> NOTE! This patch is not yet well tested and may be largely non-optimal.
> Commit with care!
>
> It was a bit tricky to implement, because the CMake-generated Makefiles
> do call cmake without supplying the same commandline arguments that we
> passed to the top-level cmake invocation.
> The solution that I implemented for this issue is to use a tristate
> variable, named USE_CCACHE, that Buildroot passes to cmake:
>  - if set to ON, it triggers the configuration for ccache to be saved
>    in the CMake cache;
>  - if set to OFF, it triggers the no-ccache configuration to be saved
>    in the CMake cache;
>  - if it is not set, this means cmake is not being called directly by
>    Buildroot; in this case it does not set any of the compiler CMake
>    variables, thus using those previously cached.
>
> Changed in v2:
>  - totally reimplemented based on Samuel's suggestion;
>  - added dependency on host-ccache for cmake packages if ccache is
>    enabled.
>
>  package/pkg-cmake.mk |   26 ++++++++++++++++++++++++--
>  1 file changed, 24 insertions(+), 2 deletions(-)
>
> diff --git a/package/pkg-cmake.mk b/package/pkg-cmake.mk
> index b2fcd67..3d37502 100644
> --- a/package/pkg-cmake.mk
> +++ b/package/pkg-cmake.mk
> @@ -20,6 +20,13 @@
>  #
>  ################################################################################
>
> +# Options to CMake that are equal for all packages
> +ifeq ($(BR2_CCACHE),y)
> +CMAKE_EXTRA_OPT += -DUSE_CCACHE=ON
> +else
> +CMAKE_EXTRA_OPT += -DUSE_CCACHE=OFF
> +endif
> +
>  ################################################################################
>  # inner-cmake-package -- defines how the configuration, compilation and
>  # installation of a CMake package should be done, implements a few hooks to
> @@ -65,6 +72,7 @@ define $(2)_CONFIGURE_CMDS
>         $$($$(PKG)_CONF_ENV) $(HOST_DIR)/usr/bin/cmake $$($$(PKG)_SRCDIR) \
>                 -DCMAKE_TOOLCHAIN_FILE="$$(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake" \
>                 -DCMAKE_INSTALL_PREFIX="/usr" \
> +               $(CMAKE_EXTRA_OPT) \
Or the inlined if works as well ;)

>                 -DCMAKE_VERBOSE_MAKEFILE=ON \
Ahem... I think this belongs to some debug remains ;)

BTW, with CMake, to switch verbose log, just run: 'VERBOSE=1 make'
In Buildroot, 'make V=1' also works... because of some magics in the
Makefile in the topdir.


>                 $$($$(PKG)_CONF_OPT) \
>         )
> @@ -82,6 +90,7 @@ define $(2)_CONFIGURE_CMDS
>                 -DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY="BOTH" \
>                 -DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE="BOTH" \
>                 -DCMAKE_INSTALL_PREFIX="$$(HOST_DIR)/usr" \
> +               $(CMAKE_EXTRA_OPT) \
>                 $$($$(PKG)_CONF_OPT) \
>         )
>  endef
> @@ -94,6 +103,10 @@ $(2)_DEPENDENCIES ?= $(filter-out $(1),$(patsubst host-host-%,host-%,$(addprefix
>
>  $(2)_DEPENDENCIES += host-cmake
>
> +ifeq ($(BR2_CCACHE),y)
> +$(2)_DEPENDENCIES += host-ccache
> +endif
I don't think this is need since host-ccache is one of the first
target add to the list in the topdir Makefile.

> +
>  #
>  # Build step. Only define it if not already defined by the package .mk
>  # file.
> @@ -191,8 +204,17 @@ $(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake:
>         @mkdir -p $(@D)
>         @echo -en "\
>         set(CMAKE_SYSTEM_NAME Linux)\n\
> -       set(CMAKE_C_COMPILER $(TARGET_CC_NOCCACHE))\n\
> -       set(CMAKE_CXX_COMPILER $(TARGET_CXX_NOCCACHE))\n\
> +       if(DEFINED USE_CCACHE AND USE_CCACHE)\n\
> +               set(CMAKE_ASM_COMPILER $(TARGET_CC_NOCCACHE))\n\
I think it does not hurt to put the CMAKE_ASM_COMPILER definition
outside the if block...

> +               set(CMAKE_C_COMPILER $(CCACHE))\n\
> +               set(CMAKE_CXX_COMPILER $(CCACHE))\n\
> +               set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE) CACHE STRING \"\" FORCE)\n\
> +               set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE) CACHE STRING \"\" FORCE)\n\
> +       endif(DEFINED USE_CCACHE AND USE_CCACHE)\n\
> +       if(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
You can replace the 2 above lines by:
else ()

> +               set(CMAKE_C_COMPILER $(TARGET_CC_NOCCACHE))\n\
> +               set(CMAKE_CXX_COMPILER $(TARGET_CXX_NOCCACHE))\n\
> +       endif(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
>         set(CMAKE_C_FLAGS \"\$${CMAKE_C_FLAGS} $(TARGET_CFLAGS)\" CACHE STRING \"Buildroot CFLAGS\" FORCE)\n\
>         set(CMAKE_CXX_FLAGS \"\$${CMAKE_CXX_FLAGS} $(TARGET_CXXFLAGS)\" CACHE STRING \"Buildroot CXXFLAGS\" FORCE)\n\
>         set(CMAKE_INSTALL_SO_NO_EXE 0)\n\
> --
> 1.7.10.4
>

I have not tested this patch but something really close, nor done
extensive tests, but I expect it will works fine.


Regards,
Thomas Petazzoni - March 23, 2013, 3:29 p.m.
Dear Samuel Martin,

On Sat, 23 Mar 2013 01:03:09 +0100, Samuel Martin wrote:
> >  ################################################################################
> >  # inner-cmake-package -- defines how the configuration, compilation and
> >  # installation of a CMake package should be done, implements a few hooks to
> > @@ -65,6 +72,7 @@ define $(2)_CONFIGURE_CMDS
> >         $$($$(PKG)_CONF_ENV) $(HOST_DIR)/usr/bin/cmake $$($$(PKG)_SRCDIR) \
> >                 -DCMAKE_TOOLCHAIN_FILE="$$(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake" \
> >                 -DCMAKE_INSTALL_PREFIX="/usr" \
> > +               $(CMAKE_EXTRA_OPT) \
> Or the inlined if works as well ;)
> 
> >                 -DCMAKE_VERBOSE_MAKEFILE=ON \
> Ahem... I think this belongs to some debug remains ;)

But it hasn't been added by this patch from Luca.


> > +ifeq ($(BR2_CCACHE),y)
> > +$(2)_DEPENDENCIES += host-ccache
> > +endif
> I don't think this is need since host-ccache is one of the first
> target add to the list in the topdir Makefile.

Correct. 

> > +               set(CMAKE_C_COMPILER $(CCACHE))\n\
> > +               set(CMAKE_CXX_COMPILER $(CCACHE))\n\
> > +               set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE) CACHE STRING \"\" FORCE)\n\
> > +               set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE) CACHE STRING \"\" FORCE)\n\
> > +       endif(DEFINED USE_CCACHE AND USE_CCACHE)\n\
> > +       if(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
> You can replace the 2 above lines by:
> else ()

I don't think so. See the explanation in Luca's commit log. He needs to
differentiate three cases:

 * USE_CCACHE is defined and set to ON
 * USE_CCACHE is defined and set to OFF
 * USE_CCACHE is not defined

Luca, I think a portion of the message you've added below the '---'
should be added either in the commit log, or maybe as a comment in
pkg-cmake.mk.

Thanks,

Thomas
Samuel Martin - March 23, 2013, 5:32 p.m.
Hi Thomas, Lucas,

2013/3/23 Thomas Petazzoni <thomas.petazzoni@free-electrons.com>:
> Dear Samuel Martin,
>
> On Sat, 23 Mar 2013 01:03:09 +0100, Samuel Martin wrote:
>> >  ################################################################################
>> >  # inner-cmake-package -- defines how the configuration, compilation and
>> >  # installation of a CMake package should be done, implements a few hooks to
>> > @@ -65,6 +72,7 @@ define $(2)_CONFIGURE_CMDS
>> >         $$($$(PKG)_CONF_ENV) $(HOST_DIR)/usr/bin/cmake $$($$(PKG)_SRCDIR) \
>> >                 -DCMAKE_TOOLCHAIN_FILE="$$(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake" \
>> >                 -DCMAKE_INSTALL_PREFIX="/usr" \
>> > +               $(CMAKE_EXTRA_OPT) \
>> Or the inlined if works as well ;)
>>
>> >                 -DCMAKE_VERBOSE_MAKEFILE=ON \
>> Ahem... I think this belongs to some debug remains ;)
>
> But it hasn't been added by this patch from Luca.
Not this patch, but for sure, it's not on master ;)

>
>
>> > +ifeq ($(BR2_CCACHE),y)
>> > +$(2)_DEPENDENCIES += host-ccache
>> > +endif
>> I don't think this is need since host-ccache is one of the first
>> target add to the list in the topdir Makefile.
>
> Correct.
>
>> > +               set(CMAKE_C_COMPILER $(CCACHE))\n\
>> > +               set(CMAKE_CXX_COMPILER $(CCACHE))\n\
>> > +               set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE) CACHE STRING \"\" FORCE)\n\
>> > +               set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE) CACHE STRING \"\" FORCE)\n\
>> > +       endif(DEFINED USE_CCACHE AND USE_CCACHE)\n\
>> > +       if(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
>> You can replace the 2 above lines by:
>> else ()
>
> I don't think so. See the explanation in Luca's commit log. He needs to
> differentiate three cases:
>
>  * USE_CCACHE is defined and set to ON
>  * USE_CCACHE is defined and set to OFF
>  * USE_CCACHE is not defined

Well, I didn't really pay enough/that much attention to the tristate
thing because I didn't really get the point...
Now, I got it, but I'm really dubious about behavior in the last case.

I mean: the goal of this toolchainfile.cmake is, among other thing, to
be able to reuse the Buildroot toolchain
to build a projects outside Buildroot because CMake is good at this.

So, in that case, we want to be sure we correctly export the toolchain
properties.

If we don't set any compiler in the case USE_CCACHE is undefined, then
we totally miss this goal,
and IMHO, it does not make sense because the toolchainfile.cmake file
is generated by Buildroot,
for the Buildroot toolchain and nothing else.

Maybe the logic is a bit more complex... something like that:

set(FIND_PROGRAM_PATH "$(HOST_DIR)/usr/bin")
find_program(CCACHE "ccache")
if (DEFINED USE_CCACHE)
  if (USE_CCACHE AND CCACHE)
    # set the compiler variables with ccache support
  else ()
    # set the compiler variables without ccache support
  endif ()
else ()
  message("To enable ccache usage, add -DUSE_CACHE=ON on the command line")
  # fallback: set only the compiler variables (with no ccache support)
endif ()


Notes:
* The find_program call and CCACHE variable are here to check/ensure
the ccache binary existence.
* We only look for ccache in the Buildroot host bindir, ie. there is
no way to use the binary from the
system in the above example.


Regards,
Luca Ceresoli - March 28, 2013, 10:21 p.m.
Samuel Martin wrote:
> [...]
>>>>                  -DCMAKE_VERBOSE_MAKEFILE=ON \
>>> Ahem... I think this belongs to some debug remains ;)
>> But it hasn't been added by this patch from Luca.
> Not this patch, but for sure, it's not on master ;)

Sorry, my mistake! :)

[...]
>>>> +               set(CMAKE_C_COMPILER $(CCACHE))\n\
>>>> +               set(CMAKE_CXX_COMPILER $(CCACHE))\n\
>>>> +               set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE) CACHE STRING \"\" FORCE)\n\
>>>> +               set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE) CACHE STRING \"\" FORCE)\n\
>>>> +       endif(DEFINED USE_CCACHE AND USE_CCACHE)\n\
>>>> +       if(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
>>> You can replace the 2 above lines by:
>>> else ()
>> I don't think so. See the explanation in Luca's commit log. He needs to
>> differentiate three cases:
>>
>>   * USE_CCACHE is defined and set to ON
>>   * USE_CCACHE is defined and set to OFF
>>   * USE_CCACHE is not defined
> Well, I didn't really pay enough/that much attention to the tristate
> thing because I didn't really get the point...

If you add at the beginning of toolchainfile.cmake the line:
message("USE_CCACHE=${USE_CCACHE}")
and then run `make rpi-userland{-dirclean,}` you'll see:

> >>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Configuring
> (cd 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/ 
> && rm -f CMakeCache.txt && 
> /home/murray/devel/buildroot/output/host/usr/bin/cmake 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/ 
> -DCMAKE_TOOLCHAIN_FILE="/home/murray/devel/buildroot/output/host/usr/share/buildroot/toolchainfile.cmake" 
> -DCMAKE_INSTALL_PREFIX="/usr" -DUSE_CCACHE=ON -DVMCS_INSTALL_PREFIX=/usr )
> Re-run cmake no build system arguments
> USE_CCACHE=ON
> USE_CCACHE=ON
> -- The C compiler identification is GNU 4.7.3
> -- The CXX compiler identification is GNU 4.7.3
> -- Check for working C compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache
> USE_CCACHE=
> -- Check for working C compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
> -- Detecting C compiler ABI info
> USE_CCACHE=
> -- Detecting C compiler ABI info - done
> -- Check for working CXX compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache
> USE_CCACHE=
> -- Check for working CXX compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
> -- Detecting CXX compiler ABI info
> USE_CCACHE=
> -- Detecting CXX compiler ABI info - done
> USE_CCACHE=
> -- Looking for execinfo.h
> USE_CCACHE=
> -- Looking for execinfo.h - found
> -- The ASM compiler identification is GNU
> -- Found assembler: 
> /home/murray/devel/buildroot/output/host/usr/bin/arm-linux-gnueabihf-gcc

Apparently CMake interprets multiple times the toolchainfile.cmake,
and it does not always pass the original parameters, so USE_CCACHE is
sometimes undefined. Hence my idea to handle that variable as a
tristate.

> Now, I got it, but I'm really dubious about behavior in the last case.
>
> I mean: the goal of this toolchainfile.cmake is, among other thing, to
> be able to reuse the Buildroot toolchain
> to build a projects outside Buildroot because CMake is good at this.
>
> So, in that case, we want to be sure we correctly export the toolchain
> properties.
>
> If we don't set any compiler in the case USE_CCACHE is undefined, then
> we totally miss this goal,
> and IMHO, it does not make sense because the toolchainfile.cmake file
> is generated by Buildroot,
> for the Buildroot toolchain and nothing else.

I actually overlookedthe need to make the whole thing usable from
outside Buildroot. It should be made working indeed.

> Maybe the logic is a bit more complex... something like that:
>
> set(FIND_PROGRAM_PATH "$(HOST_DIR)/usr/bin")
> find_program(CCACHE "ccache")
> if (DEFINED USE_CCACHE)
>    if (USE_CCACHE AND CCACHE)
>      # set the compiler variables with ccache support
>    else ()
>      # set the compiler variables without ccache support
>    endif ()
> else ()
>    message("To enable ccache usage, add -DUSE_CACHE=ON on the command line")
>    # fallback: set only the compiler variables (with no ccache support)
> endif ()

I don't like very much automagic things, such as using a tool
transparently when it'sfound. We have a BR2_CCACHE config knob, that
should rule IMO.

Still, yours is an interesting proposal. The only alternative is
probably to put the ccachelogic in the wrappers as Thomas proposed in
reply to my v1 patch.

But I see a problem here: Buildroot exports BUILDROOT_CACHE_DIR, and
$(HOST_DIR)/usr/bin/ccacheuses that environment variable to locate its
cache directory. If the same ccache executable is executed standalone
it does won't find that environment variable and default to ~/.ccache.

Anyway, thinking more about how to implement this feature, I think
maybe Thomas' proposal can avoid the mentioned issues, as the call to
ccache (as well as the ccache directory path) can be coded inside a
(C?) wrapper if the wrapper has been built with BR2_CCACHE=y.
But we would need to regenerate the wrapper whenever the user changes
the BR2_CCACHE...

Also, the BR-built ccache would be used transparently even when
calling ${HOST_DIR}/usr/bin/*-gcc. This shows clearly an advantage,
although the user might not understand well that he's using ccache
under the hood (maybe not a problem).

But I'd like to understand better your idea, Thomas. The ccache
usage is independent from the toolchain type (Buildroot/ct-NG/
external).  Would you implement a unique wrapper to be used for
all three toolchain types, and replace the current
ext-toolchain-wrapper.c?

Luca
Samuel Martin - March 29, 2013, 1:08 p.m.
Hi Lucas, all,

2013/3/28 Luca Ceresoli <luca@lucaceresoli.net>:
[...]
> If you add at the beginning of toolchainfile.cmake the line:
> message("USE_CCACHE=${USE_CCACHE}")
> and then run `make rpi-userland{-dirclean,}` you'll see:
>
[...]
>
> Apparently CMake interprets multiple times the toolchainfile.cmake,
> and it does not always pass the original parameters, so USE_CCACHE is
> sometimes undefined. Hence my idea to handle that variable as a
> tristate.
>

I don't know that much about CMake innards, but i'm pretty sure, in
the end, it is what is set in the CMakeCache.txt file that is used.


>
>> Now, I got it, but I'm really dubious about behavior in the last case.
>>
>> I mean: the goal of this toolchainfile.cmake is, among other thing, to
>> be able to reuse the Buildroot toolchain
>> to build a projects outside Buildroot because CMake is good at this.
>>
>> So, in that case, we want to be sure we correctly export the toolchain
>> properties.
>>
>> If we don't set any compiler in the case USE_CCACHE is undefined, then
>> we totally miss this goal,
>> and IMHO, it does not make sense because the toolchainfile.cmake file
>> is generated by Buildroot,
>> for the Buildroot toolchain and nothing else.
>
>
> I actually overlookedthe need to make the whole thing usable from
> outside Buildroot. It should be made working indeed.
>
>
>> Maybe the logic is a bit more complex... something like that:
>>
>> set(FIND_PROGRAM_PATH "$(HOST_DIR)/usr/bin")
>> find_program(CCACHE "ccache")
>> if (DEFINED USE_CCACHE)
>>    if (USE_CCACHE AND CCACHE)
>>      # set the compiler variables with ccache support
>>    else ()
>>      # set the compiler variables without ccache support
>>    endif ()
>> else ()
>>    message("To enable ccache usage, add -DUSE_CACHE=ON on the command
>> line")
>>    # fallback: set only the compiler variables (with no ccache support)
>> endif ()
>
>
> I don't like very much automagic things, such as using a tool
> transparently when it'sfound. We have a BR2_CCACHE config knob, that
> should rule IMO.

An alternative, with no magics when used by Buildroot:

In the CONFIGURE_CMDS functions in pkg-cmake, add -DCCACHE="$(CCACHE)",
then, in the toolchainfile.cmake:

---
set(FIND_PROGRAM_PATH "$(HOST_DIR)/usr/bin")

if(DEFINED CCACHE) # check if run by buildroot.
  # Note that to make it very cristal and enforce this check, we can
use the following condition:
  # if(DEFINED CCACHE AND NOT "$ENV{BR2_VERSION}" STREQUAL "")
  #
  # Run inside buildroot
  if (DEFINED USE_CCACHE NOT "${CCACHE}" STREQUAL "")
    # set the compiler variables with ccache support
  else ()
    # set the compiler variables without ccache support
  endif ()
else ()
  # Run outside buildroot
  if (DEFINED USE_CCACHE)
    # ccache support is set
    if (USE_CCACHE)
      # ccache support is requested
      find_program(CCACHE "ccache")
      if(CCACHE)
        # ccache support is available
        # set the compiler variables with ccache support
      else ()
        # ccache support is not available
        message("No ccache binary found")
        # set the compiler variables without ccache support
      endif ()
    else ()
      # ccache support is explicitly disabled
      # set the compiler variables without ccache support
    endif ()
  else ()
    # ccache support is undefined
    message("To enable ccache usage, add -DUSE_CACHE=ON on the command line")
    # fallback: set only the compiler variables (with no ccache support)
  endif ()
endif ()
---

>
> Still, yours is an interesting proposal. The only alternative is
> probably to put the ccachelogic in the wrappers as Thomas proposed in
> reply to my v1 patch.
>
> But I see a problem here: Buildroot exports BUILDROOT_CACHE_DIR, and
> $(HOST_DIR)/usr/bin/ccacheuses that environment variable to locate its
> cache directory. If the same ccache executable is executed standalone
> it does won't find that environment variable and default to ~/.ccache.

Is that a problem to fallback on ~/.ccache when used outside Buildroot?

BTW, if you really want to reuse the Buildroot ccache directory, you can add:

---
if(DEFINED CCACHE_DIR)
  set(ENV{BUILDROOT_CACHE_DIR} "${CCACHE_DIR}")
else()
  message("Using the default ccache directory.")
  message("To use an alternative ccache directory, add
-DCCACHE_DIR=/path/to/somewhere")
endif()
---

>
> Anyway, thinking more about how to implement this feature, I think
> maybe Thomas' proposal can avoid the mentioned issues, as the call to
> ccache (as well as the ccache directory path) can be coded inside a
> (C?) wrapper if the wrapper has been built with BR2_CCACHE=y.
> But we would need to regenerate the wrapper whenever the user changes
> the BR2_CCACHE...
>
> Also, the BR-built ccache would be used transparently even when
> calling ${HOST_DIR}/usr/bin/*-gcc. This shows clearly an advantage,
> although the user might not understand well that he's using ccache
> under the hood (maybe not a problem).
>
> But I'd like to understand better your idea, Thomas.
Me too, though I'm not so fond of wrappers...

> The ccache
> usage is independent from the toolchain type (Buildroot/ct-NG/
> external).  Would you implement a unique wrapper to be used for
> all three toolchain types, and replace the current
> ext-toolchain-wrapper.c?
>
> Luca
>

Regards,

Patch

diff --git a/package/pkg-cmake.mk b/package/pkg-cmake.mk
index b2fcd67..3d37502 100644
--- a/package/pkg-cmake.mk
+++ b/package/pkg-cmake.mk
@@ -20,6 +20,13 @@ 
 #
 ################################################################################
 
+# Options to CMake that are equal for all packages
+ifeq ($(BR2_CCACHE),y)
+CMAKE_EXTRA_OPT += -DUSE_CCACHE=ON
+else
+CMAKE_EXTRA_OPT += -DUSE_CCACHE=OFF
+endif
+
 ################################################################################
 # inner-cmake-package -- defines how the configuration, compilation and
 # installation of a CMake package should be done, implements a few hooks to
@@ -65,6 +72,7 @@  define $(2)_CONFIGURE_CMDS
 	$$($$(PKG)_CONF_ENV) $(HOST_DIR)/usr/bin/cmake $$($$(PKG)_SRCDIR) \
 		-DCMAKE_TOOLCHAIN_FILE="$$(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake" \
 		-DCMAKE_INSTALL_PREFIX="/usr" \
+		$(CMAKE_EXTRA_OPT) \
 		-DCMAKE_VERBOSE_MAKEFILE=ON \
 		$$($$(PKG)_CONF_OPT) \
 	)
@@ -82,6 +90,7 @@  define $(2)_CONFIGURE_CMDS
 		-DCMAKE_FIND_ROOT_PATH_MODE_LIBRARY="BOTH" \
 		-DCMAKE_FIND_ROOT_PATH_MODE_INCLUDE="BOTH" \
 		-DCMAKE_INSTALL_PREFIX="$$(HOST_DIR)/usr" \
+		$(CMAKE_EXTRA_OPT) \
 		$$($$(PKG)_CONF_OPT) \
 	)
 endef
@@ -94,6 +103,10 @@  $(2)_DEPENDENCIES ?= $(filter-out $(1),$(patsubst host-host-%,host-%,$(addprefix
 
 $(2)_DEPENDENCIES += host-cmake
 
+ifeq ($(BR2_CCACHE),y)
+$(2)_DEPENDENCIES += host-ccache
+endif
+
 #
 # Build step. Only define it if not already defined by the package .mk
 # file.
@@ -191,8 +204,17 @@  $(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake:
 	@mkdir -p $(@D)
 	@echo -en "\
 	set(CMAKE_SYSTEM_NAME Linux)\n\
-	set(CMAKE_C_COMPILER $(TARGET_CC_NOCCACHE))\n\
-	set(CMAKE_CXX_COMPILER $(TARGET_CXX_NOCCACHE))\n\
+	if(DEFINED USE_CCACHE AND USE_CCACHE)\n\
+		set(CMAKE_ASM_COMPILER $(TARGET_CC_NOCCACHE))\n\
+		set(CMAKE_C_COMPILER $(CCACHE))\n\
+		set(CMAKE_CXX_COMPILER $(CCACHE))\n\
+		set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE) CACHE STRING \"\" FORCE)\n\
+		set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE) CACHE STRING \"\" FORCE)\n\
+	endif(DEFINED USE_CCACHE AND USE_CCACHE)\n\
+	if(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
+		set(CMAKE_C_COMPILER $(TARGET_CC_NOCCACHE))\n\
+		set(CMAKE_CXX_COMPILER $(TARGET_CXX_NOCCACHE))\n\
+	endif(DEFINED USE_CCACHE AND NOT USE_CCACHE)\n\
 	set(CMAKE_C_FLAGS \"\$${CMAKE_C_FLAGS} $(TARGET_CFLAGS)\" CACHE STRING \"Buildroot CFLAGS\" FORCE)\n\
 	set(CMAKE_CXX_FLAGS \"\$${CMAKE_CXX_FLAGS} $(TARGET_CXXFLAGS)\" CACHE STRING \"Buildroot CXXFLAGS\" FORCE)\n\
 	set(CMAKE_INSTALL_SO_NO_EXE 0)\n\