- Albin Santhosh
- September 17, 2025
Streamlining Dependency Management in Embedded Systems with Conan and Zephyr RTOS
Introduction
As embedded systems grow more connected and feature-rich, managing dependencies has become a pain for developers. Traditional practices often involve manually copying library files, relying on vendor-specific IDEs and customizing toolchains per project—an error-prone and time-consuming approach.
As firmware stacks grow increasingly complex, development teams must balance the demands of cross-compilation, multiple target architectures and modern CI/CD integration. Achieving reproducibility and portability across environments is difficult, especially when toolchain versions drift or dependencies are not perfectly aligned.
Manual integration steps further slow down workflows and increase the risk of inconsistencies, while constrained resources on build servers can quickly turn routine builds into bottlenecks. These challenges make onboarding new developers harder as well as maintaining long-term reliability more costly. A modern approach is needed—one that ensures consistency, scalability, and automation without sacrificing performance.
Meet Conan: A Modern C/C++ Package Manager
Conan brings the elegance of package management to the C/C++ world. Tailored for developers working across platforms, it solves problems like:
- Dependency version mismatches
- Fragile manual builds
- Poor reproducibility across CI environments
- Limited reusability of firmware components
Key Conan Features for Embedded Developers
- Build/Host Profile Separation for cross-compilation
- Toolchain Packaging for consistent builds
- Binary Caching and Lockfiles for reproducible releases
- Custom Remotes (e.g. Artifactory) for secure package hosting
- Easy versioning options
Synergy with Zephyr RTOS
Zephyr is a modular, scalable RTOS ideal for microcontrollers and constrained devices. Developers building on Zephyr can use Conan to:
- Package the Zephyr SDK as a Conan toolchain
- Manage third-party libraries (e.g. FreeRTOS modules, drivers)
- Break firmware into reusable Conan packages
- Integrate with CMake and West in CI pipelines
- Improve maintainability across board variants and architectures
This setup allows teams to build portable firmware across Cortex-M, x86 and RISC-V targets, all without sacrificing control or flexibility. By combining Conan’s package management with Zephyr’s modular RTOS, developers gain control over the full dependency graph—from third-party libraries to toolchains and platform overlays. Whether you’re scaling firmware across multiple boards or optimizing CI pipelines, this combo empowers teams to build robust, portable software with confidence.
So, let’s get right into it.
Concept Check
What is Zephyr RTOS?
- Lightweight, scalable, real-time operating system
- Modular architecture and support for multiple boards
- Uses CMake and West for build and dependency management
What is Conan?
- Recipe-based package manager for C/C++
- Handles dependencies, toolchains, and build configurations
- Supports cross-compilation and caching for reproducible builds
If we integrate Zephyr with Conan, it helps us to
- Simplify third-party dependency management
- Enable reproducible builds across environments
- Support out-of-tree development and modular packaging
- Reduce manual configuration of toolchains and host tools
Zephyr supports both in-tree and out-of-tree application models, each with distinct build setups. In-tree apps reside within Zephyr’s source tree, offering simplicity but limited reuse and packaging flexibility.
Out-of-tree builds, however, allow developers to maintain applications externally, enabling easier modularization, versioning, and integration with tools like Conan for dependency management.
For multi-domain projects, Zephyr’s sysbuild system streamlines building multiple firmware components—such as bootloaders, kernels, and user apps—in one coordinated process. Conan complements this by managing dependencies across domains, packaging toolchains and subsystems to simplify complex embedded builds.
Packing Zephyr with Conan
1. Resources
- Please clone the following Git repo to recreate the example, you can find them in conan-with-zephyr-RTOS.git
- Inside the cloned repo, you can find the folders arranged in the following manner

This will help you in directly trying out the examples that we’re going to discuss further.
2. Prerequisites
- The system should have,
- Python 3.6+
- CMake
- Git
- Create python virtual env for safe and smooth executions and pkg creation for Conan.

- After creating the venv install
- West (pip install west)
- Conan (pip install conan)
3. Initial Setup
- When working with Conan for the first time, you will be prompted to set up a profile to proceed. This is a one-time process. For setting the profile use:

