大幅提速 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 无需带任何额外参数
相关推荐
吴声子夜歌5 小时前
Shell编程实例——高级脚本编程(一)
linux·运维·网络·shell
Huangjin007_6 小时前
【Linux 系统篇(二十一)】进程(九):进程等待 wait/waitpid、status状态参数
linux·运维·服务器
deepfu6 小时前
微信 API 消息模块:发送视频消息的流程与优化点
微信·机器人
螺蛳粉 螺蛳粉6 小时前
mysql的备份与恢复
linux·运维·数据库·mysql
ao-weilai6 小时前
Linux网络编程:Socket UDP
linux·服务器·网络·c++
风合星语6 小时前
2026 机器人行业观察(三):机器人走进酒店和门店——完成一次演示,和顶一个班差在哪?
人工智能·机器人·具身智能·人形机器人·人机协作
爱吃香菜的初学者7 小时前
九.Linux——文件操作
linux
星云API技术支持7 小时前
企业微信二次开发实战:群聊、单聊与系统事件如何建立统一处理机制
机器人·yapi·企业微信
园长的牧歌7 小时前
Ubuntu 打开应用在导航栏没有图标是个齿轮
linux·ubuntu
曦夜日长7 小时前
Linux系统篇,进程概念(四):内核链表的深度理解、进程优先级的底层理解
linux·运维·服务器·php