ChatGPT解决这个技术问题 Extra ChatGPT

如何在 CMake 中使用 CCache?

我想做以下事情:如果 CCache 存在于 PATH 中,则使用“ccache g++”进行编译,否则使用 g++。我尝试编写一个小的 my-cmake 脚本,其中包含

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

但它似乎不起作用(运行 make 仍然不使用 ccache;我使用 CMAKE_VERBOSE_MAKEFILE 检查了这一点)。

更新:

根据 this link,我尝试将脚本更改为

     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 的测试失败(这是可以预料的)。

为什么不将 gcc 符号链接到 ccache?如果您要分发它,我认为如果用户安装了 ccache 并希望使用它,他自己会完成符号链接。
@int3 是的,这可能会起作用(我不知道 ccache 将编译器作为可选参数)。但是,更明确会更清晰。

J
Jacob

从 CMAKE 3.4 开始,您可以执行以下操作:

-DCMAKE_CXX_COMPILER_LAUNCHER=ccache

-DCMAKE_CXX_COMPILER_LAUNCHER=ccache。这些工作精美!我不知道为什么 cmake 坚持从 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc 中找到 clang(因此符号链接技巧不起作用),而不是从 $PATH 中,但您的答案仍然有效。
这应该是最好的答案。不再弄乱路径变量和编译器符号链接!
我试过这个,但它只是给了我错误“ccache:错误:递归调用(ccache 二进制文件的名称必须是“ccache”)”。查看详细跟踪,它正在尝试运行“/usr/local/bin/ccache ccache /usr/bin/c++”...
它如何与 RULE_LAUNCH_COMPILE 交互?
这个是一直有效的;即使您使用的是工具链文件,它也可以工作,并且它指定了编译器的完整路径(其中修改系统 PATH 没有帮助)。谢谢!
B
Babcool

现在可以将 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,Craig Scott 在他的回答中给出了一个解决方法。

编辑:感谢 uprego 和 Lekensteyn 的评论,我编辑了答案以检查 ccache 在用作启动器之前是否可用,以及哪些生成器可以使用编译启动器。

Edit2:@Emilio Cobos 建议避免对链接部分这样做,因为 ccache 不会提高链接速度,并且可能会与其他类型的缓存(如 sccache)混淆


许多网站隐含地建议使用 find_program(CCACHE_FOUND "ccache") 中的双引号,我不知道哪个更便携,我的里程做得非常好,不需要双引号。
值得注意的是,这目前仅适用于 Makefile 生成器(从 cmake 3.3.2 开始)。请参阅 cmake-properties 的手册页。
值得注意的是,这与 CTEST_USE_LAUNCHERS 设置冲突。这些属性也在此处设置:github.com/Kitware/CMake/blob/master/Modules/…
我认为您可能希望将代码更改为 this one (除了 remove text from inside of endif()。改进是: 1. 有一个禁用它的配置选项,以及 2. 事实证明,以这种方式使用时,颜色会从 Make backend 中的 GCC/Clang 中消失。 ninja 后端通过添加 -fdiagnostics-color 选项来解决它,因此建议对 make 后端也这样做。
N
Nicolás

我个人的 $PATH 中有 /usr/lib/ccache。该目录包含大量符号链接,用于调用编译器的每个可能名称(如 gccgcc-4.3),所有这些都指向 ccache。

而且我什至没有创建符号链接。当我在 Debian 上安装 ccache 时,该目录已预先填充。


请注意,此 ccache 路径必须放置在 真正编译器在 $PATH 中的路径之前,它才能工作。 export PATH = /usr/lib/ccache:$PATH 之类的东西
@Gui13:比更新 PATH 更好的是明确告诉 cmake 它应该使用的 gcc 在哪里,例如 cmake -DCMAKE_CXX_COMPILER=/usr/lib/ccache/bin/g++
brew install ccache 之后,我有 /usr/local/Cellar/ccache/3.2.1/libexec/
C
Craig Scott

从 CMake 3.1 开始,可以将 ccache 与 Xcode 生成器一起使用,并且从 CMake 3.4 开始支持 Ninja。 Ninja 将像 Unix Makefiles 生成器一样尊重 RULE_LAUNCH_COMPILE (所以@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.inlaunch-cxx.in 如下所示(它们应该与 CMakeLists.txt 文件位于同一目录中):

启动-c.in:

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

启动-cxx.in:

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

以上对 Unix Makefile 和 Ninja 单独使用 RULE_LAUNCH_COMPILE,但对于 Xcode 生成器,它依赖于 CMake 的 CMAKE_XCODE_ATTRIBUTE_... 变量支持的帮助。 CCCXX 用户定义的 Xcode 属性的设置来控制编译器命令和链接器命令的 LDLDPLUSPLUS 不是,据我所知,Xcode 项目的记录功能,但它似乎确实有效。如果有人可以确认它得到 Apple 的官方支持,我会相应地更新链接的文章和这个答案。


我还需要上述文章中的 set(CMAKE_XCODE_ATTRIBUTE_LD "${CMAKE_C_COMPILER}") set(CMAKE_XCODE_ATTRIBUTE_LDPLUSPLUS "${CMAKE_CXX_COMPILER}")
感谢您的提醒,我已经更新了答案以包括设置 LD 和 LDPLUSPLUS。
ccache 不支持 VS 编译器,因此您不能使用它。有一个名为 clcache 的项目旨在为 VS 提供相同的功能,但我无法评论它的工作情况。
J
Jed

我不喜欢设置从 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 周内忘记的符号链接更舒服,然后可能想知道是否有什么不起作用......


a
amit kumar

我验证了以下作品(来源:this 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" $*

更新:我后来意识到,即使这样也行不通。奇怪的是,它每隔一段时间就会起作用(其他时间 cmake 抱怨)。


J
Jürgen Weigert

让我补充一个之前没有提到的重要项目。

在从 ubuntu:18.04 docker 映像引导一个简约的构建系统时,我发现安装顺序会有所不同。

在我的例子中,调用 gcc 时 ccache 运行良好,但未能捕获通过其他名称调用同一编译器:ccc++。要完全安装 ccache,您需要确保首先安装所有编译器,添加对 update-ccache 符号链接的调用以确保安全。

sudo /usr/sbin/update-ccache-symlinks
export PATH="/usr/lib/ccache/:$PATH"```

... and then (due to updated symlinks) also calls to cc and c++ get caught!

谢谢,我不知道 update-ccache-symlinks,我正在为一个项目创建带有脚本的 c++ 链接,它正在工作,但不适用于另一个项目(仍然不知道为什么,链接很好),update-ccache-symlinks解决了。
N
Nadir SOUALEM

在我看来,最好的方法是将 gcc,g++ 符号链接到 ccache,但如果你想在 cmake 中使用,试试这个:

export CC="ccache gcc" CXX="ccache g++" cmake ...

e
ephemerr

它正在扩展@Nicolas answer

将以下行添加到您的 cmake 文件中:

list(PREPEND CMAKE_PROGRAM_PATH /usr/lib/ccache)

或将其作为参数添加到 cmake 配置步骤:

cmake -DCMAKE_PROGRAM_PATH=/usr/lib/ccache