#缓存 #编译器 #编译 #本地存储 #构建 #包装器 #ccache

构建 sccache

Sccache 是一个类似于 ccache 的工具。它用作编译器包装器,并在可能的情况下避免编译。Sccache 具备在远程存储环境中利用缓存的能力,包括各种云存储选项,或者在本地存储。

37 个版本

0.8.1 2024 年 5 月 24 日
0.7.7 2024 年 2 月 7 日
0.7.4 2023 年 11 月 27 日
0.5.4 2023 年 6 月 28 日
0.1.0 2016 年 12 月 16 日

#14 in 构建实用工具

Download history 3148/week @ 2024-05-03 3081/week @ 2024-05-10 2674/week @ 2024-05-17 3174/week @ 2024-05-24 2570/week @ 2024-05-31 3584/week @ 2024-06-07 3094/week @ 2024-06-14 2294/week @ 2024-06-21 2253/week @ 2024-06-28 2498/week @ 2024-07-05 2811/week @ 2024-07-12 2314/week @ 2024-07-19 2988/week @ 2024-07-26 3032/week @ 2024-08-02 2425/week @ 2024-08-09 1507/week @ 2024-08-16

10,383 每月下载量

Apache-2.0

1.5MB
31K SLoC

包含 (晦涩的 autoconf 代码, 1KB) tests/autotools/configure.ac

Build Status Crates.io Matrix Crates.io dependency status

CodeCov

sccache - 共享编译缓存

sccache 是一个类似于 ccache 的编译器缓存工具。它用作编译器包装器,并在可能的情况下避免编译,将缓存结果存储在本地磁盘或多个云存储后端之一。

sccache 支持缓存 C/C++ 代码、Rust 编译,以及使用 nvccclang 的 NVIDIA CUDA。

sccache 还提供类似 icecream 的分布式编译(自动打包本地工具链)功能,适用于所有支持的编译器(包括 Rust)。分布式编译系统包含一些 icecream 缺失的安全功能,例如身份验证、传输层加密以及在构建服务器上沙箱化的编译器执行。有关更多信息,请参阅 分布式快速入门 指南。

Sccache 也可作为 GitHub Actions 使用,以方便使用 GitHub Actions 缓存进行部署。


目录


安装

Windows、Linux(针对 musl 编译的可移植二进制文件)和macOS(在发布页面上)都提供了预构建的x86-64二进制文件。一些包管理器也包含sccache包,您可以使用cargo从源安装最新版本,或直接从源代码签出构建。

macOS

在macOS上,您可以通过Homebrew

brew install sccache

或通过MacPorts

sudo port install sccache

Windows

在Windows上,您可以通过scoop

scoop install sccache

通过cargo

如果您已安装Rust工具链,您可以使用cargo安装sccache。**注意,这将从源代码编译sccache,这需要相当多的资源。出于CI目的,您应使用预构建的二进制包。**

cargo install sccache --locked

使用说明

运行sccache就像运行ccache一样:在您的编译命令前加上它,如下所示

sccache gcc -o foo.o -c foo.c

如果您想使用sccache进行Rust构建的缓存,您可以在cargo配置文件中定义build.rustc-wrapper。例如,您可以在$HOME/.cargo/config.toml中全局设置它,通过添加

[build]
rustc-wrapper = "/path/to/sccache"

请注意,您需要使用cargo 1.40或更高版本才能使用此功能。

或者,您可以使用环境变量RUSTC_WRAPPER

export RUSTC_WRAPPER=/path/to/sccache
cargo build

sccache支持gcc、clang、MSVC、rustc、NVCCNVC++Wind River的diab编译器。gcc和msvc都支持响应文件,更多关于其实现的信息请参阅此处

如果您没有指定其他设置,sccache将使用本地磁盘缓存。

