2 个不稳定版本
0.1.0-rc.1 | 2022年3月10日 |
---|---|
0.0.0 | 2020年12月10日 |
#85 在 构建工具
每月 39 次下载
1MB
24K SLoC
cachepot - 共享编译缓存
cachepot 是一个类似 ccache 的编译器缓存工具。它用作编译器包装器,并在可能的情况下避免编译,缓存结果存储在本地磁盘或几个云存储后端之一。
它也是 sccache 的分支,具有改进的安全特性和代码库的全面改进。我们尽可能地向上游贡献,但目标可能不完全匹配。
cachepot 支持缓存 C/C++ 代码、Rust 的编译,以及使用 nvcc 的 NVIDIA CUDA。
cachepot 还为所有支持的编译器(包括 Rust)提供类似 icecream 的分布式编译(自动打包本地工具链)。分布式编译系统包括 icecream 缺少的几个安全功能,如身份验证、传输层加密以及在构建服务器上沙盒化编译器执行。有关更多信息,请参阅分布式快速入门指南。
目录 (ToC)
安装
Windows、Linux(针对musl编译的便携式二进制文件)和macOS的预构建x86-64二进制文件可在发布页面找到。
如果您已安装Rust工具链,则可以使用cargo安装cachepot。 请注意,这将从源代码编译cachepot,这相对资源密集。出于CI目的,您应使用预构建的二进制包。
cargo install --git https://github.com/paritytech/cachepot
使用方法
运行cachepot就像运行ccache一样:在编译命令前加上它,如下所示
cachepot gcc -o foo.o -c foo.c
如果您想使用cachepot缓存Rust构建,您可以在cargo配置文件中定义build.rustc-wrapper
。例如,您可以在$HOME/.cargo/config
中全局设置,通过添加以下内容
[build]
rustc-wrapper = "/path/to/cachepot"
请注意,您需要使用cargo 1.40或更高版本才能使此功能正常工作。
或者,您可以使用环境变量RUSTC_WRAPPER
RUSTC_WRAPPER=/path/to/cachepot cargo build
cachepot支持gcc、clang、MSVC、rustc、NVCC和Wind River的diab编译器。
如果您没有指定其他选项,cachepot将使用本地磁盘缓存。
cachepot使用客户端-服务器模型,其中服务器(我们称之为“协调器”)在客户端相同的机器上本地运行。客户端-服务器模型允许服务器/协调器通过在内存中保留一些状态来提高效率。如果尚未运行,cachepot命令将启动协调器进程,或者您可以通过运行cachepot --start-coordinator
来启动后台服务器进程而不进行任何编译。
您可以通过运行cachepot --stop-coordinator
来终止协调器。默认情况下,它将在10分钟的无操作后终止。
运行cachepot --show-stats
将打印缓存统计摘要。
有关使用cachepot
与Jenkins的说明。
要使用cmake与cachepot一起使用,请向cmake >= 3.4
提供以下命令行参数
-DCMAKE_C_COMPILER_LAUNCHER=cachepot
-DCMAKE_CXX_COMPILER_LAUNCHER=cachepot
构建要求
cachepot是一个Rust程序。构建它需要cargo
(因此需要rustc
)。cachepot目前需要Rust 1.56.1
。我们建议您通过Rustup安装Rust。
构建
如果您是为了非开发目的构建cachepot,请确保您使用cargo build --release
来获取优化后的二进制文件
cargo build --release [--no-default-features --features=s3|redis|gcs|memcached|azure]
默认情况下,cachepot
与所有存储后端一起构建,但可以通过重置功能列表并启用所有其他后端来禁用个别后端。有关如何使用Cargo选择功能的详细信息,请参阅Cargo文档。
Linux
没有本地依赖项。
使用cargo
构建,并使用ldd
检查生成的二进制文件不再依赖于OpenSSL。
Linux和Podman
您还可以使用Parity CI Docker镜像构建存储库。
podman run --rm -it -w /shellhere/cachepot \
-v "$(pwd)":/shellhere/cachepot:Z \
-u $(id -u):$(id -g) \
--userns=keep-id \
docker.io/paritytech/cachepot-ci:staging cargo build --locked --release
#artifacts can be found in ./target/release
如果您想重新生成CI流程中的其他步骤,可以使用以下指南。
macOS
没有本地依赖项。
使用cargo
进行构建,并使用otool -L
检查生成的二进制文件是否不再依赖于OpenSSL。
Windows
在Windows上,二进制文件可能还依赖于一些在旧版Windows版本上不可用的MSVC CRT DLL。
您可以使用包含以下内容的.cargo/config
文件来静态链接CRT。
[target.x86_64-pc-windows-msvc]
rustflags = ["-Ctarget-feature=+crt-static"]
使用cargo
进行构建,并使用dumpbin /dependents
检查生成的二进制文件是否不再依赖于MSVC CRT DLL。
存储选项
本地
cachepot默认使用本地磁盘存储。您可以通过设置环境变量CACHEPOT_DIR
来更改磁盘缓存位置。默认情况下,它将在当前平台的一个合理位置使用:Linux上的~/.cache/cachepot
,Windows上的%LOCALAPPDATA%\Parity\cachepot
,以及macOS上的~/Library/Caches/Parity.cachepot
。
默认缓存大小为10GB。要更改此设置,请设置CACHEPOT_CACHE_SIZE
,例如CACHEPOT_CACHE_SIZE="1G"
。
S3
如果您想为cachepot缓存使用S3存储,您需要将环境变量CACHEPOT_BUCKET
设置为要使用的S3存储桶的名称。
您可以使用AWS_ACCESS_KEY_ID
和AWS_SECRET_ACCESS_KEY
来设置S3凭据。或者,您可以将AWS_IAM_CREDENTIALS_URL
设置为一个返回受支持的凭据格式的URL(见EC2元数据服务),凭据将根据需要从该位置获取。如果没有这些选项之一,将直接从EC2元数据服务获取实例IAM角色的凭据。
如果您需要覆盖默认端点,可以设置CACHEPOT_ENDPOINT
。例如,要连接到minio存储,可以将CACHEPOT_ENDPOINT=<ip>:<port>
。如果您的端点需要TLS,请设置CACHEPOT_S3_USE_SSL=true
。
您还可以定义一个前缀,该前缀将添加到S3存储桶中创建和读取的所有缓存对象的键中,从而创建一个作用域。为此,请使用环境变量CACHEPOT_S3_KEY_PREFIX
。当与另一个应用程序共享存储桶时,这可能非常有用。
Redis
将CACHEPOT_REDIS
设置为Redis的URL,格式为redis://[:<passwd>@]<hostname>[:port][/<db>]
以在Redis实例中存储缓存。Redis可以配置为固定最大缓存大小的LRU(最近最少使用)缓存。根据Redis文档设置maxmemory
和maxmemory-policy
。适用于cachepot用例的allkeys-lru
策略会丢弃最近最少访问或修改的键。
支持通过TLS的Redis。使用rediss://
URL方案(注意rediss
与redis
的区别)。将#insecure
追加到URL中以禁用主机名验证并接受自签名证书(危险!)。请注意,这也会禁用SNI。
Memcached
将CACHEPOT_MEMCACHED
设置为Memcached的URL,格式为tcp://<hostname>:<port> ...
以在Memcached实例中存储缓存。
Google Cloud Storage
要使用Google Cloud Storage,您需要设置环境变量CACHEPOT_GCS_BUCKET
为GCS存储桶的名称。如果您正在使用身份验证,可以将CACHEPOT_GCS_KEY_PATH
设置为JSON服务账户凭证的位置,或将CACHEPOT_GCS_CREDENTIALS_URL
设置为返回oauth令牌的URL。默认情况下,GCS上的CACHEPOT将是只读的。要更改此设置,请将CACHEPOT_GCS_RW_MODE
设置为READ_ONLY
或READ_WRITE
。
Azure
要使用Azure Blob Storage,您需要Azure连接字符串和一个现有Blob存储容器名称。将环境变量CACHEPOT_AZURE_CONNECTION_STRING
设置为您的连接字符串,并将CACHEPOT_AZURE_BLOB_CONTAINER
设置为要使用的容器名称。请注意,cachepot不会为您创建容器 - 您需要自行完成此操作。
重要:环境变量仅在服务器启动时考虑,即仅在第一次运行时。
覆盖缓存
在缓存包含损坏的构建工件的情况下,可能需要覆盖缓存中的内容。可以通过设置环境变量CACHEPOT_RECACHE
来实现。
调试
可以将CACHEPOT_ERROR_LOG
环境变量设置为路径,并将CACHEPOT_LOG
设置为让服务器进程将其日志重定向到那里(包括未处理的panic的输出,因为服务器内部设置了RUST_BACKTRACE=1
)。
CACHEPOT_ERROR_LOG=/tmp/cachepot_log.txt CACHEPOT_LOG=debug cachepot
您也可以为构建系统设置这些环境变量,例如
CACHEPOT_ERROR_LOG=/tmp/cachepot_log.txt CACHEPOT_LOG=debug cmake --build /path/to/cmake/build/directory
或者,如果您本地编译,可以通过运行CACHEPOT_START_SERVER=1 CACHEPOT_NO_DAEMON=1 cachepot
在前台模式下手动运行服务器,并通过设置环境变量CACHEPOT_LOG
(例如)将日志发送到stderr。这种方法不适用于CI服务,因为您需要同时在另一个shell中编译。
CACHEPOT_LOG=debug CACHEPOT_START_SERVER=1 CACHEPOT_NO_DAEMON=1 cachepot
与GNU make
作业服务器交互
cachePot支持GNU make jobserver。当服务器从一个提供jobserver的进程启动时,cachePot将使用该jobserver并将其提供给它所派生的任何进程。(如果您从GNU make配方中运行cachePot,您需要使用+
作为命令的前缀来获得这种行为。)如果cachePot服务器在没有jobserver的情况下启动,它将创建自己的jobserver,其槽位数量等于可用的CPU核心数量。
这在使用cachePot进行Rust编译时最有用,因为rustc支持使用jobserver进行并行代码生成,所以这确保了rustc不会因为代码生成任务而使系统过载。Cargo为rustc实现了自己的jobserver(有关NUM_JOBS
的信息,请参阅cargo文档),因此通过RUSTC_WRAPPER
使用cachePot进行Cargo的Rust编译应该会自动完成正确的事情。
已知问题
通用
- 文件的绝对路径必须匹配才能获得缓存命中。这意味着即使您正在使用共享缓存,每个人也必须在相同的绝对路径下构建(即不在
$HOME
),才能相互受益。在Rust中,这包括存储在$HOME/.cargo/registry/cache
中的第三方crate的源代码。
Rust
- 无法缓存调用系统链接器的crate。这包括
bin
、dylib
、cdylib
和proc-macro
crate。您可能可以通过将它们转换为具有薄bin
包装器的lib
crate来提高大型bin
crate的编译时间。 - 增量编译的crate无法缓存。默认情况下,在调试配置文件中,Cargo将为工作空间成员和路径依赖项使用增量编译。您可以通过禁用增量编译。
依赖关系
~26–45MB
~737K SLoC