Как использовать CCache с CMake?

91

Я хотел бы сделать следующее: если CCache присутствует в PATH, используйте для компиляции "ccache g ++", иначе используйте g ++. Я попытался написать небольшой скрипт my-cmake, содержащий

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

но похоже, что это не работает (при запуске make по-прежнему не используется ccache; я проверил это с помощью CMAKE_VERBOSE_MAKEFILE on).

Обновить:

По этой ссылке я попытался изменить свой сценарий на

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

но cmake выходит из строя, жалуясь, что тест не прошел при использовании ccache компилятора (чего можно ожидать).

амит
источник
4
Почему бы вам просто не привязать gcc к ccache? И если вы распространяете это, я бы подумал, что пользователь сам сделал бы символическую ссылку, если бы у него был установлен ccache и он хотел бы, чтобы он использовался ..
int3
1
@ int3 Да, вероятно, это сработает (я не знал, что ccache имеет компилятор в качестве необязательного аргумента). Однако было бы чище быть более явным.
amit

Ответы:

67

Лично у меня /usr/lib/ccacheв моем $PATH. Этот каталог содержит множество символических ссылок для всех возможных имен, из которых может быть вызван компилятор (например, gccи gcc-4.3), все они указывают на ccache.

И я даже не создавал символические ссылки. Этот каталог заполняется предварительно, когда я устанавливаю ccache в Debian.

Николас
источник
11
Обратите внимание, что этот путь ccache должен быть помещен перед путем, по которому находится ваш настоящий компилятор, $PATHчтобы он работал. Что-то вродеexport PATH = /usr/lib/ccache:$PATH
Gui13
6
@ Gui13: Лучше, чем обновлять PATH, было бы явно указать cmake, где gcc, который он должен использовать, например, cmake -DCMAKE_CXX_COMPILER = / usr / lib / ccache / bin / g ++
cib
3
После brew install ccacheэтого у меня есть /usr/local/Cellar/ccache/3.2.1/libexec/.
cdunn2001
96

Теперь можно указать ccache в качестве средства запуска для команд компиляции и команд связывания (начиная с cmake 2.8.0). Это работает для Makefile и генератора Ninja. Для этого просто установите следующие свойства:

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)

Также можно установить эти свойства только для определенных каталогов или целей.

Для Ninja это возможно с версии 3.4. Для XCode Крейг Скотт дает обходной путь в своем ответе.

Изменить: благодаря uprego и комментарию Lekensteyn я отредактировал ответ, чтобы проверить, доступен ли ccache, прежде чем использовать его в качестве средства запуска, и для каких генераторов можно использовать средство запуска компиляции.

Edit2: @Emilio Cobos рекомендовал избегать этого для части связывания, поскольку ccache не улучшает скорость связывания и может связываться с другими типами кеша, такими как sccache

Babcool
источник
Многие сайты неявно рекомендуют использовать двойные кавычки, например, в find_program(CCACHE_FOUND "ccache"), я не знаю, какой из них более переносимый, мой пробег отлично справился без двойных кавычек.
1737973
5
Стоит отметить, что в настоящее время это работает только для генераторов Makefile (начиная с cmake 3.3.2). См. Страницу руководства cmake-properties.
Lekensteyn 05
1
Стоит отметить, что это конфликтует с настройкой CTEST_USE_LAUNCHERS. Эти свойства также устанавливаются здесь: github.com/Kitware/CMake/blob/master/Modules/…
purpleKarrot
Я думаю, вы можете изменить код на этот (кроме удаления текста изнутриendif() ) . Усовершенствования: 1. Есть опция конфигурации, чтобы отключить это, и 2. Оказывается, цвета исчезают из GCC / Clang в бэкэнде Make при использовании таким образом. ninjaБэкенд работает вокруг него, добавив -fdiagnostics-colorопцию, так что желательно сделать это для makeвнутреннего интерфейса тоже.
Hi-Angel
95

Начиная с CMAKE 3.4 вы можете:

-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
Джейкоб
источник
1
И -DCMAKE_CXX_COMPILER_LAUNCHER=ccache. Они прекрасно работают! Я не знаю, почему cmake настаивает на поиске clangиз /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc(так что трюк с символической ссылкой не работает), а не из $PATH, но ваш ответ все равно работает.
cdunn2001
2
Это должен быть лучший ответ. Больше не нужно возиться с переменной пути и символическими ссылками на компилятор!
илья б.
1
Я пробовал это, но это выдает ошибку «ccache: error: Recursive invocation (имя двоичного файла ccache должно быть« ccache »)». Глядя на подробную трассировку, он пытается запустить "/ usr / local / bin / ccache ccache / usr / bin / c ++" ...
Крис Додд
3
Как он взаимодействует с RULE_LAUNCH_COMPILE?
Trass3r
10

