Jak używać CCache z CMake?

90

Chciałbym wykonać następujące czynności: Jeśli CCache jest obecny w PATH, użyj „ccache g ++” do kompilacji, w przeciwnym razie użyj g ++. Spróbowałem napisać mały skrypt my-cmake zawierający

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

ale wygląda na to, że nie działa (uruchomiona make nadal nie używa ccache; sprawdziłem to używając CMAKE_VERBOSE_MAKEFILE na).

Aktualizacja:

Zgodnie z tym linkiem próbowałem zmienić mój skrypt na

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

ale cmake rezygnuje z narzekania, że ​​test nie powiódł się przy użyciu pamięci podręcznej kompilatora (czego można się spodziewać).

dobrze
źródło
4
Dlaczego po prostu nie dowiązujesz symbolicznego gcc do pamięci podręcznej? A jeśli to rozprowadzasz, myślę, że sam użytkownik zrobiłby dowiązanie symboliczne, gdyby miał zainstalowaną
pamięć podręczną
1
@ int3 Tak, prawdopodobnie to zadziała (nie wiedziałem, że ccache ma kompilator jako opcjonalny argument). Byłoby jednak czystsze, gdyby było wyraźniejsze.
amit

Odpowiedzi:

67

Osobiście mam /usr/lib/ccachew swoim $PATH. Ten katalog zawiera mnóstwo dowiązań symbolicznych dla każdej możliwej nazwy, z której kompilator mógłby zostać wywołany (jak gcci gcc-4.3), wszystkie wskazujące na pamięć podręczną.

I nawet nie utworzyłem dowiązań symbolicznych. Ten katalog jest wstępnie wypełniony, kiedy instaluję ccache na Debianie.

Nicolás
źródło
11
Zauważ, że ta ścieżka pamięci podręcznej musi być umieszczona przed ścieżką, w której znajduje się twój prawdziwy kompilator $PATH, aby działał. Coś w styluexport PATH = /usr/lib/ccache:$PATH
Gui13,
6
@ Gui13: Lepszym rozwiązaniem niż aktualizacja PATH byłoby wyraźne poinformowanie cmake, gdzie powinien znajdować się gcc, np. Cmake -DCMAKE_CXX_COMPILER = / usr / lib / ccache / bin / g ++
cib
3
Później brew install ccachemam /usr/local/Cellar/ccache/3.2.1/libexec/.
cdunn2001
96

Możliwe jest teraz określenie ccache jako programu uruchamiającego dla poleceń kompilacji i poleceń linkowania (od cmake 2.8.0). To działa dla Makefile i generatora Ninja. Aby to zrobić, wystarczy ustawić następujące właściwości:

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)

Możliwe jest również ustawienie tych właściwości tylko dla określonych katalogów lub celów.

W przypadku Ninja jest to możliwe od wersji 3.4. W przypadku XCode Craig Scott podaje obejście w swojej odpowiedzi.

Edycja: Dzięki komentarzowi uprego i Lekensteyn zredagowałem odpowiedź, aby sprawdzić, czy pamięć podręczna jest dostępna przed użyciem jej jako programu uruchamiającego i dla których generatorów można użyć programu uruchamiającego kompilację.

Edit2: @Emilio Cobos zaleca unikanie robienia tego w części łączącej, ponieważ pamięć podręczna nie poprawia szybkości łączenia i może zepsuć inne typy pamięci podręcznej, takie jak sccache

Babcool
źródło
Wiele witryn pośrednio radzi, używając podwójnych cudzysłowów, jak w find_program(CCACHE_FOUND "ccache"), nie wiem, który z nich jest bardziej przenośny, mój przebieg wypadł doskonale bez potrzeby podwójnych cudzysłowów.
1737973
5
Warto zauważyć, że obecnie działa to tylko dla generatorów Makefile (od cmake 3.3.2). Zobacz stronę podręcznika cmake-properties.
Lekensteyn
1
Warto zauważyć, że jest to sprzeczne z ustawieniem CTEST_USE_LAUNCHERS. Te właściwości są również ustawione tutaj: github.com/Kitware/CMake/blob/master/Modules/…
purpleKarrot
Myślę, że możesz chcieć zmienić kod na ten (z wyjątkiem usunięcia tekstu z wnętrzaendif() ) . Ulepszenia są następujące: 1. Istnieje opcja konfiguracji, aby ją wyłączyć, i 2. Okazuje się, że kolory znikają z GCC / Clang w zapleczu Make, gdy są używane w ten sposób. ninjaBackend działa wokół niego dodając -fdiagnostics-coloropcję, więc jest to wskazane, aby zrobić dla makebackend też.
Hi-Angel
94

Od CMAKE 3.4 możesz:

-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
Jakub
źródło
1
A -DCMAKE_CXX_COMPILER_LAUNCHER=ccache. Te działają pięknie! Nie wiem, dlaczego cmake upiera się przy wyszukiwaniu clangz /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc(więc sztuczka z linkami symbolicznymi nie działa), a nie z $PATH, ale twoja odpowiedź i tak działa.
cdunn2001
2
To powinna być najlepsza odpowiedź. Koniec z mieszaniem ze zmiennymi ścieżek i dowiązaniami symbolicznymi kompilatora!
ilya b.
1
Próbowałem tego, ale po prostu wyświetla mi się błąd „ccache: error: Recursive invocation (nazwa pliku binarnego ccache musi brzmieć„ ccache ”)”. Patrząc na szczegółowy ślad, program próbuje uruchomić „/ usr / local / bin / ccache ccache / usr / bin / c ++”…
Chris Dodd
3
Jak współdziała z RULE_LAUNCH_COMPILE?
Trass3r
10

