diff mbox

[4/5] Enable ccache for cmake packages

Message ID 1362590066-5448-5-git-send-email-luca@lucaceresoli.net
State Changes Requested
Headers show

Commit Message

Luca Ceresoli March 6, 2013, 5:14 p.m. UTC
CMake fails in detecting the compiler when ccache is used. Add a wrapper
script to make it happy.

Signed-off-by: Luca Ceresoli <luca@lucaceresoli.net>
---
 Makefile             |    2 +-
 package/pkg-cmake.mk |   31 +++++++++++++++++++++++++++++--
 2 files changed, 30 insertions(+), 3 deletions(-)

Comments

Thomas Petazzoni March 6, 2013, 6:59 p.m. UTC | #1
Dear Luca Ceresoli,

On Wed,  6 Mar 2013 18:14:25 +0100, Luca Ceresoli wrote:
> CMake fails in detecting the compiler when ccache is used. Add a wrapper
> script to make it happy.

This raises the question of whether we want to generalize this in some
way: should we be doing the ccache wrapper thing in a generic way, and
use it everywhere? Since we already have a wrapper for external
toolchain tools, does it really make sense to have a shell wrapper
around a C wrapper? Should we have a single C wrapper used in all cases
(internal, external, crosstool-ng), that handles everything?

I don't (yet) have a strong opinion on this, I just wanted to have a
more global reflection about wrappers, and avoid creating many
wrappers to solve different problems.

Best regards,

Thomas
Samuel Martin March 6, 2013, 7:02 p.m. UTC | #2
Hi Lucas,

2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
> CMake fails in detecting the compiler when ccache is used. Add a wrapper
> script to make it happy.

It is possible to do this without any wrapper, setting
CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
C-compiler, respectively to the C++-compiler.

BTW, note that we currently don't handle space in the paths at all;
hope that nobody triggers issues related to this ;)

Regards,
Peter Korsgaard March 6, 2013, 7:52 p.m. UTC | #3
>>>>> "Samuel" == Samuel Martin <s.martin49@gmail.com> writes:

 Samuel> Hi Lucas,
 Samuel> 2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
 >> CMake fails in detecting the compiler when ccache is used. Add a wrapper
 >> script to make it happy.

 Samuel> It is possible to do this without any wrapper, setting
 Samuel> CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
 Samuel> CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
 Samuel> C-compiler, respectively to the C++-compiler.

 Samuel> BTW, note that we currently don't handle space in the paths at all;
 Samuel> hope that nobody triggers issues related to this ;)

I bet a lot of (make based) build systems don't handle paths with spaces
either.
Peter Korsgaard March 10, 2013, 8:29 p.m. UTC | #4
>>>>> "Samuel" == Samuel Martin <s.martin49@gmail.com> writes:

 Samuel> Hi Lucas,
 Samuel> 2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
 >> CMake fails in detecting the compiler when ccache is used. Add a wrapper
 >> script to make it happy.

 Samuel> It is possible to do this without any wrapper, setting
 Samuel> CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
 Samuel> CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
 Samuel> C-compiler, respectively to the C++-compiler.

 Samuel> BTW, note that we currently don't handle space in the paths at all;
 Samuel> hope that nobody triggers issues related to this ;)

Luca, could you respin the patch to do this instead?
Luca Ceresoli March 12, 2013, 7:38 a.m. UTC | #5
Peter Korsgaard wrote:
>>>>>> "Samuel" == Samuel Martin <s.martin49@gmail.com> writes:
>   Samuel> Hi Lucas,
>   Samuel> 2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
>   >> CMake fails in detecting the compiler when ccache is used. Add a wrapper
>   >> script to make it happy.
>
>   Samuel> It is possible to do this without any wrapper, setting
>   Samuel> CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
>   Samuel> CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
>   Samuel> C-compiler, respectively to the C++-compiler.
>
>   Samuel> BTW, note that we currently don't handle space in the paths at all;
>   Samuel> hope that nobody triggers issues related to this ;)
>
> Luca, could you respin the patch to do this instead?
>

Sure, will do.

Luca
Arnout Vandecappelle March 12, 2013, 9:40 p.m. UTC | #6
On 03/06/13 19:59, Thomas Petazzoni wrote:
> Dear Luca Ceresoli,
>
> On Wed,  6 Mar 2013 18:14:25 +0100, Luca Ceresoli wrote:
>> CMake fails in detecting the compiler when ccache is used. Add a wrapper
>> script to make it happy.
>
> This raises the question of whether we want to generalize this in some
> way: should we be doing the ccache wrapper thing in a generic way, and
> use it everywhere? Since we already have a wrapper for external
> toolchain tools, does it really make sense to have a shell wrapper
> around a C wrapper? Should we have a single C wrapper used in all cases
> (internal, external, crosstool-ng), that handles everything?

  Yes, I would be very much in favour of that. It also solves the issue 