- This will identify your native compiler and other system specific things like the OS you’re working on, the build options, etc. You can view the profile by:

4. Packing the Zephyr SDK
- The Zephyr SDK folder structure will look like this:

- This is a static folder, since it won’t have many updates other than the native updates from the respective compilers. Still, we can pack the tools only required by our project, which will give us the flexibility to work with them easily and update them in no time.
- For eg : like zephyr-arm-eabi for arm specific cores
- For eg : like zephyr-arm-eabi for arm specific cores
- The Zephyr SDK is typically identified by a Zephyr build through the ‘ZEPHYR_SDK_INSTALL_DIR’ environment variable.
- If this variable isn’t set, the build process will search for the SDK in some of the predefined directories, such as the home directory or root directory, like that.
- In our case, the SDK is usually cloned into the source directory or package (The Conan cache) directory where it will be packaged.
- After packing the SDK, we utilize the ‘ZEPHYR_SDK_INSTALL_DIR’ environment variable to retrieve the Conan Zephyr SDK for Zephyr Build.
- For packing the SDK, we need one conanfile,py, which will take care of the:
- Package dependencies
- Package layout
- SDK download directory
- OS specific packing
- Package creation and info
- Inside the cloned repo you could find conanfile.py inside the “conan-with-zephyr-RTOS/package/pack-sdk” folder
- The zephyr SDK tgz file approx. 1.6GB which may cause some issues while downloading if the network connection is not stable it can be disconnected, and you will be forced to do that multiple time. We have two conanfile.py available inside the pack-sdk folder for both scenarios.
- conanfile.py
- This Conan file will download and pack the SDK, no intervention needed.
- altconanfile.py
- This Conan file need the SDK to be downloaded and unzipped in the same path (pack-sdk)
- Please refer to the README.rst for more info on this approach.
- Now run the pack SDK command which will pack it from the current path rather than downloading and packing
- conanfile.py

- The above command will create the Conan package for Zephyr SDK. Once the package is created, we can list the created package as well as available package inside conan cache using:


- NB: If the packing fails before repacking it every time, please list the created package from cache and remove the corresponding package you’re trying to re-pack if that package has already been created in the conan cache. You can do that by:

5. Packing the Zephyr Base
- The process for packing the Zephyr Base is almost similar to the Zephyr SDK.
- The Zephyr Base folder will look like this:

- For this example, we are considering the entire Zephyr Base as a single package; this is a stiff mode of approaching. Since we package every module and base inside a single package that’ll be kind of stiff, if we need to update the base then it’ll again take the same time as creating the first one.
- We can also create different packages for each subfolder inside the source like zephyr, modules, and tools like that. That’ll give us more flexibility. By packing it like this we keep the size of the package minimal and keep the updating time for any changes to minimal.
- There is one more approach that we can follow to keep the update minimal, i.e., we can create one git repo maintaining the Zephyr base code for the specific project and pull that whenever an update is necessary and pack that, this can be easily added into the already excising conanfile using the conandata.yml file.
- The Zephyr Base is typically identified by a Zephyr build through the ‘ZEPHYR_BASE’ environment variable.
- If the env variable is not set, then it will look for a similar name in the root directory. That is found with the help of .west file Usually present inside the Source.
- In our case, the Zephyr Base is usually cloned into the source directory or package (The Conan cache) directory where it will be packaged.
- After packing the Zephyr Base, we utilize the ‘ZEPHYR_BASE’ environment variable to retrieve the Conan Zephyr Base for Zephyr Build from the Conan cache.
- The conanfile.py will be present inside the “conan-with-zehyr-RTOS/package/pack-base/” folder.
- Usually, the zephyr base doesn’t a download issue like Zephyr SDK, and runs the pack Base command

The above command will create the Conan package for Zephyr Base. Once the package is created, we can list the created package as well as available package inside conan cache using:


- NB: If somehow the packing fails before repacking it every time, please list the created package from cache and remove the corresponding package you’re trying to re-pack if that package has already been created in the conan cache. You can do that by:

6. Final Check
- If you’re able to do the above steps successfully, we’re good to go consuming those new packages created.
- To verify everything is in place, please run:

It should list all the packages inside your conan cache, which should be as follow:

