是否可以使用ccache或类似工具加速clang整洁



由于在我们的CI服务器上使用ccache,我们发现构建时间方面的瓶颈现在是我们的静态分析通行证,它使用clang-tidy和其他工具。有人知道加速clang-tidy的方法吗,类似于ccache使用常规编译器的方法吗?

我在这里发现了另一个重要的细节:

https://gitlab.kitware.com/cmake/cmake/-/merge_requests/1791/diffs

这里使用的是:

https://reviews.bitcoinabc.org/D5150?id=15995

因此,为了能够在集成clang整洁时缓存编译器的输出,请使用:设置(CMAKE_CXX_CLANG_IDY…

方法需要使用COMPILER_LAUNCHER方法来配置ccache

find_program(CCACHE ccache)
if(CCACHE)
set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE})
set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE})
endif(CCACHE)

而不是启动器规则方法:

find_program(CCACHE ccache)
if(CCACHE)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE})
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE})
endif(CCACHE)

感谢您的提问和大家的回答。

在努力使ejfitzgerald/clang整洁的缓存在没有任何像样的文档或帮助的情况下工作后,我尝试了matus chochlik/ctcache。它在安装和配置方面确实容易得多。

这里有一个片段,当它安装时,我们用来自动将它与cmake一起使用

find_program (CLANG_TIDY_CACHE_PATH NAMES "clang-tidy-cache")
if (CLANG_TIDY_CACHE_PATH)
find_program (_CLANG_TIDY_PATH NAMES "clang-tidy" "clang-tidy-15" "clang-tidy-14" "clang-tidy-13" "clang-tidy-12")
# Why do we use ';' here?
# It's a cmake black magic: https://cmake.org/cmake/help/latest/prop_tgt/LANG_CLANG_TIDY.html#prop_tgt:%3CLANG%3E_CLANG_TIDY
# The CLANG_TIDY_PATH is passed to CMAKE_CXX_CLANG_TIDY, which follows CXX_CLANG_TIDY syntax.
set (CLANG_TIDY_PATH "${CLANG_TIDY_CACHE_PATH};${_CLANG_TIDY_PATH}" CACHE STRING "A combined command to run clang-tidy with caching wrapper")
else ()
find_program (CLANG_TIDY_PATH NAMES "clang-tidy" "clang-tidy-15" "clang-tidy-14" "clang-tidy-13" "clang-tidy-12")
endif ()
set (CMAKE_CXX_CLANG_TIDY "${CLANG_TIDY_PATH}")

有了它,如果clang-tidy-cache在路径中,它将与任何找到的clang-tidy一起使用。

在构建过程中,我们定义了CTCACHE_DIR,并在构建之间保留它们。

在我们的CI中,它将短绒时间从330分钟减少到22分钟,因此速度几乎快了15倍!

有clang整洁的缓存,尽管我不知道它是如何与ccache一起工作的。

我无法构建clang整洁缓存,因为我没有正确的go版本,所以我在python中创建了cltcache。它的使用方式与ccache完全一样,希望它比clang整洁的缓存更容易安装。

它将使用注释以及启用的检查和clang-time版本字符串对预处理器输出进行散列,并将其用作缓存的密钥。缓存未命中时,它将执行clang整洁调用,并将stdout、stderr和返回代码压缩并存储在缓存中。

不确定它是否对其他项目足够快,但在我的项目中,clang-time消耗的时间大约是实际编译的四倍,因此额外运行预处理器所消耗的时间相对可以忽略不计。

最后,我找到了一个解决方案:将构建系统切换到bazel。bazel是一个非常通用的构建系统,它定义了一个动作图。基本上,每个动作都有一组输入和输出。根据输入,可以缓存输出。因此,巴泽尔从根本上解决了这个问题。

可以在这里找到以可编辑的方式集成clang-time的必要规则:https://github.com/erenon/bazel_clang_tidy

为了利用缓存,您需要设置一个远程缓存。这可以使用docker compose脚本来完成。必要的docker容器已存在。让它运行的命令可以在这里找到:https://github.com/buchgr/bazel-remote/

最后,bazel还解决了缓存链接阶段的结果的问题。

不仅如此,bazel还允许构建其他语言,如java。因此,在复杂的项目中,它允许用一个构建系统替换所有其他构建系统。

最后,bazel还允许在集群上并行化构建。

最后但同样重要的是,您可以定义几个平台和工具链。所有这些都允许进行跨平台构建。

最新更新