Como usar o CCache com o CMake?

92

Eu gostaria de fazer o seguinte: Se CCache estiver presente no PATH, use "ccache g ++" para compilação, caso contrário, use g ++. Tentei escrever um pequeno script my-cmake contendo

    CC="ccache gcc" CXX="ccache g++" cmake $*

mas parece não funcionar (executar make ainda não usa ccache; verifiquei isso usando CMAKE_VERBOSE_MAKEFILE em).

Atualizar:

Por este link , tentei alterar meu script para

     cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*

mas o cmake se recupera reclamando que um teste falhou ao usar o compilador ccache (o que pode ser esperado).

amit
fonte
4
Por que você não faz um link simbólico gcc para ccache? E se você estiver distribuindo isso, eu acho que o próprio usuário teria feito o link simbólico se ele tivesse o ccache instalado e quisesse que fosse usado ..
int3
1
@ int3 Sim, provavelmente funcionaria (não sabia que o ccache tem o compilador como um argumento opcional). No entanto, seria mais claro ser mais explícito.
Amit

Respostas:

68

Eu pessoalmente tenho /usr/lib/ccacheno meu $PATH. Este diretório contém muitos links simbólicos para todos os nomes possíveis de onde o compilador pode ser chamado (como gcce gcc-4.3), todos apontando para ccache.

E eu nem mesmo criei os links simbólicos. Esse diretório vem pré-preenchido quando instalo o ccache no Debian.

Nicolás
fonte
11
Observe que esse caminho do ccache deve ser colocado antes do caminho onde o seu compilador real está $PATHpara que ele funcione. Algo comoexport PATH = /usr/lib/ccache:$PATH
Gui13
6
@ Gui13: Melhor do que atualizar o PATH seria informar ao cmake explicitamente onde está o gcc que ele deve usar, por exemplo, cmake -DCMAKE_CXX_COMPILER = / usr / lib / ccache / bin / g ++
cib
3
Depois brew install ccache, eu tenho /usr/local/Cellar/ccache/3.2.1/libexec/.
cdunn2001
98

A partir do CMAKE 3.4, você pode fazer:

-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
Jacob
fonte
1
E -DCMAKE_CXX_COMPILER_LAUNCHER=ccache. Estes funcionam lindamente! Não sei por que cmake insiste em encontrar clangde /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc(então o truque do link simbólico não funciona), em vez de de $PATH, mas sua resposta funciona mesmo assim.
cdunn2001
3
Esta deve ser a melhor resposta. Não há mais confusão com a variável de caminho e links simbólicos do compilador!
ilya b.
1
Eu tentei isso, mas me deu o erro "ccache: erro: invocação recursiva (o nome do binário ccache deve ser" ccache ")". Observando o rastreamento detalhado, ele está tentando executar "/ usr / local / bin / ccache ccache / usr / bin / c ++" ...
Chris Dodd
3
Como ele interage com RULE_LAUNCH_COMPILE?
Trass3r
98

Agora é possível especificar ccache como um iniciador para comandos de compilação e comandos de link (desde o cmake 2.8.0). Isso funciona para Makefile e gerador Ninja. Para fazer isso, basta definir as seguintes propriedades:

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)

Também é possível definir essas propriedades apenas para diretórios ou destinos específicos.

Para o Ninja, isso é possível desde a versão 3.4. Para o XCode, Craig Scott oferece uma solução alternativa em sua resposta.

Edit: Graças ao uprego e ao comentário de Lekensteyn, editei a resposta para verificar se o ccache está disponível antes de usá-lo como iniciador e para quais geradores é possível usar um iniciador de compilação.

Edit2: @Emilio Cobos recomendado para evitar fazer isso para a parte de vinculação, pois ccache não melhora a velocidade de vinculação e pode bagunçar com outros tipos de cache como o sccache

Babcool
fonte
Muitos sites aconselham implicitamente o uso de aspas duplas, como em find_program(CCACHE_FOUND "ccache"), não sei qual é mais portátil, minha milhagem funcionou perfeitamente sem a necessidade de aspas duplas.
1737973
5
É importante notar que isso atualmente só funciona para geradores de Makefile (a partir de cmake 3.3.2). Veja a página do manual de cmake-properties.
Lekensteyn
1
É importante notar que isso está em conflito com a configuração CTEST_USE_LAUNCHERS. Essas propriedades também são definidas aqui: github.com/Kitware/CMake/blob/master/Modules/…
purpleKarrot
Acho que você pode querer alterar o código para este (exceto, remover o texto de dentro deendif() ) . As melhorias são: 1. Há uma opção de configuração para desabilitá-lo e 2. Acontece que as cores desaparecem do GCC / Clang no back-end do Make quando usadas dessa forma. O ninjaback-end contorna isso adicionando uma -fdiagnostics-coloropção, portanto, é aconselhável fazer isso também para o makeback-end.
Hi-Angel,
9

