大幅提速 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 无需带任何额外参数
相关推荐
MY_TEUCK2 小时前
【Redis 高级实战】分布式缓存、 多级缓存与最佳实践一篇打通
redis·分布式·缓存
被java抛弃的网工2 小时前
Linux基础--挣点元子(1)
linux·运维·服务器
weiwen14082 小时前
快递100 API 工具类封装实践:签名、请求与缓存防锁单
spring boot·spring·缓存
小夏子_riotous2 小时前
Docker学习路径——7、Docker搭建MySQL 主从复制
linux·运维·mysql·docker·容器·centos·云计算
派勤电子2 小时前
高性能工控机在高精度机器人中的应用
机器人·高性能工控机·高精度机器人·机器人工控主机·ut100ea·机器人工控主板·工业主板
IMPYLH2 小时前
Linux 的 sleep 命令
linux·运维·服务器·bash
Elivs.Xiang2 小时前
ubuntu20中安装gitlab
linux·ubuntu·gitlab
快乐的划水a2 小时前
单片机仿Linux驱动开发(二)
linux·驱动开发·单片机
ken22322 小时前
中文文件名:find 与 git ls-files / ls-tree 的区别
linux·搜索引擎