Integrating OSIUtilities into Your Project¶
This guide covers how to use the OSIUtilities C++ library in a downstream CMake project. Three integration methods are available — choose based on your dependency management strategy and caching requirements.
Quick Start¶
After installation (any method), usage in CMake is always the same:
find_package(OSIUtilities REQUIRED)
target_link_libraries(my_target PRIVATE OSIUtilities::OSIUtilities)
This gives you:
The OSIUtilities library (MCAP/binary/TXTH trace file readers and writers)
OSI C++ bindings (osi3 protobuf headers and libraries, transitively)
Protobuf (transitively, via OSI)
MCAP headers (transitively)
LZ4 and ZSTD compression (linked internally, headers not exposed)
Integration Methods Overview¶
Method |
Dependency control |
Caching |
Complexity |
Best for |
|---|---|---|---|---|
A. Two-phase build |
Baseline (vcpkg) or custom |
✅ Excellent |
Medium |
CI pipelines, large projects |
B. add_subdirectory |
Full (your project controls) |
Via ccache |
Low |
Embedded/submodule workflows |
C. System install |
Full (system packages) |
OS package cache |
Low |
Linux distro packaging |
Method A: Two-Phase Build with find_package() (Recommended)¶
Build and install OSIUtilities and its dependencies in a separate phase, then
consume via find_package(). This gives excellent CI caching — the
dependency install directory can be cached and only rebuilt when the submodule
is bumped.
Step 1: Add as a submodule¶
git submodule add https://github.com/lichtblick-suite/asam-osi-utilities.git \
externals/asam-osi-utilities
git submodule update --init --recursive
Step 2: Phase A — Build and install dependencies¶
# Configure (uses vcpkg for protobuf, lz4, zstd)
cmake -S externals/asam-osi-utilities \
-B build-deps \
--preset vcpkg \
-DBUILD_EXAMPLES=OFF \
-DBUILD_TESTING=OFF
# Build
cmake --build build-deps --config Release --parallel
# Install to a local prefix
cmake --install build-deps --config Release --prefix deps/
This produces a self-contained deps/ directory with all headers, libraries,
and CMake config files.
Step 3: Phase B — Build your project¶
# Your project's CMakeLists.txt
cmake_minimum_required(VERSION 3.16)
project(my_project)
find_package(OSIUtilities REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE OSIUtilities::OSIUtilities)
Configure with the install prefix and vcpkg dependencies:
cmake -S . -B build \
-DCMAKE_PREFIX_PATH=deps/ \
-DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake \
-DVCPKG_INSTALLED_DIR=build-deps/vcpkg_installed \
-DVCPKG_MANIFEST_MODE=OFF
cmake --build build --config Release
Key flags explained:
Flag |
Purpose |
|---|---|
|
Tells CMake where to find OSIUtilities and OSI configs |
|
vcpkg toolchain ensures protobuf is found in CONFIG mode (required for abseil transitive deps) |
|
Points to Phase A’s vcpkg-installed packages (protobuf, lz4, zstd) |
|
Prevents vcpkg from trying to install packages again — uses existing ones |
CI Caching¶
Cache the deps/ directory and build-deps/vcpkg_installed/ keyed on the
submodule commit hash:
# GitHub Actions example
- uses: actions/cache@v4
with:
path: |
deps/
build-deps/vcpkg_installed/
key: osi-utils-${{ hashFiles('externals/asam-osi-utilities/**') }}
Phase A only re-runs when the submodule is bumped. Phase B (your project) uses the cached artifacts and builds in seconds.
Method B: add_subdirectory() (Simplest)¶
Embed asam-osi-utilities directly in your CMake build tree. This is the simplest approach and gives your project full control over all dependencies.
Step 1: Add as a submodule¶
git submodule add https://github.com/lichtblick-suite/asam-osi-utilities.git \
externals/asam-osi-utilities
git submodule update --init --recursive
Step 2: Include in your CMakeLists.txt¶
cmake_minimum_required(VERSION 3.16)
project(my_project)
# Provide protobuf, lz4, zstd before adding the subdirectory.
# Option 1: vcpkg toolchain (recommended)
# Option 2: find_package(Protobuf), find_package(lz4), find_package(zstd)
# Option 3: System packages (Linux)
# Disable parts you don't need
set(BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(BUILD_TESTING OFF CACHE BOOL "" FORCE)
add_subdirectory(externals/asam-osi-utilities)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE OSIUtilities::OSIUtilities)
Dependency resolution¶
With add_subdirectory(), your project is responsible for making protobuf,
lz4, and zstd available. Common approaches:
vcpkg (cross-platform): Add a vcpkg.json to your project:
{
"dependencies": ["protobuf", "lz4", "zstd"]
}
Then configure with CMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake.
System packages (Linux):
# Debian/Ubuntu
sudo apt install libprotobuf-dev protobuf-compiler liblz4-dev libzstd-dev
# Fedora/RHEL
sudo dnf install protobuf-devel lz4-devel libzstd-devel
Then configure with the base preset or plain cmake.
Trade-offs¶
✅ Simplest setup — no install step, targets available directly
✅ Full control over dependency versions (your CMake environment provides them)
❌ No caching benefit — asam-osi-utilities recompiles with every clean build
❌ OSI protobuf code generation runs every build (can be slow)
Method C: System Install + find_package()¶
Install asam-osi-utilities system-wide or to a custom prefix, then consume via
find_package() in any project. Useful for Linux distro packaging or shared
development environments.
Step 1: Build and install¶
git clone --recurse-submodules \
https://github.com/lichtblick-suite/asam-osi-utilities.git
cd asam-osi-utilities
# Using system packages (no vcpkg)
cmake --preset base \
-DBUILD_EXAMPLES=OFF \
-DBUILD_TESTING=OFF
cmake --build build --config Release --parallel
sudo cmake --install build --config Release
This installs to /usr/local/ by default. Override with --prefix:
cmake --install build --config Release --prefix /opt/osi-utilities
Step 2: Use in your project¶
find_package(OSIUtilities REQUIRED)
target_link_libraries(my_app PRIVATE OSIUtilities::OSIUtilities)
If installed to a non-standard prefix:
cmake -S . -B build -DCMAKE_PREFIX_PATH=/opt/osi-utilities
Customizing Dependencies¶
Using a different protobuf version¶
Protobuf is a public dependency — google::protobuf::Message appears in
the OSIUtilities API. The consumer and OSIUtilities must use the same
protobuf version (ABI-compatible) to avoid ODR violations.
With two-phase build (Method A): The protobuf version is determined by the
vcpkg baseline in vcpkg-configuration.json. To override:
# Option 1: Use the base preset with your own protobuf
cmake -S externals/asam-osi-utilities -B build-deps \
--preset base \
-DProtobuf_DIR=/path/to/your/protobuf/lib/cmake/protobuf
# Option 2: Override vcpkg baseline
# Create your own vcpkg-configuration.json with a different baseline hash
# and pass it via VCPKG_MANIFEST_DIR
cmake -S externals/asam-osi-utilities -B build-deps \
--preset vcpkg \
-DVCPKG_MANIFEST_DIR=/path/to/your/vcpkg-manifest/
With add_subdirectory (Method B): Your project provides protobuf. If you
call find_package(Protobuf) before add_subdirectory(asam-osi-utilities),
your protobuf is used automatically (CMake’s find_package is a no-op when
the package is already found).
Controlling compression libraries (lz4, zstd)¶
LZ4 and ZSTD are private dependencies — they are not exposed in any public header. Consumers do not need their headers, but the libraries must be available at link time (CMake handles this automatically for both static and shared builds).
To use custom lz4/zstd installations:
cmake -S externals/asam-osi-utilities -B build-deps \
--preset base \
-DCMAKE_PREFIX_PATH=/path/to/custom/lz4:/path/to/custom/zstd
Dependency Visibility Reference¶
Understanding which dependencies are transitive helps when diagnosing build issues or integrating into projects with existing dependency trees.
Dependency |
Visibility |
In public API |
Notes |
|---|---|---|---|
protobuf |
PUBLIC |
|
Must be ABI-compatible between library and consumer |
OSI (open_simulation_interface) |
PUBLIC |
Consumers instantiate |
Built from proto source via osi-cpp submodule |
mcap |
PUBLIC (headers) |
|
Header-only library, bundled |
lz4 |
PRIVATE |
Not in any public header |
Linked internally for MCAP compression |
zstd |
PRIVATE |
Not in any public header |
Linked internally for MCAP compression |
abseil |
Transitive (via protobuf) |
Not directly used |
Required by protobuf ≥ 4.x at link time |
utf8_range |
Transitive (via protobuf) |
Not directly used |
Required by protobuf ≥ 4.x at link time |
What this means for consumers¶
You do not need to
find_package(Protobuf)orfind_package(lz4)— they are resolved automatically through the OSIUtilities CMake config.If your project already uses protobuf, ensure it is the same version used to build OSIUtilities. Mixing versions causes undefined behavior.
If your project already uses lz4/zstd, there is no conflict — they are private to OSIUtilities and will not pollute your include paths.
Troubleshooting¶
find_package(OSIUtilities) fails¶
Ensure CMAKE_PREFIX_PATH includes the install prefix:
cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/deps
Protobuf not found (during find_package(OSIUtilities))¶
The OSIUtilities config calls find_dependency(Protobuf) internally. If this
fails, protobuf is not findable from your build environment. Solutions:
Two-phase build: Pass
VCPKG_INSTALLED_DIRandVCPKG_MANIFEST_MODE=OFFso the vcpkg toolchain finds the pre-installed protobuf.System packages: Ensure
libprotobuf-dev(or equivalent) is installed.Manual: Set
Protobuf_DIRorCMAKE_PREFIX_PATHto your protobuf install.
Abseil linker errors¶
If you see unresolved absl:: symbols, protobuf was likely found via CMake’s
built-in FindProtobuf module (which doesn’t know about abseil) instead of
protobuf’s own config-mode package. Fix: use the vcpkg toolchain or explicitly
request config mode:
find_package(Protobuf CONFIG REQUIRED) # before find_package(OSIUtilities)
Symbol conflicts with existing protobuf¶
If your project links a different protobuf version, you will get linker errors or runtime crashes. Ensure a single protobuf version across the entire build. The two-phase build (Method A) is safest because it isolates the dependency resolution.
Next Steps¶
Building — Build the library itself
Examples — Code examples for readers and writers
API Reference — Full C++ API documentation