Od CMake 3.1 można używać ccache z generatorem Xcode, a Ninja jest obsługiwany od CMake 3.4. Ninja będzie honorować RULE_LAUNCH_COMPILEtak samo, jak generator Unix Makefiles (więc odpowiedź @ Babcool prowadzi również do Ninja), ale uzyskanie pamięci podręcznej działającej dla generatora Xcode wymaga trochę więcej pracy. Poniższy artykuł wyjaśnia szczegółowo tę metodę, koncentrując się na ogólnej implementacji, która działa dla wszystkich trzech generatorów CMake i nie przyjmuje żadnych założeń dotyczących konfigurowania dowiązań symbolicznych ccache lub używanego kompilatora (nadal pozwala CMake zdecydować o kompilatorze):

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

Ogólna istota artykułu jest następująca. Początek CMakeLists.txtpliku powinien wyglądać tak:

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

Dwa pliki szablonów skryptów launch-c.ini launch-cxx.inwyglądają następująco (powinny znajdować się w tym samym katalogu co CMakeLists.txtplik):

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}" "$@"

Powyższe używa RULE_LAUNCH_COMPILEtylko dla Unix Makefiles i Ninja, ale dla generatora Xcode opiera się na pomocy z obsługi CMAKE_XCODE_ATTRIBUTE_...zmiennych CMake . Ustawienie CCi CXXzdefiniowanych przez użytkownika Xcode atrybutów kontrolować polecenia kompilator LDi LDPLUSPLUSdla polecenia łącznikowej nie, o ile mogę powiedzieć, udokumentowany cechą projektów Xcode, ale wydaje się do pracy. Jeśli ktokolwiek może potwierdzić, że jest on oficjalnie obsługiwany przez Apple, zaktualizuję odpowiednio powiązany artykuł i tę odpowiedź.

Craig Scott
źródło
Potrzebowałem też set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}") set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")ze wspomnianego artykułu.
Jörn Reimerdes,
Dzięki za przypomnienie, zaktualizowałem odpowiedź tak, aby zawierała ustawienia LD i LDPLUSPLUS.
Craig Scott,
ccache nie obsługuje kompilatorów VS, więc nie możesz jej do tego użyć. Istnieje projekt o nazwie clcache, który ma na celu zapewnienie tej samej funkcjonalności dla VS, ale nie mogę komentować, jak dobrze to działa.
Craig Scott
9

Nie lubiłem ustawiać linku symbolicznego od g++do ccache. ICXX="ccache g++" nie zadziałało dla mnie, ponieważ pewien przypadek testowy cmake chciał mieć tylko program kompilujący bez atrybutów.

Więc zamiast tego użyłem małego skryptu bash:

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

i zapisał go jako plik wykonywalny w /usr/bin/ccache-g++.

Następnie C skonfigurował cmake do użycia /usr/bin/ccache-g++jako kompilator C ++. W ten sposób przechodzi testy cmake i czuję się bardziej komfortowo niż posiadanie linków symbolicznych, o których mógłbym zapomnieć za 2 lub 3 tygodnie, a potem być może zastanawiam się, czy coś nie działa ...

jonas
źródło
5

Moim zdaniem najlepszym sposobem jest dowiązanie symboliczne gcc, g ++ do ccache, ale jeśli chcesz używać w cmake, spróbuj tego:

export CC="ccache gcc" CXX="ccache g++" cmake ...
Nadir SOUALEM
źródło
5

Zweryfikowałem następujące prace (źródło: ten 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" $*

Aktualizacja : Później zdałem sobie sprawę, że nawet to nie działa. O dziwo działa co drugi raz (innym razem cmake narzeka).

dobrze
źródło
4

Dodam jeszcze jedną ważną rzecz, o której wcześniej nie było mowy.

Podczas ładowania minimalistycznego systemu kompilacji z obrazu dockera ubunutu: 18.04 zauważyłem, że kolejność instalacji ma znaczenie.

W moim przypadku ccache działał dobrze podczas wywoływania gcc, ale nie udało się przechwycić wywołań tego samego kompilatora pod innymi nazwami: cci c++. Aby w pełni zainstalować ccache, musisz najpierw upewnić się, że wszystkie kompilatory są zainstalowane, lub dodać wywołanie do dowiązań symbolicznych update-ccache dla bezpieczeństwa.

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

... a następnie (ze względu na zaktualizowane dowiązania symboliczne) również wywołania cc i c ++ zostają złapane!

Jürgen Weigert
źródło
Dzięki, o których nie wiedziałem update-ccache-symlinks, tworzyłem c++link ze skryptem do projektu i działało, ale nie dla innego projektu (nadal nie wiem dlaczego, link był w porządku), update-ccache-symlinksrozwiązany.
Alex