that some configure systems don't deal very well with a CC that contains 
spaces. And for external toolchains, it's nice that the actual options 
that are passed to the external toolchain are also visible to ccache.

  I see two issues however:

- How to deal with HOSTCC?

- How to deal with HOSTCC_NOCCACHE? (TARGET_CC_NOCCACHE can probably be 
removed)


  Anyway, for cmake the solution proposed by Samuel works even better.

  Regards,
  Arnout


> I don't (yet) have a strong opinion on this, I just wanted to have a
> more global reflection about wrappers, and avoid creating many
> wrappers to solve different problems.
>
> Best regards,
>
> Thomas
>
Luca Ceresoli March 20, 2013, 5:15 p.m. UTC | #7
Samuel Martin wrote:
 > Hi Lucas,
 >
 > 2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
 >> CMake fails in detecting the compiler when ccache is used. Add a wrapper
 >> script to make it happy.
 >
 > It is possible to do this without any wrapper, setting
 > CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
 > CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
 > C-compiler, respectively to the C++-compiler.

Do you meansomething like this?

  $(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\
+       set(CMAKE_C_COMPILER $(CCACHE))\n\
+       set(CMAKE_CXX_COMPILER $(CCACHE))\n\
+       set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE))\n\
+       set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE))\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\" F
         set(CMAKE_INSTALL_SO_NO_EXE 0)\n\
         set(CMAKE_PROGRAM_PATH \"$(HOST_DIR)/usr/bin\")\n\

This is undocumented in the official CMake manual, yet OpenWRT uses it,
so it looks like a serious thing. And it actually works, except it breaks
rpi-userland:


$ LANG= make V=1 rpi-userland{-dirclean,}
...
 >>> 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" -DVMCS_INSTALL_PREFIX=/usr )
Re-run cmake no build system arguments
-- The C compiler identification is GNU 4.7.3
-- The CXX compiler identification is GNU 4.7.3
...
 >>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Building
PATH="/home/murray/devel/buildroot/output/host/bin:/home/murray/devel/buildroot/output/host/usr/bin:/home/murray/devel/buildroot/output/host/usr/sbin/:/home/murray/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" 
PERLLIB="/home/murray/devel/buildroot/output/host/usr/lib/perl" 
/usr/bin/make -j8  -C 
/home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/
...
[  8%] [  8%] /home/murray/devel/buildroot/output/host/usr/bin/cmake -E 
cmake_progress_report 
/home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/CMakeFiles
/home/murray/devel/buildroot/output/host/usr/bin/ccache: invalid option 
-- 'D'
Usage:
     ccache [options]
     ccache compiler [compiler options]
     compiler [compiler options]          (via symbolic link)

Options:
     -c, --cleanup         delete old files and recalculate size counters
                           (normally not needed as this is done 
automatically)
     -C, --clear           clear the cache completely
     -F, --max-files=N     set maximum number of files in cache to N 
(use 0 for
                           no limit)
     -M, --max-size=SIZE   set maximum size of cache to SIZE (use 0 for no
                           limit; available suffixes: G, M and K; default
                           suffix: G)
     -s, --show-stats      show statistics summary
     -z, --zero-stats      zero statistics counters

     -h, --help            print this help text
     -V, --version         print version and copyright information

See also <http://ccache.samba.org>.
make[3]: *** 
[interface/khronos/CMakeFiles/khrn_client.dir/common/khrn_int_hash_asm.s.o] 
Error 1
...


I don't know if rpi-userland is doing something wrong or the _ARG1
implementation is unreliable. I'll investigate on that, but if you
have any clues they would be helpful. I am no CMake guru.

Luca
Luca Ceresoli March 21, 2013, 10:29 p.m. UTC | #8
Luca Ceresoli wrote:
> Samuel Martin wrote:
> > Hi Lucas,
> >
> > 2013/3/6 Luca Ceresoli <luca@lucaceresoli.net>:
> >> CMake fails in detecting the compiler when ccache is used. Add a 
> wrapper
> >> script to make it happy.
> >
> > It is possible to do this without any wrapper, setting
> > CMAKE_C_COMPILER and CMAKE_CXX_COMPILER to the ccache binary path, and
> > CMAKE_C_COMPILER_ARG1 and CMAKE_CXX_COMPILER_ARG1 to the actual
> > C-compiler, respectively to the C++-compiler.
>
> Do you meansomething like this?
>
>  $(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\
> +       set(CMAKE_C_COMPILER $(CCACHE))\n\
> +       set(CMAKE_CXX_COMPILER $(CCACHE))\n\
> +       set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE))\n\
> +       set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE))\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\" F
>         set(CMAKE_INSTALL_SO_NO_EXE 0)\n\
>         set(CMAKE_PROGRAM_PATH \"$(HOST_DIR)/usr/bin\")\n\
>
> This is undocumented in the official CMake manual, yet OpenWRT uses it,
> so it looks like a serious thing. And it actually works, except it breaks
> rpi-userland:
>
>
> $ LANG= make V=1 rpi-userland{-dirclean,}
> ...
> >>> 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" -DVMCS_INSTALL_PREFIX=/usr )
> Re-run cmake no build system arguments
> -- The C compiler identification is GNU 4.7.3
> -- The CXX compiler identification is GNU 4.7.3
> ...
> >>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Building
> PATH="/home/murray/devel/buildroot/output/host/bin:/home/murray/devel/buildroot/output/host/usr/bin:/home/murray/devel/buildroot/output/host/usr/sbin/:/home/murray/bin:/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games" 
> PERLLIB="/home/murray/devel/buildroot/output/host/usr/lib/perl" 
> /usr/bin/make -j8  -C 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/
> ...
> [  8%] [  8%] /home/murray/devel/buildroot/output/host/usr/bin/cmake 
> -E cmake_progress_report 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/CMakeFiles
> /home/murray/devel/buildroot/output/host/usr/bin/ccache: invalid 
> option -- 'D'
> Usage:
>     ccache [options]
>     ccache compiler [compiler options]
>     compiler [compiler options]          (via symbolic link)
>
> Options:
>     -c, --cleanup         delete old files and recalculate size counters
>                           (normally not needed as this is done 
> automatically)
>     -C, --clear           clear the cache completely
>     -F, --max-files=N     set maximum number of files in cache to N 
> (use 0 for
>                           no limit)
>     -M, --max-size=SIZE   set maximum size of cache to SIZE (use 0 for no
>                           limit; available suffixes: G, M and K; default
>                           suffix: G)
>     -s, --show-stats      show statistics summary
>     -z, --zero-stats      zero statistics counters
>
>     -h, --help            print this help text
>     -V, --version         print version and copyright information
>
> See also <http://ccache.samba.org>.
> make[3]: *** 
> [interface/khronos/CMakeFiles/khrn_client.dir/common/khrn_int_hash_asm.s.o] 
> Error 1
> ...

Oh, now I see, this happens when trying to assemble a .s file.
With -DCMAKE_VERBOSE_MAKEFILE=ON you can see it does the wrong thing:

> >>> 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" -DVMCS_INSTALL_PREFIX=/usr )
> Re-run cmake no build system arguments
> -- 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
> -- Check for working C compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
> -- Detecting C compiler ABI info
> -- Detecting C compiler ABI info - done
> -- Check for working CXX compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache
> -- Check for working CXX compiler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
> -- Detecting CXX compiler ABI info
> -- Detecting CXX compiler ABI info - done
> -- Looking for execinfo.h
> -- Looking for execinfo.h - found
> -- The ASM compiler identification is GNU
> -- Found assembler: 
> /home/murray/devel/buildroot/output/host/usr/bin/ccache
> CMake Warning at interface/usbdk/CMakeLists.txt:2 (message):
>   usbdk: using stubbed out hostreq, HDMI buttons and gestures code
>
>
> -- Configuring done
> -- Generating done
> -- Build files have been written to: 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108
> touch 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/.stamp_configured
> >>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Building
...
> [  1%] Building C object 
> interface/vcos/pthreads/CMakeFiles/vcos.dir/vcos_pthreads.c.o
> cd 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/vcos/pthreads 
> && /home/murray/devel/buildroot/output/host/usr/bin/ccache 
> /home/murray/devel/buildroot/output/host/usr/bin/arm-linux-gnueabihf-gcc 
> <blah blah>
...
>
> [ 17%] Building ASM object 
> interface/khronos/CMakeFiles/khrn_client.dir/common/khrn_int_hash_asm.s.o
> cd 
> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/khronos 
> && /home/murray/devel/buildroot/output/host/usr/bin/ccache 
> -DEGL_SERVER_DISPMANX -DHAVE_CMAKE_CONFIG <blah blah>

Note in the above line the assembler executable is missing.
Apparently CMake automagically set CMAKE_ASM_COMPILER equal to
CMAKE_C_COMPILER or so, but it looks like CMAKE_ASM_COMPILER_ARG1 is empty.

So I set CMAKE_ASM_COMPILER{,_ARG1}just like I did for C and CXX:

-       set(CMAKE_C_COMPILER $(TARGET_CC_NOCCACHE))\n\
-       set(CMAKE_CXX_COMPILER $(TARGET_CXX_NOCCACHE))\n\
+       set(CMAKE_ASM_COMPILER $(CCACHE))\n\
+       set(CMAKE_C_COMPILER $(CCACHE))\n\
+       set(CMAKE_CXX_COMPILER $(CCACHE))\n\
+       set(CMAKE_ASM_COMPILER_ARG1 $(TARGET_CC_NOCCACHE))\n\
+       set(CMAKE_C_COMPILER_ARG1 $(TARGET_CC_NOCCACHE))\n\
+       set(CMAKE_CXX_COMPILER_ARG1 $(TARGET_CXX_NOCCACHE))\n\

Now it compiles correctly but with two bad side effects.

First, when building without ccache, CMake detects /usr/bin/cc as the
(supposedly cross-) compiler, leading to an obvious link failure.
Ok, this can be worked around by generating a different
toolchainfile.cmake for the ccache and non-ccache cases, although it
is annoying.

Second, during both the staging install and the target install phases,
it complains saying:

 > Re-run cmake: build system dependency is missing
 > -- The ASM compiler identification is unknown
 > -- Found assembler: 
/home/murray/devel/buildroot/output/host/usr/bin/ccache
 > -- Warning: Did not find file Compiler/-ASM
 > CMake Warning at interface/usbdk/CMakeLists.txt:2 (message):
 >   usbdk: using stubbed out hostreq, HDMI buttons and gestures code
 >
 >
 > -- Configuring done
 > -- Generating done
 > -- Build files have been written to: 
/home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108

and recompiles the whole package again. These amount to three
compilations! And they are ccached separately, so the first compilation
actually takes an unreasonably long time. Well, during subsequent
compilations with a full ccache the time loss is not more than 15
seconds on a dual core i5, but this clearly shows something is not
working properly.

Samuel, your idea was certainly good, but I think CMake is thinking
too much instead of just doing what it should... the result is a mess
I have no time to dig into. I guess I'll stay with my stupid (but
working) shell wrappers for the moment. :-(

Luca
Samuel Martin March 22, 2013, 8:33 a.m. UTC | #9
Hi Lucas,

2013/3/21 Luca Ceresoli <luca@lucaceresoli.net>:
> Luca Ceresoli wrote:
[...]
> Oh, now I see, this happens when trying to assemble a .s file.
> With -DCMAKE_VERBOSE_MAKEFILE=ON you can see it does the wrong thing:
>
>> >>> 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" -DVMCS_INSTALL_PREFIX=/usr )
>> Re-run cmake no build system arguments
>> -- 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
>> -- Check for working C compiler:
>> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
>> -- Detecting C compiler ABI info
>> -- Detecting C compiler ABI info - done
>> -- Check for working CXX compiler:
>> /home/murray/devel/buildroot/output/host/usr/bin/ccache
>> -- Check for working CXX compiler:
>> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
>> -- Detecting CXX compiler ABI info
>> -- Detecting CXX compiler ABI info - done
>> -- Looking for execinfo.h
>> -- Looking for execinfo.h - found
>> -- The ASM compiler identification is GNU
>> -- Found assembler:
>> /home/murray/devel/buildroot/output/host/usr/bin/ccache
>> CMake Warning at interface/usbdk/CMakeLists.txt:2 (message):
>>   usbdk: using stubbed out hostreq, HDMI buttons and gestures code
>>
>>
>> -- Configuring done
>> -- Generating done
>> -- Build files have been written to:
>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108
>> touch
>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/.stamp_configured
>> >>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Building
>
> ...
>>
>> [  1%] Building C object
>> interface/vcos/pthreads/CMakeFiles/vcos.dir/vcos_pthreads.c.o
>> cd
>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/vcos/pthreads
>> && /home/murray/devel/buildroot/output/host/usr/bin/ccache
>> /home/murray/devel/buildroot/output/host/usr/bin/arm-linux-gnueabihf-gcc
>> <blah blah>
>
> ...
>>
>>
>> [ 17%] Building ASM object
>> interface/khronos/CMakeFiles/khrn_client.dir/common/khrn_int_hash_asm.s.o
>> cd
>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/khronos
>> && /home/murray/devel/buildroot/output/host/usr/bin/ccache
>> -DEGL_SERVER_DISPMANX -DHAVE_CMAKE_CONFIG <blah blah>
>
>
> Note in the above line the assembler executable is missing.
> Apparently CMake automagically set CMAKE_ASM_COMPILER equal to
> CMAKE_C_COMPILER or so, but it looks like CMAKE_ASM_COMPILER_ARG1 is empty.
>
> So I set CMAKE_ASM_COMPILER{,_ARG1}just like I did for C and CXX:
AFAIK, ccache only supports C, C++, Objective-C and Objective-C++.
So, I think, it is useless to set it for anything else.

BTW, I also use to set most of the binutils/gcc binaries in my CMake
toolchain files,
this includes setting the following variables:
CMAKE_{LINKER,AR,RANDLIB,NM,OBJCOPY,OBJDUMP,STRIP}.

So, IMHO, it is not stupid to set CMAKE_ASM_COMPILER as well, though I
never need it so far.

[...]
>
> Now it compiles correctly but with two bad side effects.
>
> First, when building without ccache, CMake detects /usr/bin/cc as the
> (supposedly cross-) compiler, leading to an obvious link failure.
> Ok, this can be worked around by generating a different
> toolchainfile.cmake for the ccache and non-ccache cases, although it
> is annoying.
Well, here I use to conditionnaly enable ccache if found using
something like this:

--
find_program(CCACHE "ccache")
if (CCACHE)
  message( STATUS "Using ccache")
endif(CCACHE)

if (CCACHE AND NOT FORCE_NO_CCACHE)
  set(CMAKE_C_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
  set(CMAKE_CXX_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
  set(CMAKE_C_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
  set(CMAKE_CXX_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
else(CCACHE AND NOT FORCE_NO_CCACHE)
  set(CMAKE_C_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
  set(CMAKE_CXX_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
endif(CCACHE AND NOT FORCE_NO_CCACHE)
--

But I have to check that find program will actually look in
${HOST_DIR}/usr/bin, not in the system...

About the /usr/bin/cc issue, I think it will vanish by correctly
handling the ccache presence;
if not, ccache seems to use a number of environment variables, so...
our salute might eventually be there ;)

>
> Second, during both the staging install and the target install phases,
> it complains saying:
>
>> Re-run cmake: build system dependency is missing
>> -- The ASM compiler identification is unknown
>> -- Found assembler:
>> /home/murray/devel/buildroot/output/host/usr/bin/ccache
>> -- Warning: Did not find file Compiler/-ASM
>> CMake Warning at interface/usbdk/CMakeLists.txt:2 (message):
>>   usbdk: using stubbed out hostreq, HDMI buttons and gestures code
>>
>>
>> -- Configuring done
>> -- Generating done
>> -- Build files have been written to:
>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108
hum... here I think it is because ccache with the assembler is
misleading CMake...

>
> and recompiles the whole package again. These amount to three
> compilations! And they are ccached separately, so the first compilation
> actually takes an unreasonably long time. Well, during subsequent
> compilations with a full ccache the time loss is not more than 15
> seconds on a dual core i5, but this clearly shows something is not
> working properly.
>
> Samuel, your idea was certainly good, but I think CMake is thinking
> too much instead of just doing what it should... the result is a mess
> I have no time to dig into. I guess I'll stay with my stupid (but
> working) shell wrappers for the moment. :-(

Ok, I'll try to find some time to play with the toolchainfile.cmake
generation reusing what you've already done.


Regards,
Luca Ceresoli March 22, 2013, 9:40 a.m. UTC | #10
Samuel Martin wrote:
> Hi Lucas,
>
> 2013/3/21 Luca Ceresoli <luca@lucaceresoli.net>:
>> Luca Ceresoli wrote:
> [...]
>> Oh, now I see, this happens when trying to assemble a .s file.
>> With -DCMAKE_VERBOSE_MAKEFILE=ON you can see it does the wrong thing:
>>
>>>>>> 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" -DVMCS_INSTALL_PREFIX=/usr )
>>> Re-run cmake no build system arguments
>>> -- 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
>>> -- Check for working C compiler:
>>> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
>>> -- Detecting C compiler ABI info
>>> -- Detecting C compiler ABI info - done
>>> -- Check for working CXX compiler:
>>> /home/murray/devel/buildroot/output/host/usr/bin/ccache
>>> -- Check for working CXX compiler:
>>> /home/murray/devel/buildroot/output/host/usr/bin/ccache -- works
>>> -- Detecting CXX compiler ABI info
>>> -- Detecting CXX compiler ABI info - done
>>> -- Looking for execinfo.h
>>> -- Looking for execinfo.h - found
>>> -- The ASM compiler identification is GNU
>>> -- Found assembler:
>>> /home/murray/devel/buildroot/output/host/usr/bin/ccache
>>> CMake Warning at interface/usbdk/CMakeLists.txt:2 (message):
>>>    usbdk: using stubbed out hostreq, HDMI buttons and gestures code
>>>
>>>
>>> -- Configuring done
>>> -- Generating done
>>> -- Build files have been written to:
>>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108
>>> touch
>>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/.stamp_configured
>>>>>> rpi-userland 5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108 Building
>> ...
>>> [  1%] Building C object
>>> interface/vcos/pthreads/CMakeFiles/vcos.dir/vcos_pthreads.c.o
>>> cd
>>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/vcos/pthreads
>>> && /home/murray/devel/buildroot/output/host/usr/bin/ccache
>>> /home/murray/devel/buildroot/output/host/usr/bin/arm-linux-gnueabihf-gcc
>>> <blah blah>
>> ...
>>>
>>> [ 17%] Building ASM object
>>> interface/khronos/CMakeFiles/khrn_client.dir/common/khrn_int_hash_asm.s.o
>>> cd
>>> /home/murray/devel/buildroot/output/build/rpi-userland-5e9a740a88a889dfc8a18bb1b00c17e5dd9d0108/interface/khronos
>>> && /home/murray/devel/buildroot/output/host/usr/bin/ccache
>>> -DEGL_SERVER_DISPMANX -DHAVE_CMAKE_CONFIG <blah blah>
>>
>> Note in the above line the assembler executable is missing.
>> Apparently CMake automagically set CMAKE_ASM_COMPILER equal to
>> CMAKE_C_COMPILER or so, but it looks like CMAKE_ASM_COMPILER_ARG1 is empty.
>>
>> So I set CMAKE_ASM_COMPILER{,_ARG1}just like I did for C and CXX:
> AFAIK, ccache only supports C, C++, Objective-C and Objective-C++.
> So, I think, it is useless to set it for anything else.

Ouch, right!
The fix is as easy as:
 >     set(CMAKE_ASM_COMPILER $(TARGET_CC_NOCCACHE))\n\

Now when ccache is enabled it all works OK.

> BTW, I also use to set most of the binutils/gcc binaries in my CMake
> toolchain files,
> this includes setting the following variables:
> CMAKE_{LINKER,AR,RANDLIB,NM,OBJCOPY,OBJDUMP,STRIP}.
>
> So, IMHO, it is not stupid to set CMAKE_ASM_COMPILER as well, though I
> never need it so far.
>
> [...]
>> Now it compiles correctly but with two bad side effects.
>>
>> First, when building without ccache, CMake detects /usr/bin/cc as the
>> (supposedly cross-) compiler, leading to an obvious link failure.
>> Ok, this can be worked around by generating a different
>> toolchainfile.cmake for the ccache and non-ccache cases, although it
>> is annoying.
> Well, here I use to conditionnaly enable ccache if found using
> something like this:
>
> --
> find_program(CCACHE "ccache")
> if (CCACHE)
>    message( STATUS "Using ccache")
> endif(CCACHE)
>
> if (CCACHE AND NOT FORCE_NO_CCACHE)
>    set(CMAKE_C_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>    set(CMAKE_CXX_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>    set(CMAKE_C_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>    set(CMAKE_CXX_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
> else(CCACHE AND NOT FORCE_NO_CCACHE)
>    set(CMAKE_C_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>    set(CMAKE_CXX_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
> endif(CCACHE AND NOT FORCE_NO_CCACHE)
> --

I'm not following you here. This would require patching the
CMakeLists.txt file for every CMake package, right?

If we want to solve this cleanly, it should be in the BR infrastructure.
I think we shouldgenerate the toolchainfile.cmakefile with a different
content for the two cases (ccache/no-ccache). But we also should generate
it unconditionally at every build, in case the user changes the BR2_CCACHE
setting.

Luca
Samuel Martin March 22, 2013, 10:08 a.m. UTC | #11
Lucas,

2013/3/22 Luca Ceresoli <luca@lucaceresoli.net>:
> Samuel Martin wrote:
>>
>> Hi Lucas,
>>
>> 2013/3/21 Luca Ceresoli <luca@lucaceresoli.net>:
[...]
>> AFAIK, ccache only supports C, C++, Objective-C and Objective-C++.
>> So, I think, it is useless to set it for anything else.
>
>
> Ouch, right!
> The fix is as easy as:
>>     set(CMAKE_ASM_COMPILER $(TARGET_CC_NOCCACHE))\n\
>
> Now when ccache is enabled it all works OK.
>
>
>> BTW, I also use to set most of the binutils/gcc binaries in my CMake
>> toolchain files,
>> this includes setting the following variables:
>> CMAKE_{LINKER,AR,RANDLIB,NM,OBJCOPY,OBJDUMP,STRIP}.
>>
>> So, IMHO, it is not stupid to set CMAKE_ASM_COMPILER as well, though I
>> never need it so far.
>>
>> [...]
>>>
>>> Now it compiles correctly but with two bad side effects.
>>>
>>> First, when building without ccache, CMake detects /usr/bin/cc as the
>>> (supposedly cross-) compiler, leading to an obvious link failure.
>>> Ok, this can be worked around by generating a different
>>> toolchainfile.cmake for the ccache and non-ccache cases, although it
>>> is annoying.
>>
>> Well, here I use to conditionnaly enable ccache if found using
>> something like this:
>>
>> --
>> find_program(CCACHE "ccache")
>> if (CCACHE)
>>    message( STATUS "Using ccache")
>> endif(CCACHE)
>>
>> if (CCACHE AND NOT FORCE_NO_CCACHE)
>>    set(CMAKE_C_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>>    set(CMAKE_CXX_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>>    set(CMAKE_C_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>>    set(CMAKE_CXX_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
>> else(CCACHE AND NOT FORCE_NO_CCACHE)
>>    set(CMAKE_C_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>>    set(CMAKE_CXX_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
>> endif(CCACHE AND NOT FORCE_NO_CCACHE)
>> --
>
>
> I'm not following you here. This would require patching the
> CMakeLists.txt file for every CMake package, right?
Nope, just the toolchainfile.cmake.
And when ccache is disabled, we can just force it by setting
FORCE_NO_CCACHE in the CMake infra.

>
> If we want to solve this cleanly, it should be in the BR infrastructure.
Agree

> I think we shouldgenerate the toolchainfile.cmakefile with a different
> content for the two cases (ccache/no-ccache). But we also should generate
> it unconditionally at every build, in case the user changes the BR2_CCACHE
> setting.
I'm not sure I follow you here...

If we are able to generate one toolchain.cmake file that handle both case
(even enabling/disabling ccache from one run to another), we don't need
anything else, nor regenerate the toolchainfile.cmake file at each build start.

Anyway, there are few things to check and test, I'll look into this. :)

Regards,
Luca Ceresoli March 22, 2013, 10:41 p.m. UTC | #12
Samuel Martin wrote:
> Lucas,
>
> 2013/3/22 Luca Ceresoli <luca@lucaceresoli.net>:
>> Samuel Martin wrote:
>>> Hi Lucas,
>>>
>>> 2013/3/21 Luca Ceresoli <luca@lucaceresoli.net>:
> [...]
>>> AFAIK, ccache only supports C, C++, Objective-C and Objective-C++.
>>> So, I think, it is useless to set it for anything else.
>>
>> Ouch, right!
>> The fix is as easy as:
>>>      set(CMAKE_ASM_COMPILER $(TARGET_CC_NOCCACHE))\n\
>> Now when ccache is enabled it all works OK.
>>
>>
>>> BTW, I also use to set most of the binutils/gcc binaries in my CMake
>>> toolchain files,
>>> this includes setting the following variables:
>>> CMAKE_{LINKER,AR,RANDLIB,NM,OBJCOPY,OBJDUMP,STRIP}.
>>>
>>> So, IMHO, it is not stupid to set CMAKE_ASM_COMPILER as well, though I
>>> never need it so far.
>>>
>>> [...]
>>>> Now it compiles correctly but with two bad side effects.
>>>>
>>>> First, when building without ccache, CMake detects /usr/bin/cc as the
>>>> (supposedly cross-) compiler, leading to an obvious link failure.
>>>> Ok, this can be worked around by generating a different
>>>> toolchainfile.cmake for the ccache and non-ccache cases, although it
>>>> is annoying.
>>> Well, here I use to conditionnaly enable ccache if found using
>>> something like this:
>>>
>>> --
>>> find_program(CCACHE "ccache")
>>> if (CCACHE)
>>>     message( STATUS "Using ccache")
>>> endif(CCACHE)
>>>
>>> if (CCACHE AND NOT FORCE_NO_CCACHE)
>>>     set(CMAKE_C_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>>>     set(CMAKE_CXX_COMPILER "${CCACHE}" CACHE FILEPATH "" FORCE)
>>>     set(CMAKE_C_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>>>     set(CMAKE_CXX_COMPILER_ARG1 "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
>>> else(CCACHE AND NOT FORCE_NO_CCACHE)
>>>     set(CMAKE_C_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-gcc")
>>>     set(CMAKE_CXX_COMPILER "${HOST_DIR}/usr/bin/${TARGET_TUPLE}-g++")
>>> endif(CCACHE AND NOT FORCE_NO_CCACHE)
>>> --
>>
>> I'm not following you here. This would require patching the
>> CMakeLists.txt file for every CMake package, right?
> Nope, just the toolchainfile.cmake.
> And when ccache is disabled, we can just force it by setting
> FORCE_NO_CCACHE in the CMake infra.

Ahh, now I got you idea! Thanks!

I worked on it, and although it was a bit tricky (probably because of my
limited experience with CMake) it seems to be working.
Even if it is not yet fully tested, I'm submitting a v2 patch now to let you
have a preliminary look at this work.

Luca
diff mbox

Patch

diff --git a/Makefile b/Makefile
index 1300725..f6d8494 100644
--- a/Makefile
+++ b/Makefile
@@ -387,7 +387,7 @@  $(TARGETS_ALL): __real_tgt_%: $(BASE_TARGETS) %
 dirs: $(TOOLCHAIN_DIR) $(BUILD_DIR) $(STAGING_DIR) $(TARGET_DIR) \
 	$(HOST_DIR) $(BINARIES_DIR) $(STAMP_DIR)
 
-$(BASE_TARGETS): dirs $(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake
+$(BASE_TARGETS): dirs $(CMAKE_PKG_DEPENDENCIES)
 
 $(BUILD_DIR)/buildroot-config/auto.conf: $(BUILDROOT_CONFIG)
 	$(MAKE) $(EXTRAMAKEARGS) HOSTCC="$(HOSTCC_NOCCACHE)" HOSTCXX="$(HOSTCXX_NOCCACHE)" silentoldconfig
diff --git a/package/pkg-cmake.mk b/package/pkg-cmake.mk
index 626a0b0..0a44cfe 100644
--- a/package/pkg-cmake.mk
+++ b/package/pkg-cmake.mk
@@ -183,6 +183,26 @@  cmake-package = $(call inner-cmake-package,$(call pkgname),$(call UPPERCASE,$(ca
 host-cmake-package = $(call inner-cmake-package,host-$(call pkgname),$(call UPPERCASE,host-$(call pkgname)),$(call UPPERCASE,$(call pkgname)),$(call pkgparentdir),host)
 
 ################################################################################
+# Generate wrappers for the compiler.
+# If CMAKE_C_COMPILER were set to $(TARGET_CC), which may contanin a ccache
+# prefix, CMake would fail to detect the compiler. Generate two simple wrappers
+# that make it believe it is calling the compiler directly.
+################################################################################
+
+CMAKE_CC_WRAPPER  = $(HOST_DIR)/usr/bin/cmake-cc-wrapper
+CMAKE_CXX_WRAPPER = $(HOST_DIR)/usr/bin/cmake-cxx-wrapper
+
+$(CMAKE_CC_WRAPPER):
+	echo "#!/bin/sh" >$@
+	echo "$(TARGET_CC)" '$$@' >>$@
+	chmod a+x $@
+
+$(CMAKE_CXX_WRAPPER):
+	echo "#!/bin/sh" >$@
+	echo "$(TARGET_CXX)" '$$@' >>$@
+	chmod a+x $@
+
+################################################################################
 # Generation of the CMake toolchain file
 ################################################################################
 
@@ -190,8 +210,8 @@  $(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\
+	set(CMAKE_C_COMPILER $(CMAKE_CC_WRAPPER))\n\
+	set(CMAKE_CXX_COMPILER $(CMAKE_CXX_WRAPPER))\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\
@@ -203,3 +223,10 @@  $(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake:
 	set(ENV{PKG_CONFIG_SYSROOT_DIR} \"$(STAGING_DIR)\")\n\
 	" > $@
 
+################################################################################
+# dependencies for the top-level Makefile
+################################################################################
+
+CMAKE_PKG_DEPENDENCIES = \
+	$(CMAKE_CC_WRAPPER) $(CMAKE_CXX_WRAPPER) \
+	$(HOST_DIR)/usr/share/buildroot/toolchainfile.cmake