跳到主要内容

RFrame 编译指南

文档总入口:《RFrame 使用入口》

1. 文档定位​

本文面向使用已安装 RFrame SDK 的 C++ 和 Python 用户,说明:

  • C++ 工程如何通过 CMake 消费 RFrame;
  • 应该声明哪些 component、链接哪些 target;
  • Python wheel 如何与 native RFrame 保持一致;
  • 编译期、Python binding 和运行期环境变量如何管理;
  • RFrameExample 中可以参考哪些文件。

本文不涉及 RFrame 框架源码编译和 SDK 制作。软件包安装与运行配置见《RFrame 部署指南》,Channel API 见《RFrame 开发指南》。

参考工程:deb 包 robby-r-frame-example(安装后位于 /opt/robby/RFrameExample/)。

2. C++ 用户接入​

2.1. 编译前提​

  • CMake 3.10 或更高版本;
  • 支持 C++17 的编译器;
  • 已安装匹配版本的 r-frame SDK;
  • 使用 ROS 2 消息类型时,已安装并加载 ROS 2 Humble;
  • 使用自定义消息类型时,已安装并加载对应消息工作区。
cmake --version
c++ --version
dpkg-query -W r-frame

使用 ROS 2 类型时,必须在 CMake configure 前执行:

source /opt/ros/humble/setup.bash
source /path/to/message_workspace/install/setup.bash # 自定义类型时

不要手工设置 AMENT_PREFIX_PATH 或 ROS 相关的多个 CMake 路径;以 source 对应 setup.bash 为准。

标准 deb 安装的布局如下,RFrame 本体和底层依赖库都放在 /usr/local/lib 下:

内容安装路径
RFrame 本体库 libr_frame_*.so/usr/local/lib/
随包底层库(如 libecdr.so)/usr/local/lib/
C++ 头文件/usr/local/include/r、/usr/local/include/r_c
CMake package/usr/local/lib/cmake/r-frame/
Channel/Runtime 插件 .so(r-frame-plugin deb)/usr/local/lib/<插件名>/
插件默认 catalog/opt/robby/r-frame/config/plugins.json
随包第三方底层依赖(fastcdr、rosidl typesupport 等)/opt/robby/r-frame/lib/third_party/
Python wheel/usr/local/lib/rframe/

find_package(r-frame) 默认能在 /usr/local/lib/cmake/r-frame 找到配置;/usr/local/lib 下的库由系统动态链接器自动解析,正常不需要额外设置 LD_LIBRARY_PATH。

2.2. 推荐 CMake 写法​

用户工程只声明代码直接使用的 RFrame component,并链接对应命名空间 target:

