ROS1 Noetic 是 ROS1 系列的最后一个长期支持版本,官方原本只对 Ubuntu 20.04 提供二进制包支持。但 Ubuntu 24.04 已经发布一段时间了,不少做机器人开发的朋友手里新装的机器、新配的开发环境都是 24.04,又不想为了一个 ROS1 降级系统或者再开一台虚拟机。这种情况下,从源码编译安装 Noetic 就成了唯一可行的路子。我自己前阵子刚在一台 Ubuntu 24.04 的机器上完整走了一遍这个流程,中间踩了不少坑,也总结了一些能省时间的技巧。这篇内容就是把这套流程完整记录下来,从依赖准备、rosdep 初始化、catkin 工作空间搭建,到编译过程中常见的报错和排查方法,尽量写得细一点,让第一次上手的人也能跟着做下来。适合有基本 Linux 命令行基础、想在 Ubuntu 24.04 上跑 ROS1 的开发者参考。
1. 为什么要在 Ubuntu 24.04 上源码编译 ROS1 Noetic
1.1 官方支持现状与版本错位的现实问题
ROS1 Noetic 官方明确支持的平台是 Ubuntu 20.04 Focal。到了 Ubuntu 22.04 就已经没有官方二进制包了,24.04 更是完全不在支持列表里。这意味着你没法用apt install ros-noetic-desktop-full这种一行命令搞定的事情,apt 源里根本没有对应的包。
那为什么还有人要在 24.04 上折腾 ROS1 呢?原因其实很现实。一方面,很多实验室和公司的机器人代码库是好几年前写的,全是 ROS1 的 API,迁移到 ROS2 的成本很高,短期内不现实。另一方面,新买的硬件、新的显卡驱动、新的内核特性,往往在 24.04 上支持更好。你不可能为了跑一个老框架,把整台机器降级到 20.04,那样其他工具链又跟不上。
源码编译的本质,就是绕过 apt 的二进制分发机制,直接从源代码构建出可执行文件和库。这样做的好处是版本可控、能针对当前系统做适配;坏处是编译时间长、依赖问题多、出错概率高。所以走这条路之前,心里要有个预期:这不是一条轻松的路,但只要按步骤来,是能走通的。
1.2 源码编译相比降级系统的取舍分析
有人会问,那我直接装个 Ubuntu 20.04 的虚拟机或者双系统不就行了?这确实是一条路,但有几个问题。虚拟机的性能损耗在跑仿真、点云处理、SLAM 这类计算密集任务时很明显,GPU 直通配置也麻烦。双系统切换成本高,开发体验割裂。
源码编译的方案,优势在于所有东西都在同一个系统里,工具链统一,不用来回切换。而且编译出来的东西是针对当前系统架构和库版本优化的,理论上运行效率更好。代价就是前期配置工作量大,编译一次可能要一两个小时,中间还可能因为某个依赖版本不对而失败。
我的建议是:如果你只是临时跑一下 ROS1 的某个包,虚拟机够用;如果你是长期在 24.04 上做 ROS1 开发,那源码编译值得投入。下面这套流程,我实测下来在 24.04 上是能完整跑通的。
1.3 编译前需要明确的几个前提条件
在动手之前,先确认几件事。第一,你的磁盘空间要够,源码编译加上中间产物,至少预留 20GB 以上,我建议留 30GB 更稳妥。第二,内存最好 8GB 以上,编译某些大包的时候内存吃紧会直接 OOM 失败。第三,网络要能稳定访问 GitHub 和 PyPI,因为 rosdep 和部分依赖需要从这些地方拉取。
还有一个容易被忽略的点:Ubuntu 24.04 默认的 GCC 版本是 13,Python 是 3.12。ROS1 Noetic 的很多代码是按 GCC 9 和 Python 3.8 写的,这两个版本差异会带来不少编译错误。这是整个过程中最核心的难点,后面会专门讲怎么处理。
2. 编译环境的依赖准备与系统配置
2.1 基础编译工具链的安装
第一步是把编译需要的基础工具装齐。这些包在 24.04 的官方源里都有,直接 apt 装就行。
sudo apt update sudo apt install -y python3-pip python3-rosdep python3-rosinstall-generator python3-vcstools python3-rosinstall build-essential cmake git这里解释一下每个包的作用。build-essential提供了 gcc、g++、make 这一套编译基础,没有它什么都编不了。cmake是 ROS 构建系统 catkin 的底层依赖。python3-rosdep是依赖管理工具,负责自动安装各个 ROS 包需要的系统依赖。python3-rosinstall-generator和python3-vcstools用来生成和拉取源码清单。
装完之后验证一下版本:
gcc --version cmake --version python3 --version在 24.04 上,你应该看到 GCC 13.x、CMake 3.28.x、Python 3.12.x。记住这几个版本号,后面排查问题的时候要用到。
注意:不要试图去降级系统的 GCC 和 Python,那会破坏系统其他组件的依赖关系,得不偿失。正确的做法是在编译时针对新版本做适配,而不是把系统改回旧版本。
2.2 关键依赖库的补充安装
ROS1 Noetic 依赖一大堆第三方库,其中有一部分在 24.04 上包名变了或者需要额外安装。下面这些是我在实际编译中确认必须补上的:
sudo apt install -y libboost-all-dev libconsole-bridge-dev libtinyxml2-dev liblz4-dev libbz2-dev libeigen3-dev libyaml-cpp-dev liburdfdom-dev liburdfdom-headers-devlibboost-all-dev是重头戏,ROS 大量使用 Boost 库。24.04 自带的是 Boost 1.83,而 Noetic 当年是针对 Boost 1.71 写的,这个版本差异会导致一些 API 不兼容的问题,后面编译时会遇到。
另外还需要装 Python 相关的开发头文件:
sudo apt install -y python3-dev python3-numpy python3-yaml python3-pyparsingpython3-dev提供 Python.h 等头文件,编译 Python 扩展模块时必须要有。python3-numpy和python3-yaml是很多 ROS Python 包的运行时依赖。
2.3 rosdep 的初始化与国内源配置
rosdep 是 ROS 的依赖管理工具,它会读取每个包的 package.xml,自动解析出需要安装的系统依赖。初始化命令是:
sudo rosdep init rosdep update但这里有个现实问题:rosdep init会去访问 raw.githubusercontent.com 拉取默认的源列表,国内网络环境下大概率会超时失败。解决办法是手动创建配置文件,指定国内的镜像源。
先手动创建目录和文件:
sudo mkdir -p /etc/ros/rosdep/sources.list.d然后创建/etc/ros/rosdep/sources.list.d/20-default.list文件,内容指向国内可访问的镜像。具体用哪个镜像,可以根据自己网络环境选择,这里不展开具体地址,思路就是找一个能稳定访问的 rosdistro 镜像仓库。
配置好之后执行rosdep update,如果能看到一堆 "Hit" 或者 "Read" 的输出,最后显示 updated cache,就说明成功了。这一步失败的话后面编译会寸步难行,因为所有依赖都得手动装,工作量巨大。
实操心得:rosdep update 有时候会因为缓存问题反复失败,可以试试先
sudo rm -rf /home/$USER/.ros/rosdep清掉旧缓存再重新 update。另外 update 的时候不要挂全局代理,有时候反而会因为代理规则问题导致部分请求失败。
3. 源码拉取与工作空间搭建
3.1 用 rosinstall_generator 生成源码清单
ROS1 的源码分布在几百个独立的 git 仓库里,手动一个个 clone 不现实。官方提供了rosinstall_generator工具来生成清单文件。
我建议编译desktop_full版本,它包含了 ROS 核心、常用工具(rviz、rqt)、仿真(gazebo 相关)、导航等大部分常用功能。命令如下:
mkdir -p ~/ros_catkin_ws cd ~/ros_catkin_ws rosinstall_generator desktop_full --rosdistro noetic --deps --tar > noetic-desktop_full.rosinstall这里几个参数说明一下。--deps表示把依赖包也一起包含进来,不加的话只会列出顶层包,编译时会缺依赖。--tar表示使用 release 版本的 tarball 而不是 git 仓库的最新提交,这样版本更稳定,不会因为上游某个提交引入的 bug 导致编译失败。这个选择很重要,我强烈建议加上--tar。
生成的.rosinstall文件是一个 YAML 格式的清单,里面列出了每个包的名称、版本和下载地址。你可以打开看看,大概有 200 多个条目。
3.2 拉取源码与目录结构说明
有了清单文件,用wstool来批量拉取:
wstool init src noetic-desktop_full.rosinstall这个命令会把所有源码下载到src目录下。下载时间取决于网络,快的话十几分钟,慢的话可能要一个小时。如果中途断了,可以重复执行同样的命令,wstool 会跳过已经下载好的部分继续。
拉完之后看一下目录结构:
ls src你会看到一堆以包名命名的文件夹,比如ros_comm、geometry、robot_model、navigation等等。每个文件夹里是一个独立的 catkin 包,有自己的package.xml和CMakeLists.txt。
注意:不要随意删除或修改 src 里的包,除非你明确知道自己在做什么。有些包之间有复杂的依赖关系,删一个可能导致一大片编译失败。
3.3 用 rosdep 安装所有系统依赖
源码拉下来只是第一步,这些包还依赖大量的系统库。这时候 rosdep 就派上用场了:
rosdep install --from-paths src --ignore-src --rosdistro noetic -y逐个参数解释:--from-paths src表示从 src 目录下的所有包读取依赖信息;--ignore-src表示如果某个依赖已经在 src 里以源码形式存在,就不要再去 apt 装了;--rosdistro noetic指定发行版;-y表示自动确认,不用一个个手动敲 yes。
这一步会安装几百个系统包,时间比较长。如果中途有包安装失败,rosdep 会报错并列出是哪个包、缺什么依赖。常见的失败原因是某个包在 24.04 的源里改名了或者被移除了,需要手动处理。
我遇到的一个典型问题是某些 Python 2 时代的包在 24.04 里已经彻底没有了,rosdep 会报 "unable to resolve" 之类的错误。这种情况下需要手动编辑对应包的 package.xml,把那个依赖去掉或者替换成 Python 3 的等价包。
4. 针对 Ubuntu 24.04 的编译适配与核心难点
4.1 GCC 13 带来的编译错误与处理
这是整个过程中最麻烦的部分。GCC 13 比 GCC 9 严格很多,一些老的 C++ 代码在新编译器下会直接报错。我遇到的主要有几类:
第一类是头文件缺失。GCC 13 移除了一些隐式的头文件包含,很多老代码没有显式#include <cstdint>就用了uint32_t这类类型,在旧编译器下能过,新编译器下就报 "uint32_t does not name a type"。解决办法是在报错的文件里手动加上缺失的头文件。
第二类是-Werror导致的警告变错误。有些包的 CMakeLists.txt 里开了-Werror,GCC 13 产生的新警告会被当成错误。可以在编译时加-DCMAKE_CXX_FLAGS="-Wno-error"来临时关掉。
第三类是 C++ 标准问题。Noetic 默认用 C++14,但有些代码在 GCC 13 下需要 C++17 才能编过。可以在 catkin 配置时指定标准:
catkin_make -DCMAKE_CXX_STANDARD=17我实测下来,大部分包在 C++17 下都能正常编译,少数包可能需要单独调整。
4.2 Python 3.12 相关的兼容性修复
Python 3.12 相比 3.8 也有不少变化。最典型的是distutils模块被标记为废弃,而 ROS1 的一些构建脚本还在用它。如果报 "No module named distutils",需要装:
sudo apt install python3-setuptools python3-distutils在 24.04 上python3-distutils可能已经不存在了,那就装python3-setuptools并通过 setuptools 提供的兼容层来解决。
另一个常见问题是empy模块。ROS 的消息生成依赖 empy,但 24.04 源里的 empy 版本可能和 Noetic 期望的不一致。如果报 empy 相关的错误,可以试试用 pip 装指定版本:
pip3 install empy==3.3.4实操心得:Python 相关的编译错误往往比较隐蔽,报错信息可能指向一个完全不相关的文件。遇到莫名其妙的 Python 报错时,先检查是不是某个基础模块的版本问题,而不是急着去改 ROS 的源码。
4.3 Boost 1.83 的 API 变更应对
Boost 从 1.71 到 1.83 之间有一些 API 被移除或改了签名。ROS 里受影响比较大的是boost::shared_ptr相关的用法和boost::filesystem的一些函数。
如果编译时报 Boost 相关的错误,先看具体是哪个函数。大部分情况下,把boost::替换成std::对应的类型(比如boost::shared_ptr换成std::shared_ptr)就能解决。但这样做需要改源码,比较麻烦。
另一个思路是看能不能通过定义宏来绕过。比如某些 Boost 版本检查的代码,可以通过定义BOOST_FILESYSTEM_VERSION=3之类的宏来适配。具体怎么改要看报错信息,没有一刀切的方案。
我个人的经验是,Boost 相关的问题主要集中在少数几个包里,大部分包是不受影响的。遇到一个解决一个,不要试图提前把所有 Boost 问题都找出来。
5. 编译执行与过程监控
5.1 catkin_make 的首次编译与参数配置
依赖都装好、适配问题也处理得差不多了,就可以开始编译了。在~/ros_catkin_ws目录下执行:
cd ~/ros_catkin_ws catkin_make -DCMAKE_CXX_STANDARD=17 -DCMAKE_BUILD_TYPE=Release -j4参数说明:-DCMAKE_CXX_STANDARD=17指定 C++ 标准;-DCMAKE_BUILD_TYPE=Release表示编译优化版本,运行效率更高,但编译时间更长,调试阶段也可以用 Debug;-j4表示用 4 个线程并行编译,这个数字根据你机器的 CPU 核心数调整,一般设为核心数或者核心数的一半。
首次编译时间很长,我这边 8 核机器大概跑了一个半小时。中间会刷大量的编译输出,只要不出现红色的 Error,就让它跑着。
5.2 编译过程中的错误定位方法
编译失败是常态,关键是怎么快速定位问题。catkin_make 的输出很长,直接往上翻很难找到第一个错误。我的做法是把输出重定向到文件,然后搜索:
catkin_make -DCMAKE_CXX_STANDARD=17 -j4 2>&1 | tee build.log grep -n "error:" build.log | head -20这样能快速找到前 20 个错误的位置。注意,第一个错误往往是最关键的,后面的错误很多是它引发的连锁反应。先解决第一个,再重新编译看还有没有。
如果错误集中在某个特定的包,可以单独编译那个包来加快调试速度:
catkin_make --pkg 包名 -DCMAKE_CXX_STANDARD=17这样只编译指定的包和它的依赖,比全量编译快很多。
5.3 增量编译与断点续编技巧
catkin_make 本身支持增量编译,已经编好的包不会重复编译。所以如果编译到一半失败了,解决完问题直接重新执行 catkin_make 就行,它会从失败的地方继续。
但有个坑要注意:如果你修改了某个包的源码或者 CMakeLists.txt,catkin 可能会重新编译依赖它的所有包,这个范围可能很大。所以改代码之前想清楚影响范围。
另外,如果编译过程中因为内存不足被系统 kill 了,可以降低并行度,比如把-j4改成-j2甚至-j1,虽然慢但更稳。
实操心得:编译大包(比如
moveit、gazebo_ros)的时候特别吃内存,如果机器内存小于 16GB,建议编译这些包时单独用-j1,避免 OOM。我就在编译moveit_core的时候被 OOM 干掉过一次,白白浪费了半小时。
6. 环境配置与安装验证
6.1 setup.bash 的加载与验证
编译成功后,工作空间里会生成devel目录,里面有环境配置脚本。加载它:
source ~/ros_catkin_ws/devel/setup.bash为了每次开终端都自动加载,把这行加到~/.bashrc末尾:
echo "source ~/ros_catkin_ws/devel/setup.bash" >> ~/.bashrc source ~/.bashrc然后验证核心命令是否可用:
roscore如果能看到 "started core service" 之类的输出,说明核心已经跑起来了。再开一个终端,运行:
rosrun turtlesim turtlesim_node如果弹出一个小乌龟的窗口,恭喜你,ROS1 Noetic 在 Ubuntu 24.04 上算是装好了。
6.2 常见运行时问题的排查
装好之后运行时也可能遇到问题。最常见的是找不到包或者找不到库。如果报 "Package not found",先确认ROS_PACKAGE_PATH环境变量是否正确包含了你的工作空间:
echo $ROS_PACKAGE_PATH如果报某个.so文件找不到,用ldd检查依赖:
ldd /path/to/your/binary | grep "not found"缺哪个库就装哪个。有时候是库的版本不对,需要手动指定LD_LIBRARY_PATH。
还有一个 24.04 特有的问题是 Wayland 显示协议。24.04 默认用 Wayland,而 ROS 的一些 GUI 工具(rviz、rqt)在 Wayland 下可能显示异常。解决办法是登录时切换到 X11 会话,或者设置QT_QPA_PLATFORM=xcb环境变量强制用 X11 后端。
6.3 编译产物的清理与重装
如果编译过程中改了很多东西,最后想从头来一遍,可以清理工作空间:
cd ~/ros_catkin_ws rm -rf build devel然后重新catkin_make。注意不要删src,那是源码,删了就得重新下载。
如果只是想清理某个包的编译产物,可以进到build目录下删对应的文件夹,但这样容易导致依赖关系混乱,不太推荐。要么全清,要么不动。
7. 常见问题速查与避坑经验
7.1 编译错误速查表
| 错误信息关键词 | 可能原因 | 解决方法 |
|---|---|---|
uint32_t does not name a type | GCC 13 缺少隐式头文件包含 | 在报错文件加#include <cstdint> |
No module named distutils | Python 3.12 移除 distutils | 安装python3-setuptools |
empy相关错误 | empy 版本不匹配 | pip3 install empy==3.3.4 |
boost::shared_ptr相关错误 | Boost 版本 API 变更 | 替换为std::shared_ptr或定义兼容宏 |
-Werror导致的警告变错误 | GCC 13 警告更严格 | 加-DCMAKE_CXX_FLAGS="-Wno-error" |
| 编译到一半被 kill | 内存不足 OOM | 降低并行度-j1或增加 swap |
Could not find a package configuration file | 依赖包没装或路径不对 | 检查 rosdep 是否完整执行 |
7.2 几个容易忽略的细节
第一个细节是 swap 空间。24.04 默认可能没开 swap 或者 swap 很小,编译大包时内存不够会直接崩。建议手动开一个 8GB 的 swap 文件:
sudo fallocate -l 8G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile第二个细节是编译时的 locale 设置。有些包的 CMake 脚本对 locale 敏感,如果系统 locale 是中文,可能出现编码相关的编译错误。可以在编译前临时设置:
export LC_ALL=C第三个细节是时间同步。如果系统时间不对,git clone 和 rosdep update 可能因为证书验证失败而报错。用timedatectl检查一下时间是否同步。
7.3 长期维护的建议
源码编译安装的 ROS 不像 apt 装的那么好维护。apt 装的可以用apt upgrade统一更新,源码编译的得手动进到 src 里git pull然后重新编译。
我的建议是,装好之后把整个~/ros_catkin_ws目录打个快照或者备份一下,万一哪天编译环境被搞坏了,可以直接恢复,不用重新走一遍几个小时的编译流程。
另外,如果后续要装额外的 ROS 包,尽量也用源码方式装到同一个工作空间的 src 里,保持环境统一。混用 apt 装的 ROS 包和源码编译的包,很容易出现版本冲突和路径混乱。
最后分享一个小技巧:编译完成后,可以用
catkin_make install把产物安装到install目录,然后 source 那个目录的 setup.bash。这样做的好处是 devel 目录可以随时删掉重新编译,不影响已安装的版本,相当于多了一层保险。
这套流程我在两台不同配置的 Ubuntu 24.04 机器上都跑通过,一台是 8 核 16GB 的台式机,一台是 12 核 32GB 的服务器。配置高的机器主要优势在编译速度,内存大的机器在编译大包时更稳。如果你的机器配置一般,建议分批次编译,先编核心包,确认没问题再编桌面和仿真部分,这样出问题时排查范围小,不至于一上来就面对几百个包的编译错误。