大幅提速 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 buildcache 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.shchmod +x 后执行一次即可。


总结

  • ccache:解决重复编译问题,改一个包只编译那一个包
  • 并行数控制:解决大型工作区 OOM 问题,编译更稳定
  • ~/.colcon/defaults.yaml :一次配置,所有工作区永久生效,colcon build 无需带任何额外参数
相关推荐
zylyehuo11 小时前
Linux 彻底且安全地删除文件
linux
用户805533698031 天前
主线 U-Boot 上 RK3506:和闭源 rkbin 拔河的三个隐性契约
linux·嵌入式
用户034095297911 天前
linux fcitx 5 雾凇拼音 设置在中文输入法下仍然输入英文标点
linux
小七-七牛开发者3 天前
TokenPilot:让 LLM Agent 长会话成本降 60%+ 的上下文管理
缓存·agent·token·context·上下文·推理成本
Web3探索者3 天前
可视化服务器管理和传统命令行区别是什么?新手教程:Linux 运维到底该用图形界面还是 SSH 命令行?
linux·ssh
zylyehuo3 天前
Linux系统中网线与USB网络共享冲突
linux
Sokach10154 天前
Linux Shell 脚本从零到能用:一个新手的一天学习总结
linux
AlfredZhao5 天前
Docker 容器时区不对,`timedatectl` 不存在怎么办?
linux·timezone
zzzzzz3106 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql