Skip to content

Generate Paho C Bindings

Frank Pagliughi edited this page Aug 14, 2019 · 3 revisions

Generate Paho C Bindings

The Paho MQTT Rust client wraps the Paho C library which handles network interactions. The Rust repository contains a Git submodule normally pointing to the the latest stable C library source release on GitHub. The Rust paho-mqtt-sys crate can automatically build the C library and use the rather amazing bindgen crate to automatically generate the bindings to the C library.

The problem with using bindgen inside the build is that it has a lot of dependencies and really slows down compilation of any application that includes the Paho Rust crate. This is especially true when building natively on a small embedded target like an ARM board. It can take 10, 20, 30 minutes or more depending on the board.

This is especially problematic since the binding will never change, unless we update the version of Paho C. Therefore we can create the bindings for a version of the C library once, store it in the repository, and reuse it to speed up the build.

The one minor issue id that there could be differences in the bindings for different target platforms. The ones included in the Paho Rust repository were generated on an x86_64 running a recent version of Mint/Ubuntu Linux. They appear to work on ARM v7 and v8 boards, but there is no guarantee. So it might be wise for users to regenerate the bindings for their targets.

The methods described here can be used to generate target-specific bindings, or to upgrade for a new version of the Paho C library.

The following instructions work on Mint 19 / Ubuntu 18.04. Other platforms should work similarly, given different package managers, etc.

Install Bindgen

Bindgen Documentation

Bindgen GitHub Repository

First off, bindgen requires llvm. This can be obtained from here: LLVM Download Page

Or through you package manager, like:

$ sudo apt install llvm
...

$ llvm-config --version
6.0.0

The requirements for bindgen may change, but as of this writing, and version of LLVM >= v3.9 should be adequate.

You can then use cargo to download, build, and install the command-line version of bindgen:

$ cargo install bindgen
...

$ bindgen --version
bindgen 0.51.0

Generate New Bindings

Bindgen Command Line Usage

The C header file, wrapper.h, in the paho-mqtt-sys crate contains all the Paho C headers that need to be wrapped. This is the one that should be used to generate bindings. The basic form is:

$ bindgen wrapper.h -o bindings.rs

but if the Paho C headers are not in a standard location, we need to pass flags in to clang so that it can them, like:

$ bindgen wrapper.h -o bindings.rs -- -I./paho.mqtt.c/src

Upgrading the Paho C Version

When bindings are being generated to support a new version of Paho C, such as for a new release of the Paho Rust crate, a few additional things should be done:

  1. Update the Paho C submodule to the required version.
$ cd paho.mqtt.rust/
$ git co develop
$ paho-mqtt-sys/paho.mqtt.c/
$ git co v1.3.1
$ git pull

$ cd ../..
$ git add paho-mqtt-sys/paho.mqtt.c
$ git ci -m "Moved the Paho C submodule to v1.3.1"
$ git push origin develop 

If this was previously done and you have a fresh clone of the Paho Rust library, you need to pull down the C sources in the submodule:

$ cd paho.mqtt.rust/
$ git submodule init
$ git submodule update
  1. Generate the new bindings, and save them in the directory paho-mqtt-sys/bindings with the C version number as part of the file name, like:
bindings_paho_mqtt_c_1.3.1.rs

This can typically be done with bindgen in one step, like:

$ cd paho-mqtt-sys/
$ bindgen wrapper.h -o bindings/bindings_paho_mqtt_c_1.3.1.rs \
    -- -I./paho.mqtt.c/src
  1. Update the build file, paho-mqtt-sys/build.rs and change the PAHO_MQTT_C_VERSION version number constant (~line 75):
const PAHO_MQTT_C_VERSION: &'static str = "1.3.1";
  1. Update the default traits for the C struct wrappers to account for any new fields added to the structs in the new version. These are in paho-mqtt-sys/src/lib.rs

Now, the -sys wrapper crate should build:

$ cd paho.mqtt.rust/paho-mqtt-sys
$ cargo clean
$ cargo build
...