A partir do CMake 3.1, é possível usar o ccache com o gerador Xcode e o Ninja é compatível com o CMake 3.4 em diante. Ninja vai honrarRULE_LAUNCH_COMPILE assim como o gerador de Makefiles do Unix (então a resposta de @Babcool leva você lá para o Ninja também), mas fazer o ccache funcionar para o gerador de Xcode dá um pouco mais de trabalho. O artigo a seguir explica o método em detalhes, focando em uma implementação geral que funciona para todos os três geradores CMake e não fazendo suposições sobre a configuração de links simbólicos ccache ou o compilador subjacente usado (ainda permite que o CMake decida o compilador):

https://crascit.com/2016/04/09/using-ccache-with-cmake/

A essência geral do artigo é a seguinte. O início do seu CMakeLists.txtarquivo deve ser configurado assim:

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()

Os arquivos de modelo de duas roteiro launch-c.ine launch-cxx.inolhar como este (que devem estar no mesmo diretório do CMakeLists.txtarquivo):

launch-c.in:

#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_C_COMPILER}" "$@"

launch-cxx.in:

#!/bin/sh
export CCACHE_CPP2=true
exec "${RULE_LAUNCH_COMPILE}" "${CMAKE_CXX_COMPILER}" "$@"

O acima usa RULE_LAUNCH_COMPILEsozinho para Makefiles Unix e Ninja, mas para o gerador de Xcode, ele depende da ajuda do CMAKE_XCODE_ATTRIBUTE_...suporte de variáveis do CMake . A configuração do CCe CXXdefinido pelo usuário Xcode atributos para controlar o comando do compilador e LDe LDPLUSPLUSpara o comando vinculador não é, tanto quanto eu posso dizer, uma característica documentada de projetos Xcode, mas parece ao trabalho. Se alguém puder confirmar que ele é oficialmente suportado pela Apple, atualizarei o artigo vinculado e esta resposta de acordo.

Craig Scott
fonte
Eu também precisava do set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}") set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")artigo mencionado.
Jörn Reimerdes de
Obrigado pelo lembrete, atualizei a resposta para incluir a configuração LD e LDPLUSPLUS.
Craig Scott
ccache não suporta compiladores VS, então você não pode usá-lo para isso. Existe um projeto chamado clcache que visa fornecer a mesma funcionalidade para o VS, mas não posso comentar como funciona bem.
Craig Scott
8

Não gostei de definir um link simbólico de g++para ccache. ECXX="ccache g++" não funcionou para mim, pois algum caso de teste cmake queria ter apenas o programa compilador sem atributos.

Então, usei um pequeno script bash:

#!/bin/bash
ccache g++ "$@"

e salvou-o como um executável em /usr/bin/ccache-g++.

Então C configurou o cmake para ser usado /usr/bin/ccache-g++como compilador C ++. Desta forma, ele passa nos casos de teste cmake e me sinto mais confortável do que ter links simbólicos que eu possa esquecer em 2 ou 3 semanas e então talvez me pergunte se algo não funciona ...

Jonas
fonte
6

Eu verifiquei os seguintes trabalhos (fonte: este link ):

        CC="gcc" CXX="g++" cmake -D CMAKE_CXX_COMPILER="ccache" -D CMAKE_CXX_COMPILER_ARG1="g++" -D CMAKE_C_COMPILER="ccache" -D CMAKE_C_COMPILER_ARG1="gcc" $*

Atualização : mais tarde percebi que mesmo isso não funciona. Estranhamente, funciona a cada vez (nas outras vezes, cmake reclama).

amit
fonte
5

Na minha opinião, a melhor maneira é fazer um link simbólico gcc, g ++ para ccache, mas se você gostaria de usar dentro do cmake, tente isto:

export CC="ccache gcc" CXX="ccache g++" cmake ...
Nadir SOUALEM
fonte
4

Deixe-me adicionar um item importante que não foi mencionado aqui antes.

Ao inicializar um sistema de compilação minimalista a partir da imagem docker ubunutu: 18.04, descobri que a ordem de instalação faz a diferença.

No meu caso, o ccache funcionou bem ao chamar gcc, mas falhou em capturar as invocações do mesmo compilador pelos outros nomes: cce c++. Para instalar completamente o ccache, você precisa ter certeza de que todos os compiladores estão instalados primeiro, ou adicionar uma chamada para update-ccache symlinks para ser seguro.

sudo apt-get install ccache build-essential # and everyhting ... sudo /usr/sbin/update-ccache-symlinks export PATH="/usr/lib/ccache/:$PATH"

... e então (devido aos links simbólicos atualizados) também as chamadas para cc e c ++ são detectadas!

Jürgen Weigert
fonte
Obrigado que não sabia update-ccache-symlinks, estava criando c++link com um script para um projeto e estava funcionando mas não para outro projeto (ainda não sei porque, o link estava bom), update-ccache-symlinksresolvido.
Alex