大幅提速 colcon build —— ccache 缓存 + 并行数控制防爆内存

适用环境:Ubuntu 22.04 + ROS2 Humble


一、问题背景

ROS2 工作区一旦包含大量 C++ 包(SLAM、控制器、传感器驱动等),每次 colcon build 动辄耗时数分钟甚至十几分钟。主要痛点有两个:

  1. 重复编译:改了一个包,其余未改动的包却被重新编译
  2. 内存溢出 :colcon 默认并行编译所有包,包数多时极易把内存打爆,触发 OOM Killer,编译直接中断

本文给出两个针对性的解决方案。


二、ccache ------ 缓存编译结果,告别重复编译

原理

ccache 会把每次编译生成的 .o 文件按源码内容哈希缓存下来。下次编译时,若源码和编译参数完全相同,直接返回缓存结果,跳过实际编译,速度接近瞬间完成。

即使执行了 rm -rf build/,只要源码没变,ccache 依然命中缓存。

安装

bash 复制代码
sudo apt install ccache

配置缓存目录和大小

写入 ~/.bashrc:

bash 复制代码
export CCACHE_DIR="$HOME/.ccache"
export CCACHE_MAXSIZE="10G"
bash 复制代码
source ~/.bashrc

缓存上限根据硬盘空间自行调整,10~20G 对大型 ROS2 工作区均够用。

全局永久生效(推荐)

colcon 支持通过 ~/.colcon/defaults.yaml 为所有工作区统一注入编译参数,无需每次手敲:

bash 复制代码
mkdir -p ~/.colcon
cat > ~/.colcon/defaults.yaml << 'EOF'
build:
  cmake-args:
    - -DCMAKE_C_COMPILER_LAUNCHER=ccache
    - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
    - --no-warn-unused-cli
EOF

配置完成后,直接敲 colcon build 即可,ccache 自动接管所有 C/C++ 编译。

--no-warn-unused-cli 说明 :工作区中若存在纯 Python 包(ament_python 类型),CMake 会警告 CMAKE_CXX_COMPILER_LAUNCHER 未被使用。加上此参数可屏蔽该无害警告,保持输出整洁。

验证是否生效

bash 复制代码
# 查看缓存命中统计
ccache -s

首次全量编译后再执行一次 colcon build,cache hit 数量应大幅上升,编译时间骤降。

bash 复制代码
# 清零统计计数(不清除缓存内容)
ccache -z

三、控制并行数 ------ 防止编译时爆内存

问题原因

colcon 默认同时编译所有包,每个包又会启动多个编译线程,内存消耗随包数和线程数成倍放大。16G 内存的机器在编译 SLAM 相关工作区时经常 OOM。

解决方案

在 ~/.colcon/defaults.yaml 中追加并行控制参数:

yaml 复制代码
build:
  cmake-args:
    - -DCMAKE_C_COMPILER_LAUNCHER=ccache
    - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
    - --no-warn-unused-cli
  parallel-workers: 4        # 同时编译的包数,按内存酌情调整
  cmake-args:
    - -DCMAKE_BUILD_PARALLEL_LEVEL=4   # 每个包内部的并行线程数

注意 :cmake-args 在 YAML 中只能出现一次,需合并为同一个列表,完整写法见下方。

完整 ~/.colcon/defaults.yaml

yaml 复制代码
build:
  cmake-args:
    - -DCMAKE_C_COMPILER_LAUNCHER=ccache
    - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
    - -DCMAKE_BUILD_PARALLEL_LEVEL=4
    - --no-warn-unused-cli
  parallel-workers: 4
参数 含义
parallel-workers colcon 同时构建的包数
CMAKE_BUILD_PARALLEL_LEVEL 每个包内 make 使用的线程数

内存估算参考:parallel-workers × CMAKE_BUILD_PARALLEL_LEVEL × ~500MB,根据自身内存调整。32G 内存可适当放开到 8 × 8。


四、效果对比

场景 优化前 优化后
首次全量编译 基准 基准(建立缓存)
未改动包的重新编译 与首次相当 接近 0 秒
清空 build/ 后重新编译 与首次相当 大幅缩短(命中缓存)
大型工作区并行编译 易 OOM 中断 稳定完成

五、一键配置脚本

bash 复制代码
#!/bin/bash
# 安装 ccache
sudo apt install -y ccache

# 写入环境变量
grep -qxF 'export CCACHE_DIR="$HOME/.ccache"' ~/.bashrc || \
  echo 'export CCACHE_DIR="$HOME/.ccache"' >> ~/.bashrc
grep -qxF 'export CCACHE_MAXSIZE="10G"' ~/.bashrc || \
  echo 'export CCACHE_MAXSIZE="10G"' >> ~/.bashrc

source ~/.bashrc

# 写入 colcon 全局配置
mkdir -p ~/.colcon
cat > ~/.colcon/defaults.yaml << 'EOF'
build:
  cmake-args:
    - -DCMAKE_C_COMPILER_LAUNCHER=ccache
    - -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
    - -DCMAKE_BUILD_PARALLEL_LEVEL=4
    - --no-warn-unused-cli
  parallel-workers: 4
EOF

echo "配置完成,直接使用 colcon build 即可。"

保存为 setup_colcon_speedup.sh,chmod +x 后执行一次即可。


总结

  • ccache:解决重复编译问题,改一个包只编译那一个包
  • 并行数控制:解决大型工作区 OOM 问题,编译更稳定
  • ~/.colcon/defaults.yaml :一次配置,所有工作区永久生效,colcon build 无需带任何额外参数
相关推荐
闲云野鹤在人间3 小时前
MySQL|从理论、安装、备份到主从复制、MHA高可用详解
linux·运维·数据库·mysql·云计算
禾小西3 小时前
Redis:从两大维度和三大主线建立知识体系
数据库·redis·缓存
一个风轻云淡3 小时前
GCC 和 GDB命令简单解读
java·linux·前端
H.莓飛4 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
资料库014 小时前
Linux 8个常见运维故障排查
java·linux·运维
零基础1235 小时前
Ubuntu 常用命令汇总
linux·运维·开发语言
Android系统攻城狮5 小时前
Linux Gstreamer深度解析之gst_audio_sink_get_type调用流程与实战(六十五)
linux·运维·服务器·音视频·gstreamer音视频·音视频进阶·gstreamer音视频进阶
xiaoqiMikko5 小时前
Linux 实战(一):CentOS 7、Rocky 9、Ubuntu 24.04 三台真机实测 —— 认清系统、换源、装包的版本坑
linux·centos
迷途之人不知返5 小时前
【基础IO】-1-预备知识与准备工作
linux
xiaoqiMikko5 小时前
Linux 实战(二):端口不通 —— CentOS 7、Rocky 9、Ubuntu 24.04 上防火墙和 SELinux 的实测差异
linux·centos