NB: These commands alone can’t guarantee that packing is completed. Make sure the packing process doesn’t show any errors. If any errors should occur, clear the package from the cache using a Conan command and try packing again.
Consuming the Zephyr Conan Packages from a Sample App
- Now that we have the required packages ready, we can test it out in one sample application to verify that, here I’m taking the official blinky example from the Zephyr repo. The folder structure is very important for any Zephyr Sample to get a clean build. Keep that in mind whenever you try a new sample.
- Inside the cloned repo you could see two more folders named multicore-build and singlecore-build. The rest of the things you can try directly from there.
1. Multicore-Build (With West)
- The folder structure of multicore-build folder is as follows,

- Here, you can see the core two core names core 0 & core 1 having one Blinky example each, which also has one conanfile.py inside each blinky sample and one main conanfile.py inside the multicore-build itself.
- We can focus on the root conanfile.py for the time begin which will take care of the multicore build and should take care of,
- The dependencies
- The build target
- The way of building projects
- The way of handling the build and output folder
- For this example, we’re considering the “stm32f3_disco” core [stm32 f303 – Discovery kit].
- You can go to the multicore-build folder and run the following to start checking for the dependencies

- You should see the requires are fetched from the cache successfully like this:

- NB: The name of the package will be different when you’re trying, you can see the package name from conan cache using the “conan list” command and update the same inside the conanfile.py

- Now we can build the sample using

- Once completed you will see two elf images created for each core present inside the out/ folder.
- Tips: you can edit the conanfile.py add other important files like the map file etc. To the out folder as your requirements. It is just a copy function inside a python file.
- The respective build will be present inside the build folder
- This example uses the West command itself to build the project inside the conanfile.py

- Yeah, so now this is multicore build with Conan using West commands
Now a question may arise: by this time, you would be thinking I already said we need to set some environment variables to make this work, right?
Conan will take care of that internally, if you look inside the conan package file for Zephyr base and SDK on the last lines you’ll be able to see the package info been set, that will populate the conanbuild.sh inside the build/generators which will source this before building the project. Pretty cool, right?!
- The conanfile inside each core folder has its own specific build command present try it out,
Hint : The commands are the same!
- The conanfile inside each core folder has its own specific build command present try it out,
2. Singlecore-Build (Without West)
- We’ve already seen the build with West from above, so this is a bonus topic. We can build the same without West. What West is doing behind the hood is running some CMake commands and Ninja command, guess what we can also do that directly that will be explained inside this section.
- You can go to the zephyr-conan/singlecore-build/ folder from the cloned git repo. If you look inside the build method instead of using West commands, we have used the CMake build commands.
- This approach comes with a trade of easiness, because we need to manually give every module that are required for that specific core to build, like in case of stm32
- modules/hal/stm32
- modules/hal/cmsis
- This will vary according to the board in use, this will give us more control over the build than West So, it’ll be good to do some experiments on this.
- The build process is the same:

- The elf will be created inside the build/zephyr folder
- You can refer more about this from : Build System (CMake)
Updating Packages
- You can always update the SDK and Zephyr Base version from the conanfile, and repack it. You can edit it as follows,
- For Zephyr SDK

- For Zephyr Base

For Zephyr base, you should also update the conandata.yml to update the branch.
Conan Server
- To preserve all the packages, we’ve created and share them with the team and other members, we’ll use the Conan Server.
- Conan Server is a lightweight, open-source remote repository implementation.
- It’s mainly used for testing or small teams, not recommended for production-scale use.
Installed via pip:

- Runs locally on port 9300 and stores packages in a simple directory structure. We can also inspect those from the home directory.
Conan Serve comes in handy when we’re working in a collaborative development team,1. Centralized Package Hosting
- Teams can upload and share packages to a central Conan server or remote (like Artifactory).
- Ensures everyone uses the same dependency versions and configurations.
2. Version Control & Lockfiles- Use lock files to freeze dependency graphs.
- Share lockfiles via Git to guarantee reproducible builds across machin
3. CI/CD Integration- Conan integrates with CI tools like GitHub Actions, GitLab CI, Jenkins.
- Automates package creation, testing, and deployment.
4. Recipe Hygiene- Modular conanfile.py recipes help teams maintain clean, reusable logic.
- Use tool_requires for build tools and isolate build vs host dependencies.
The Conan Server offers us the ability to upload our created packages onto the server and maintain them. This way, others can download the same packages from the server, making contributions and collaboration easier. We can host one server by starting one Conan server as mentioned at the start of this section. Once started you can see the server will look like,