cmake_minimum_required(VERSION 3.10)
project(my_rframe_app LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

find_package(r-frame REQUIRED COMPONENTS channel app log)

add_executable(my_rframe_app main.cpp)
target_link_libraries(my_rframe_app
PRIVATE
r::channel
r::app
r::log
)

配置和编译:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4

RFrame 的 CMake package 会加载所请求 component 的传递依赖。用户工程不应重复 find_package 或硬编码 Boost、Protobuf、jsoncpp 等 SDK 内部依赖。

2.3. Component 和 target 选择​

用户代码直接使用find_package component链接 target
AppCoreappr::app
日志 APIlogr::log
ChannelManager、Hybrid Topic/RPCchannelr::channel

Target 规则:

  • r::<component>:推荐;
  • r::frame:聚合 target,仅在确实直接使用大量模块时采用;
  • r_frame_<component>:旧工程兼容写法,不作为新工程首选。

2.4. RFrameExample 参考路径​

示例源码由 deb 包交付,下表路径均相对 /opt/robby/RFrameExample/:

需求参考文件
最小 find_package 和 target 写法src/find_package_usage/CMakeLists.txt
日志依赖声明src/log/CMakeLists.txt
AppCore/核心依赖声明src/core/CMakeLists.txt
Channel demo targetsrc/channel/CMakeLists.txt
ChannelManager 基础示例src/channel/quickstart/channel_manager_example.cpp
JSON 配置检查器src/channel/config/channel_config_json_example.cpp
typed Hybrid Topicsrc/channel/typed/typed_channel_example.cpp
typed Hybrid RPCsrc/channel/typed/typed_rpc_example.cpp

需要验证 SDK 接入时,安装示例 deb 后独立编译最小 Channel 示例(散装单元,无需克隆仓库):

sudo apt install robby-r-frame-example
source /opt/ros/humble/setup.bash

cmake -S /opt/robby/RFrameExample/src/channel -B build/channel -DCMAKE_BUILD_TYPE=Release
cmake --build build/channel -j4 --target \
channel_manager_example channel_config_json_example \
typed_channel_example typed_rpc_example

typed_rpc_example 依赖 example_interfaces(sudo apt install ros-${ROS_DISTRO}-example-interfaces);环境缺失时该目标会被自动跳过,其余示例不受影响。

2.5. 非系统安装路径​

SDK 不在标准安装路径时,用 CMAKE_PREFIX_PATH 指定该 SDK:

cmake -S . -B build \
-DCMAKE_PREFIX_PATH=/path/to/rframe/install \
-DCMAKE_BUILD_TYPE=Release
cmake --build build -j4

多个前缀用分号分隔:

cmake -S . -B build \
'-DCMAKE_PREFIX_PATH=/path/to/rframe/install;/usr/local'

不要用 link_directories() 或手工 .so 路径代替 find_package。

3. Python wheel 保障​

3.1. 交付关系​

r-frame deb 同时交付:

  • native RFrame library;
  • 系统 Python binding:/usr/lib/python3/dist-packages/rframe;
  • 同批次 wheel:/usr/local/lib/rframe/rframe-*.whl。

wheel 的版本来自与 deb 相同的构建 tag。wheel 只提供 Python binding,不能脱离同批次 native r-frame 使用。

3.2. 系统 Python​

系统 Python 直接使用 deb 安装的 binding,不需要再次执行 pip:

/usr/bin/python3 -c \
'import rframe; print(rframe.__file__, rframe.__version__, rframe.__build_tag__)'

3.3. 虚拟环境或自定义 Python​

虚拟环境安装 deb 内同批次 wheel:

python3 -m venv --system-site-packages .venv
source .venv/bin/activate

ls /usr/local/lib/rframe/rframe-*.whl
python -m pip install --no-deps /usr/local/lib/rframe/rframe-*.whl
python -c \
'import rframe; print(rframe.__file__, rframe.__version__, rframe.__build_tag__)'

使用 ROS 2 Python 消息时保留 --system-site-packages,使虚拟环境能够访问系统安装的 ROS 2 模块。纯 SHM 且不依赖系统消息包时可以省略。

禁止以下组合:

  • 只复制 wheel,不安装 native r-frame;
  • 使用另一个发布批次生成的 wheel;
  • 系统 Python、虚拟环境和 Conda 环境之间混用 site-packages;
  • 用 PYTHONPATH 指向 RFrame 源码目录替代正式 wheel。

3.4. 3.4 版本一致性检查​

dpkg-query -W -f='${Version}\n' r-frame
python -c \
'import rframe; print(rframe.__version__, rframe.__build_tag__)'

__build_tag__ 应对应已安装 deb 的构建批次。PEP 440 wheel 版本和 Debian 版本的标点可能不同,应比较版本主体、rc/dev 编号和构建时间戳。

3.5. Python 示例参考​

以下文件均相对 deb 安装路径 /opt/robby/RFrameExample/:

需求文件
日志python/log_example.py
typed Hybrid Topicpython/typed_channel_interop.py
Hybrid RPC、JSON 映射、C++ 互通python/rpc_interop.py

示例运行方式见《RFrame 开发指南》。

4. 环境变量和路径保障​

4.1. 变量分类​

变量或环境阶段正式用法
CMAKE_PREFIX_PATHC++ configure仅在 SDK 非标准安装路径时设置
ROS 2 setup.bashC++ configure / Python 运行使用 ROS 2 类型或后端时 source
消息工作区 setup.bashC++ configure / Python 运行使用自定义消息或 service 时 source
RFRAME_C_API_LIBPython native binding仅用于非标准 native library 路径或诊断
LD_LIBRARY_PATH运行时诊断标准 deb 安装不设置;仅临时验证非标准 SDK
PYTHONPATHPython import正式安装不设置;通过 deb 或 wheel 提供 binding
RFRAME_CONFIG_PATH应用运行选择全局 rframe.json,见部署指南
RFRAME_LOG_LEVEL应用运行覆盖全局日志级别,见部署指南

4.2. RFRAME_C_API_LIB​

Python binding 通过 native C API library 工作。标准 deb 安装应由动态链接器自动找到该库,不需要设置变量。

仅在验证非标准 SDK 时显式指定:

export RFRAME_C_API_LIB=/path/to/libr_frame_c_api.so
python -c 'import rframe; print(rframe.__file__)'

该变量必须指向与 wheel 同批次的 library,用完后取消:

unset RFRAME_C_API_LIB

4.3. LD_LIBRARY_PATH​

标准 deb 安装的 RFrame 本体库和底层依赖库都在 /usr/local/lib 下(见 §2.1 安装布局),由系统动态链接配置自动解析,不应要求业务设置 LD_LIBRARY_PATH。只有验证非标准 SDK 时临时设置:

export LD_LIBRARY_PATH=/path/to/rframe/install/lib:${LD_LIBRARY_PATH:-}
ldd build/my_rframe_app

不要把该变量写入正式启动脚本来掩盖 SDK 混装问题。

4.4. 运行期变量​

RFRAME_CONFIG_PATH 和 RFRAME_LOG_LEVEL 不参与 CMake 和 wheel 安装。它们只在应用运行时生效,配置方式见《RFrame 部署指南》。

5. 用户工程验证​

5.1. C++​

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
ldd build/my_rframe_app

确认:

  • CMake 从预期 SDK 找到 r-frame;
  • 编译和链接成功;
  • ldd 显示 RFrame 与依赖来自同一套安装;
  • ROS 2 type support 来自已 source 的目标工作区。

5.2. Python​

python -c \
'import rframe; print(rframe.__file__, rframe.__version__, rframe.__build_tag__)'

确认:

  • import 路径属于预期系统 Python 或虚拟环境;
  • wheel build tag 与 native deb 对应;
  • 标准安装没有依赖源码 PYTHONPATH;
  • RFRAME_C_API_LIB 未意外指向另一套 SDK。

6. 常见问题​

6.1. CMake 找不到 r-frame​

检查 SDK 是否安装,以及 CMAKE_PREFIX_PATH 是否指向包含 lib/cmake/r-frame 的安装前缀。

6.2. 找不到 ROS 2 或自定义类型​

重新 source ROS 2 和消息工作区后,删除旧的用户工程 CMake cache 并重新 configure。

6.3. C++ 链接到错误版本​

用 ldd 检查实际 library;清理错误的 CMAKE_PREFIX_PATH、LD_LIBRARY_PATH 和旧 build cache,不要手工补 link_directories()。

6.4. Python 无法导入或加载 native library​

依次检查:

  1. 当前 Python 解释器;
  2. rframe.__file__;
  3. wheel 是否来自 /usr/local/lib/rframe/;
  4. native r-frame deb 是否安装且版本匹配;
  5. RFRAME_C_API_LIB 是否错误覆盖。