sccache使用客户端-服务器模型,其中服务器在客户端所在的同一台机器上本地运行。客户端-服务器模型允许服务器通过在内存中保持一些状态来提高效率。如果还没有正在运行的进程,sccache命令将启动服务器进程;或者,您也可以运行sccache --start-server来启动后台服务器进程而不进行任何编译。

您可以通过运行sccache --stop-server来终止服务器。默认情况下,它将在10分钟的不活动后终止。

运行sccache --show-stats将打印缓存统计摘要。

有关使用sccacheJenkins的一些说明,请参阅此处

要使用sccache与cmake一起使用,请向cmake 3.4或更高版本提供以下命令行参数

-DCMAKE_C_COMPILER_LAUNCHER=sccache
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache

使用sccache与MSVC和cmake配合的过程取决于你使用的cmake版本。对于3.24版本及更早的cmake版本,为了使用MSVC进行调试生成PDB文件,你可以使用/Z7选项。或者,如果/Fd为每个生成的对象文件指定了不同的PDB文件名,则可以使用/Zi选项与/Fd选项。请注意,CMake默认设置/Zi,所以如果你使用CMake,你可以在CMakeLists.txt中添加如下代码来使用/Z7

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
  string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
  string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
  string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
elseif(CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
  string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
  string(REPLACE "/Zi" "/Z7" CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
endif()

默认情况下,如果sccache无法成功与其相关服务器通信,它将使你的构建失败。为了使sccache在不停止的情况下优雅地切换到本地编译器,请设置环境变量SCCACHE_IGNORE_SERVER_IO_ERROR=1

对于3.25版本及以后的cmake版本,为了使用MSVC进行编译,你必须使用新的CMAKE_MSVC_DEBUG_INFORMATION_FORMAT选项,该选项用于配置-Z7标志。此外,你必须将cmake策略编号0141设置为NEW设置。

set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
cmake_policy(SET CMP0141 NEW)

以下是我们自动在PATH中查找sccache的示例配置。

find_program(SCCACHE sccache REQUIRED)

set(CMAKE_C_COMPILER_LAUNCHER ${SCCACHE})
set(CMAKE_CXX_COMPILER_LAUNCHER ${SCCACHE})
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT Embedded)
cmake_policy(SET CMP0141 NEW)

或者,如果使用命令行配置cmake与MSVC,假设sccache位于默认搜索路径上。

cmake -DCMAKE_C_COMPILER_LAUNCHER=sccache -DCMAKE_CXX_COMPILER_LAUNCHER=sccache -DCMAKE_MSVC_DEBUG_INFORMATION_FORMAT=Embedded -DCMAKE_POLICY_CMP0141=NEW [...]

你可以像往常一样在命令行中不添加任何额外标志地构建代码,这对于IDE非常有用。


构建要求

sccache是一个Rust程序。构建它需要cargo(因此需要rustc)。sccache目前需要Rust 1.70.0。我们建议你通过Rustup安装Rust。

构建

如果你是为了非开发目的构建sccache,请确保你使用cargo build --release来获取优化后的二进制文件。

cargo build --release [--no-default-features --features=s3|redis|gcs|memcached|azure|gha|webdav|oss]

功能列表可以在Cargo.toml文件的[features]部分找到。

默认情况下,sccache构建时支持所有存储后端,但可以通过重置功能列表并启用所有其他后端来禁用单个后端。有关如何使用Cargo选择功能的详细信息,请参阅Cargo文档

构建可移植二进制文件

当使用dist-server功能构建时,sccache将依赖于OpenSSL,这可能在你想要分发可移植二进制文件时造成不便。可以使用openssl/vendored功能将OpenSSL静链接。

Linux

使用cargo构建,并使用ldd检查生成的二进制文件不再依赖于OpenSSL。

macOS

使用cargo构建,并使用otool -L检查生成的二进制文件不再依赖于OpenSSL。

Windows

在Windows上,二进制文件可能还依赖于一些在较旧Windows版本上不可用的MSVC CRT DLL。

可以使用以下内容的.cargo/config.toml文件将CRT静链接。

[target.x86_64-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static"]

使用cargo构建,并使用dumpbin /dependents检查生成的二进制文件不再依赖于MSVC CRT DLL。

当使用 OpenSSL 进行静态链接时,您需要在您的 $PATH 中可访问 Perl。


调用之间分离缓存

在应该不互相重用缓存结果的多个编译调用的情况下,可以将 SCCACHE_C_CUSTOM_CACHE_BUSTER 设置为唯一的值,该值将混合到哈希中。变量 MACOSX_DEPLOYMENT_TARGETIPHONEOS_DEPLOYMENT_TARGET 已经表现出这种抑制重用的行为。目前还没有用于编译 Rust 的此类变量。


覆盖缓存

在缓存包含损坏的构建工件的情况下,可能需要覆盖缓存中的内容。可以通过设置环境变量 SCCACHE_RECACHE 来实现这一点。


调试

您可以将环境变量 SCCACHE_ERROR_LOG 设置为路径,并将 SCCACHE_LOG 设置为让服务器进程将日志重定向到那里(包括未处理的恐慌输出,因为服务器内部设置了 RUST_BACKTRACE=1)。

SCCACHE_ERROR_LOG=/tmp/sccache_log.txt SCCACHE_LOG=debug sccache

您也可以为您的构建系统设置这些环境变量,例如

SCCACHE_ERROR_LOG=/tmp/sccache_log.txt SCCACHE_LOG=debug cmake --build /path/to/cmake/build/directory

或者,如果您本地编译,可以通过运行 SCCACHE_START_SERVER=1 SCCACHE_NO_DAEMON=1 sccache 在前台模式手动运行服务器,并通过设置环境变量 SCCACHE_LOG(例如)将日志发送到 stderr。此方法不适合 CI 服务,因为您需要同时在另一个 shell 中编译。

SCCACHE_LOG=debug SCCACHE_START_SERVER=1 SCCACHE_NO_DAEMON=1 sccache

与GNU make作业服务器的交互

sccache 提供了对 GNU make jobserver 的支持。当服务器从一个提供 jobserver 的进程启动时,sccache 将使用该 jobserver 并将其提供给它启动的任何进程。如果从 GNU make 脚本运行 sccache,您需要使用 + 作为命令的前缀来获得此行为。如果没有 jobserver,sccache 服务器将创建一个自己的 jobserver,其槽位数量等于可用的 CPU 核心数量。

当使用 sccache 进行 Rust 编译时,这最有用,因为 rustc 支持使用 jobserver 进行并行代码生成,这样就可以确保 rustc 不会因代码生成任务而使系统不堪重负。Cargo 为 rustc 实现了自己的 jobserver(有关 NUM_JOBS 的信息,请参阅 cargo 文档),因此通过 RUSTC_WRAPPER 使用 sccache 进行 cargo 的 Rust 编译应该会自动完成正确操作。


已知注意事项

General

  • 要获得缓存命中,文件绝对路径必须匹配。这意味着即使您正在使用共享缓存,每个人也必须使用相同的绝对路径(例如,不是在 $HOME)进行构建,以便互相受益。在 Rust 中,这包括存储在 $HOME/.cargo/registry/cache 的第三方 crate 的源代码。默认情况下。

Rust

  • 无法缓存调用系统链接器的crate。这包括bindylibcdylibproc-macrocrate。您可能可以通过将它们转换为带有薄bin包装器的libcrate来提高大型bincrate的编译时间。
  • 增量编译的crate无法缓存。默认情况下,在调试配置文件中,Cargo将为工作空间成员和路径依赖项使用增量编译。您可以禁用增量编译。

Rust的注意事项更多细节

  • 指向sccache的符号链接将不起作用。请使用硬链接:ln sccache /usr/local/bin/cc

存储选项

依赖关系

~26–48MB
~841K SLoC