The Eclipse Zenoh: Zero Overhead Pub/sub, Store/Query and Compute.
Zenoh (pronounce /zeno/) unifies data in motion, data at rest and computations. It carefully blends traditional pub/sub with geo-distributed storages, queries and computations, while retaining a level of time and space efficiency that is well beyond any of the mainstream stacks.
Check the website zenoh.io and the roadmap for more detailed information.
This repository provides a C binding based on the main Zenoh implementation written in Rust.
⚠️ WARNING⚠️ : Zenoh and its ecosystem are under active development. When you build from git, make sure you also build from git any other Zenoh repository you plan to use (e.g. binding, plugin, backend, etc.). It may happen that some changes in git are not compatible with the most recent packaged Zenoh release (e.g. deb, docker, pip). We put particular effort in mantaining compatibility between the various git repositories in the Zenoh project.
-
Make sure that Rust is available on your platform. Please check here to learn how to install it.
-
Clone the source with
git
:git clone https://github.com/eclipse-zenoh/zenoh-c.git
- Build:
Good CMake practice is to perform build outside of source directory, leaving source tree untouched. The examples below demonstrates this mode of building. On the other hand VScode by default creates build directory named 'build' inside source tree. In this case build script sligthly changes its behavior. See more about it in section 'VScode'.
By default build configuration is set to Release
, it's not necessary to add -DCMAKE_BUILD_TYPE=Release
option on configuration step. But if your platform uses multi-config generator by default (this is the case on Windows), you may need to add option --config Release
on build step. See more in CMake build-configurations documenation. Option--config Release
is skipped in further examples for brewity. It's actually necessary for Visual Studio generators only. For Ninja Multi-Config the build script is able to select Release
as the default configuration.
$ mkdir -p build && cd build
$ cmake ../zenoh-c
$ cmake --build . --config Release
The generator to use is selected with option -G
. If Ninja is installed on your system, adding -GNinja
to cmake
command can greatly speed up the build time:
$ cmake ../zenoh-c -GNinja
$ cmake --build .
- Install:
To install zenoh-c library into system just build target install
. You need root privileges to do it, as the default install location is /usr/local
.
$ cmake --build . --target install
If you want to install zenoh-c libraries locally, you can set the installation directory with CMAKE_INSTALL_PREFIX
$ cmake ../zenoh-c -DCMAKE_INSTALL_PREFIX=~/.local
$ cmake --build . --target install
By default only dynamic library is installed. Set ZENOHC_INSTALL_STATIC_LIBRARY
variable to install static library also:
$ cmake ../zenoh-c -DCMAKE_INSTALL_PREFIX=~/.local -DZENOHC_INSTALL_STATIC_LIBRARY=TRUE
$ cmake --build . --target install
The result of installation is the header files in include
directory, the library files in lib
directory and cmake package configuration files for package zenohc
in lib/cmake
directory. The library later can be loaded with CMake command find_package(zenohc)
.
Link to targets zenohc::lib
for dynamic library and zenohc::static
for static one in your CMakeLists.txt configuration file.
For Debug
configuration the library package zenohc_debug
is installed side-by-side with release zenohc
library. Suffix d
is added to names of library files (libzenohcd.so).
- VScode
When zenoh-c project is opened in VSCode the build directory is set to build
inside source tree (this is default behavior of Microsoft CMake Tools). The project build script detects this situation. In this case it places build files in target
directory and Cargo.toml
file (which is generated from Cargo.toml.in
) into the root of source tree, as the rust developers used to and as the rust build tools expects by default. This behavior also can be explicitly enabled by setting ZENOHC_BUILD_IN_SOURCE_TREE
variable to TRUE
.
The examples can be built in two ways. One is to select examples
as a build target of zenoh-c project (assuming here that the current directory is side-by-side with zenoh-c directory):
$ cmake ../zenoh-c
$ cmake --build . --target examples
You may also use --target <example_name>
if you wish to only build a specific example.
All build artifacts will be in the target/release/examples
directory in this case.
Second way is to directly build examples
as a root project:
$ cmake ../zenoh-c/examples
$ cmake --build .
In this case the examples executables will be built in the current directory.
As a root project the examples
project links zenoh-c
with CMake's add_subdirectory command by default. There are also other ways to link zenoh-c
- with find_package or FetchContent:
Link with zenoh-c
installed into default location in the system (with find_package):
$ cmake ../zenoh-c/examples -DZENOHC_SOURCE=PACKAGE
Link with zenoh-c
installed in ~/.local
directory:
$ cmake ../zenoh-c/examples -DZENOHC_SOURCE=PACKAGE -DCMAKE_INSTALL_PREFIX=~/.local
Download specific zenoh-c
version from git with FetchContent:
$ cmake ../zenoh-c/examples -DZENOHC_SOURCE=GIT_URL -DZENOHC_GIT_TAG=0.8.0-rc
See also configure_include_project
function in helpers.cmake for more information
$ ./target/release/examples/z_sub
$ ./target/release/examples/z_pub
$ ./target/release/examples/z_queryable
$ ./target/release/examples/z_get
$ ./target/release/examples/z_sub_thgr
$ ./target/release/examples/z_pub_thgr
Many of the types exposed by the zenoh-c
API are types for which destruction is necessary. To help you spot these types, we named them with the convention that any destructible type must start by z_owned
.
For maximum performance, we try to make as few copies as possible. Sometimes, this implies moving data that you z_owned
. Any function that takes a non-const pointer to a z_owned
type will perform its destruction. To make this pattern more obvious, we encourage you to use the z_move
macro instead of a simple &
to create these pointers. Rest assured that all z_owned
types are double-free safe, and that you may check whether any z_owned_X_t
typed value is still valid by using z_X_check(&val)
, or the z_check(val)
macro if you're using C11.
We hope this convention will help you streamline your memory-safe usage of zenoh, as following it should make looking for leaks trivial: simply search for paths where a value of a z_owned
type hasn't been passed to a function using z_move
.
Functions that simply need to borrow your data will instead take values of the associated z_X_t
type. You may construct them using z_X_loan(&val)
(or the z_loan(val)
generic macro with C11).
Note that some z_X_t
typed values can be constructed without needing to z_borrow
their owned variants. This allows you to reduce the amount of copies realized in your program.
The examples have been written with C11 in mind, using the conventions we encourage you to follow.
Finally, we strongly advise that you refrain from using structure field that starts with _
:
- We try to maintain a common API between
zenoh-c
andzenoh-pico
, such that porting code from one to the other is, ideally, trivial. However, some types must have distinct representations in either library, meaning that using these representations explicitly will get you in trouble when porting. - We reserve the right to change the memory layout of any type which has
_
-prefixed fields, so trying to use them might cause your code to break on updates.
By default, zenoh-c enables Zenoh's logging library upon using the z_open
or z_scout
functions. This behaviour can be disabled by adding -DDISABLE_LOGGER_AUTOINIT:bool=true
to the cmake
configuration command. The logger may then be manually re-enabled with the zc_init_logger
function.
- The following alternative options have been introduced to facilitate cross-compilation.
⚠️ WARNING⚠️ : Perhaps aditional efforts are neccesary, that will depend of your enviroment.
-DZENOHC_CARGO_CHANNEL=nightly|beta|stable
: refers to a specific rust toolchain release [rust-channels
] https://rust-lang.github.io/rustup/concepts/channels.html-DZENOHC_CARGO_FLAGS
: several optional flags can be used for compilation. [cargo flags
] https://doc.rust-lang.org/cargo/commands/cargo-build.html-DZENOHC_CUSTOM_TARGET
: specifies a crosscompilation target. Currently rust support several Tire-1, Tire-2 and Tire-3 targets [targets
] https://doc.rust-lang.org/nightly/rustc/platform-support.html. But keep in mind that zenoh-c only have support for following targets:aarch64-unknown-linux-gnu
,x86_64-unknown-linux-gnu
,arm-unknown-linux-gnueabi
Lets put all together in an example: Assuming you want to crosscompile for aarch64-unknown-linux-gnu.
- install required packages
sudo apt install gcc-aarch64-linux-gnu
- *(Only if you use
nightly
)
rustup component add rust-src --toolchain nightly
- Compile Zenoh-C. Assume that it's in 'zenoh-c' directory. Notice that build in this sample is performed outside of source directory
$ export RUSTFLAGS="-Clinker=aarch64-linux-gnu-gcc -Car=aarch64-linux-gnu-ar"
$ mkdir -p build && cd build
$ cmake ../zenoh-c -DZENOHC_CARGO_CHANNEL=nightly -DZENOHC_CARGO_FLAGS="-Zbuild-std=std,panic_abort" -DZENOHC_CUSTOM_TARGET="aarch64-unknown-linux-gnu" -DCMAKE_INSTALL_PREFIX=../aarch64/stage
$ cmake --build . --target install
Additionaly you can use RUSTFLAGS
enviroment variable for lead the compilation.
If all goes right the building files will be located at:
/path/to/zenoh-c/target/aarch64-unknown-linux-gnu/release
and release files will be located at
/path/to/zenoh-c/target/aarch64-unknown-linux-gnu/release