大幅提速 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 无需带任何额外参数
相关推荐
明志数科24 分钟前
4D时序标注技术详解:让机器人理解连续动作的数据基础
java·算法·机器人
Peace41 分钟前
【Prometheus】
linux·运维·prometheus
XWalnut2 小时前
Redis从入门到精通
数据库·redis·缓存
LZZ and MYY2 小时前
RTS 在windows和Linux之间ShareMem
linux·运维·服务器
aningx2 小时前
openSUSE Leap 16.0 运行 sunshine 报错的解决方法
linux
爱学习的徐徐2 小时前
Linux 基础IO
linux·服务器
xiaofeichaichai3 小时前
Service Worker、PWA 与 Web Worker — 离线缓存与主线程算力分离
前端·缓存
xiaobobo33303 小时前
面向对象:linux内核中函数转数据的用法
linux·面向对象·隔离·函数指针绑定
姓刘的哦3 小时前
C++软件架构设计思路
linux
ModestCoder_3 小时前
windows/ubuntu解决挂梯子但是codex reconnecting五次的问题
linux·windows·ubuntu