RFrame Build Guide
Documentation entry point: Getting Started with RFrame.
1. Scope
For C++ and Python users of an installed RFrame SDK, this guide explains:
- How C++ projects consume RFrame through CMake.
- Which components to declare and targets to link.
- How to keep Python wheels consistent with native RFrame.
- How to manage build-time, Python binding, and runtime environment variables.
- Which RFrameExample files to reference.
Building the framework source and producing SDK packages are outside this guide's scope. See the RFrame Deployment Guide for package installation and runtime configuration, and the RFrame Development Guide for Channel APIs.
Reference project: the robby-r-frame-example deb package, installed at /opt/robby/RFrameExample/.
2. C++ integration
2.1. Build prerequisites
- CMake 3.10 or later.
- A compiler supporting C++17.
- A matching
r-frameSDK installed. - ROS 2 Humble installed and sourced when using ROS 2 message types.
- The corresponding message workspace installed and sourced when using custom message types.
cmake --version
c++ --version
dpkg-query -W r-frame
For ROS 2 types, run this before CMake configuration:
source /opt/ros/humble/setup.bash
source /path/to/message_workspace/install/setup.bash # For custom types
Do not manually set AMENT_PREFIX_PATH or multiple ROS-related CMake paths; source the corresponding setup.bash instead.
The standard deb layout is shown below. RFrame libraries and underlying dependencies are installed under /usr/local/lib:
| Contents | Installation path |
|---|---|
RFrame libraries libr_frame_*.so | /usr/local/lib/ |
Bundled underlying libraries, such as libecdr.so | /usr/local/lib/ |
| C++ headers | /usr/local/include/r, /usr/local/include/r_c |
| CMake package | /usr/local/lib/cmake/r-frame/ |
Channel/Runtime plugin .so files (r-frame-plugin deb) | /usr/local/lib/<plugin-name>/ |
| Default plugin catalog | /opt/robby/r-frame/config/plugins.json |
| Bundled third-party dependencies (fastcdr, rosidl typesupport, etc.) | /opt/robby/r-frame/lib/third_party/ |
| Python wheel | /usr/local/lib/rframe/ |
find_package(r-frame) finds the configuration in /usr/local/lib/cmake/r-frame by default. The system dynamic linker resolves libraries in /usr/local/lib, so setting LD_LIBRARY_PATH is normally unnecessary.
2.2. Recommended CMake configuration
Declare only the RFrame components directly used by your code, and link their namespaced targets:
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
)
Configure and build:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
The RFrame CMake package loads transitive dependencies of requested components. Do not repeat find_package calls or hardcode SDK-internal dependencies such as Boost, Protobuf, or jsoncpp in application projects.
2.3. Select components and targets
| Directly used in application code | find_package component | Link target |
|---|---|---|
AppCore | app | r::app |
| Logging API | log | r::log |
ChannelManager、Hybrid Topic/RPC | channel | r::channel |
Target rules:
r::<component>: recommended.r::frame: aggregate target; use only when directly using many modules.r_frame_<component>: compatibility syntax for older projects, not preferred for new projects.
2.4. RFrameExample reference paths
Example sources are delivered in the deb package. Paths below are relative to /opt/robby/RFrameExample/:
| Requirement | Reference file |
|---|---|
Minimal find_package and target usage | src/find_package_usage/CMakeLists.txt |
| Logging dependency declaration | src/log/CMakeLists.txt |
AppCore/core dependency declaration | src/core/CMakeLists.txt |
| Channel demo target | src/channel/CMakeLists.txt |
Basic ChannelManager example | src/channel/quickstart/channel_manager_example.cpp |
| JSON configuration checker | src/channel/config/channel_config_json_example.cpp |
| typed Hybrid Topic | src/channel/typed/typed_channel_example.cpp |
| typed Hybrid RPC | src/channel/typed/typed_rpc_example.cpp |
To validate SDK integration, install the example deb and independently build the minimal Channel examples. They are standalone units; cloning the repository is unnecessary:
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 depends on example_interfaces (sudo apt install ros-${ROS_DISTRO}-example-interfaces). If unavailable, this target is skipped automatically without affecting other examples.
2.5. Nonstandard installation paths
For an SDK outside standard installation paths, specify it with CMAKE_PREFIX_PATH:
cmake -S . -B build \
-DCMAKE_PREFIX_PATH=/path/to/rframe/install \
-DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
Separate multiple prefixes with semicolons:
cmake -S . -B build \
'-DCMAKE_PREFIX_PATH=/path/to/rframe/install;/usr/local'
Do not replace find_package with link_directories() or manually specified .so paths.
3. Python wheel compatibility
3.1. Delivered components
The r-frame deb includes:
- native RFrame library;
- System Python binding:
/usr/lib/python3/dist-packages/rframe. - A wheel from the same build:
/usr/local/lib/rframe/rframe-*.whl.
The wheel version comes from the same build tag as the deb. It supplies only Python bindings and cannot be used without the native r-frame from the same build.
3.2. System Python
System Python directly uses the binding installed by the deb; no additional pip installation is required:
/usr/bin/python3 -c \
'import rframe; print(rframe.__file__, rframe.__version__, rframe.__build_tag__)'
3.3. Virtual environments or custom Python
Install the wheel bundled with the deb into the virtual environment:
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__)'
Keep --system-site-packages when using ROS 2 Python messages, allowing access to system-installed ROS 2 modules. It can be omitted for SHM-only use without system message packages.
Do not use these combinations:
- Copying only the wheel without installing native
r-frame. - Using a wheel from another release build.
- Mixing site-packages between system Python, virtual environments, and Conda.
- Pointing
PYTHONPATHat RFrame source instead of using the official wheel.
3.4. Check version consistency
dpkg-query -W -f='${Version}\n' r-frame
python -c \
'import rframe; print(rframe.__version__, rframe.__build_tag__)'
__build_tag__ should match the installed deb's build. PEP 440 wheel versions and Debian versions may differ in punctuation; compare the main version, rc/dev number, and build timestamp.
3.5. Python example references
Paths below are relative to /opt/robby/RFrameExample/ in the deb installation:
| Requirement | File |
|---|---|
| Logging | python/log_example.py |
| typed Hybrid Topic | python/typed_channel_interop.py |
| Hybrid RPC, JSON mapping, C++ interoperability | python/rpc_interop.py |
See the RFrame Development Guide for running these examples.
4. Environment variables and paths
4.1. Variable categories
| Variable or environment | Stage | Intended usage |
|---|---|---|
CMAKE_PREFIX_PATH | C++ configure | Set only for nonstandard SDK installation paths |
ROS 2 setup.bash | C++ configure / Python runtime | Source when using ROS 2 types or backends |
Message workspace setup.bash | C++ configure / Python runtime | Source when using custom messages or services |
RFRAME_C_API_LIB | Python native binding | Nonstandard native library paths or diagnosis only |
LD_LIBRARY_PATH | Runtime diagnosis | Unset for standard deb installations; temporary nonstandard SDK validation only |
PYTHONPATH | Python import | Unset for production installation; use deb or wheel bindings |
RFRAME_CONFIG_PATH | Application runtime | Select global rframe.json; see the deployment guide |
RFRAME_LOG_LEVEL | Application runtime | Override the global log level; see the deployment guide |
4.2. RFRAME_C_API_LIB
Python bindings use the native C API library. With a standard deb installation, the dynamic linker should find it automatically; no variable is needed.
Specify it explicitly only when validating a nonstandard SDK:
export RFRAME_C_API_LIB=/path/to/libr_frame_c_api.so
python -c 'import rframe; print(rframe.__file__)'
The variable must point to a library from the same build as the wheel. Unset it afterwards:
unset RFRAME_C_API_LIB
4.3. LD_LIBRARY_PATH
Standard deb installations place RFrame and its underlying libraries in /usr/local/lib (see §2.1). System dynamic-linker configuration resolves them automatically; application code should not require LD_LIBRARY_PATH. Set it temporarily only for nonstandard SDK validation:
export LD_LIBRARY_PATH=/path/to/rframe/install/lib:${LD_LIBRARY_PATH:-}
ldd build/my_rframe_app
Do not add this variable to production startup scripts to conceal mixed SDK installations.
4.4. Runtime variables
RFRAME_CONFIG_PATH and RFRAME_LOG_LEVEL do not affect CMake or wheel installation. They apply only at application runtime; see the RFrame Deployment Guide.
5. Validate an application project
5.1. C++
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j4
ldd build/my_rframe_app
Confirm:
- CMake finds
r-framein the intended SDK. - Compilation and linking succeed.
lddresolves RFrame and dependencies from the same installation.- ROS 2 type support comes from the intended sourced workspace.
5.2. Python
python -c \
'import rframe; print(rframe.__file__, rframe.__version__, rframe.__build_tag__)'
Confirm:
- The import path belongs to the intended system Python or virtual environment.
- The wheel build tag matches the native deb.
- The standard installation does not depend on source-code
PYTHONPATH. RFRAME_C_API_LIBdoes not accidentally point to another SDK.
6. Troubleshooting
6.1. CMake cannot find r-frame
Check that the SDK is installed and that CMAKE_PREFIX_PATH points to the installation prefix containing lib/cmake/r-frame.
6.2. ROS 2 or custom types cannot be found
Source ROS 2 and the message workspace again, remove the old application CMake cache, and reconfigure.
6.3. C++ links against the wrong version
Inspect actual libraries with ldd. Clear incorrect CMAKE_PREFIX_PATH, LD_LIBRARY_PATH, and old build caches. Do not patch the problem with link_directories().
6.4. Python import or native library loading fails
Check in order:
- The current Python interpreter.
rframe.__file__;- Whether the wheel comes from
/usr/local/lib/rframe/. - Whether native
r-frameis installed with a matching version. - Whether
RFRAME_C_API_LIBincorrectly overrides the library path.