You can list already existing remote using:


Now you can upload the package created to this server using,

Now you can set security to this server by adding restriction to read and write to this server, you can explore that more on the Conan Server official documentation.
More Integrations
Since Zephyr top-level building settings was based on CMake, we’ve used the Conan integrated CMake examples above, Other than that conan offers the flexibility of integrating much wide range of toolchain like,
CMake Integration
- Conan 2.x (CMakeToolchain + CMakeDeps):
- Auto-generates toolchain and dependency files
- Clean integration with find_package() and targets
- Best for modern workflows
- cmake-conan (legacy):
- Invokes Conan inside CMakeLists.txt
- Useful for projects not yet migrated to Conan 2
Ninja Integration
- Super-fast parallel builds
- Set generator via config:

- Works seamlessly with Conan presets
Make Integration
- Use with Unix Makefiles generator

- Slower than Ninja but widely supported
ROS Integration (ROS2)
- Use the ROSEnv generator in conanfile
- Source ROS and Conan env scripts:

- Build with colcon
Other Features
1. Freezing the conanfile (Version Pinning)
To ensure consistent builds across machines and time:
Pin exact versions in your conanfile.txt or conanfile.py:

- Avoid using version ranges like fmt/[>=9.0 <11.0] unless necessary.
- Use lockfiles to freeze the full dependency graph:

- Share the lock file with your team to guarantee reproducibility.
2. Reproducible Builds
Conan supports reproducibility through:
Profiles: Define consistent settings (OS, compiler, arch, etc.)

- Toolchain files: Generated by CMakeToolchain to ensure consistent build flags.
- Lockfiles: Capture exact versions and options of all dependencies.
- Immutable remotes: Use read-only artifact storage to prevent accidental overwrites.
3. Recreating Error Scenarios
To simulate or reproduce build failures:
Use –build=missing to force local builds and expose compiler issues:
conan install . –build=missing
- Use –build=* to rebuild everything from source.
- Modify profiles to test edge cases (e.g., unsupported compilers or architectures).
Use conan graph to inspect and manipulate dependency trees:

A typical graph will look like this, showing all the dependencies,

4. Modular & Maintainable Recipes
Best practices for recipe hygiene:
- Split logic into reusable py classes or templates.
- Use tool_requires for build tools like CMake, Ninja, etc.
- Keep options and settings minimal and well-documented.
- Use package_info() to expose only necessary targets and paths.
5. Remote Artifact Storage for Teams
To collaborate effectively:
- Use a Conan server, Artifactory, or Conan-compatible remote.
- This is already discussed inside Conan Server Section
Further Experiments
You can try out much more out of this, what we’ve done is a small leap. some of them are,
- Making the Conan Server integrated with git so that we can pull the source also from there.
- Protecting Conan Server such that it can be shared among multiple users with multiple permission states.
- Packing the Zephyr Base as separate packages, in that case you need to create one common package that will keep track of all the fragmented packages and can pull it together from the cache.
- Add option to flash the sample from conanfile itself, using profile options
- Same with debug as well.
Conclusion
Incorporating Conan into Zephyr RTOS build offers a robust, scalable, and reproducible approach to dependency management in embedded systems. With Conan’s modular recipe system, version pinning, and lockfile capabilities, teams can consistently reproduce builds across different environments, CI pipelines, and hardware configurations. This approach helps reduce integration overhead and simplifies dependency resolution—especially important in constrained embedded contexts where build determinism and stability are critical.
By leveraging Conan’s toolchain integration, remote artifact storage, and collaboration-friendly ecosystem, teams working on Zephyr-based projects gain enhanced control over third-party libraries and build tools, while aligning with modern DevOps and continuous integration practices. The result is a system that promotes maintainability, traceability, and scalability—without compromising performance or flexibility.