Начиная с CMake 3.1, можно использовать ccache с генератором Xcode, а Ninja поддерживается начиная с CMake 3.4. Ninja будет RULE_LAUNCH_COMPILEуважать так же, как генератор Unix Makefiles (так что ответ @Babcool доставит вас туда и для Ninja), но для того, чтобы заставить ccache работать для генератора Xcode, требуется немного больше работы. В следующей статье подробно описывается метод, фокусируясь на общей реализации, которая работает для всех трех генераторов CMake, и не делая никаких предположений о настройке символических ссылок ccache или используемого базового компилятора (он по-прежнему позволяет CMake определять компилятор):

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

Общая суть статьи такова. Начало вашего CMakeLists.txtфайла должно быть настроено примерно так:

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

Два файла шаблона сценария launch-c.inи launch-cxx.inвыглядят следующим образом (они должны находиться в том же каталоге, что и CMakeLists.txtфайл):

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

Вышеупомянутое используется RULE_LAUNCH_COMPILEтолько для Unix Makefiles и Ninja, но для генератора Xcode он полагается на CMAKE_XCODE_ATTRIBUTE_...поддержку переменных CMake . Установка из CCи CXXопределяемого пользователя Xcode атрибутов для управления командой компилятора и LDи LDPLUSPLUSдля команды линкера нет, насколько я могу сказать, документально особенность проектов Xcode, но это не похоже на работу. Если кто-нибудь может подтвердить, что он официально поддерживается Apple, я обновлю связанную статью и этот ответ соответственно.

Крейг Скотт
источник
Мне также понадобилась set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}") set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")статья из упомянутой статьи.
Jörn Reimerdes
Спасибо за напоминание, я обновил ответ, включив в него настройки LD и LDPLUSPLUS.
Крейг Скотт
ccache не поддерживает компиляторы VS, поэтому вы не можете использовать его для этого. Существует проект под названием clcache, целью которого является предоставление той же функциональности для VS, но я не могу комментировать, насколько хорошо он работает.
Крейг Скотт
9

Мне не нравилось устанавливать символическую ссылку с g++на ccache. А такжеCXX="ccache g++" это не сработало для меня, поскольку какой-то тестовый пример cmake хотел иметь только программу компилятора без атрибутов.

Поэтому вместо этого я использовал небольшой сценарий bash:

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

и сохранил его как исполняемый файл в формате /usr/bin/ccache-g++.

Затем C настроил cmake для использования в /usr/bin/ccache-g++качестве компилятора C ++. Таким образом, он проходит тесты cmake, и мне удобнее, чем иметь символические ссылки, о которых я могу забыть через 2 или 3 недели, а затем, возможно, задаться вопросом, не работает ли что-то ...

Йонас
источник
5

На мой взгляд, лучший способ - это символическая ссылка gcc, g ++ на ccache, но если вы хотите использовать в cmake, попробуйте следующее:

export CC="ccache gcc" CXX="ccache g++" cmake ...
Надир СУАЛЕМ
источник
5

Я проверил следующие работы (источник: эта ссылка ):

        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" $*

Обновление : позже я понял, что даже это не работает. Как ни странно, он работает каждый раз (иногда cmake жалуется).

амит
источник
4

Позвольте мне добавить один важный момент, о котором здесь раньше не упоминалось.

При загрузке минималистичной системы сборки из образа докера ubunutu: 18.04 я обнаружил, что порядок установки имеет значение.

В моем случае ccache работал нормально при вызове gcc, но не смог поймать вызовы того же компилятора с другими именами: ccи c++. Чтобы полностью установить ccache, вам необходимо сначала убедиться, что все компиляторы установлены, или добавить вызов символических ссылок update-ccache для безопасности.

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

... а затем (из-за обновленных символических ссылок) также ловятся вызовы cc и c ++!

Юрген Вайгерт
источник
Спасибо, о чем я не знал update-ccache-symlinks, я создавал c++ссылку на сценарий для проекта, и он работал, но не для другого проекта (до сих пор не знаю, почему, ссылка была в порядке), update-ccache-symlinksрешено.
Alex