Skip to content

Latest commit

 

History

History
151 lines (101 loc) · 4.56 KB

cross-compile.md

File metadata and controls

151 lines (101 loc) · 4.56 KB

Cross-compiling OPC UA for Rust

The Raspberry Pi will be used as the target device for this document. If you have another target, e.g. some bitbake concoction, then you will have to adapt the instructions accordingly.

Cross compilation is described in two ways - one that uses the cross tool and one that is manual. Depending on your needs you may decide on one or the other.

Build with Cross

The cross tool attempts to make it as simple as possible to cross-compile software by automatically fetching the appropriate cross compile toolchain and environment.

Install docker if you have not already.

$ sudo apt install docker.io

Install cross for Rust.

$ cargo install cross

Install the tool according its own instructions. Ensure your docker permissions are set. Now you can use cross in place of cargo. e.g.

$ cross build --all --target armv7-unknown-linux-gnueabihf

The additional argument --target armv7-unknown-linux-gnueabihf tells cross to set up a build environment before invoking cargo.

SELinux conflict

The cross tool may have an issue running cargo on Fedora / Red Hat dists due to a SELinux policy. Read the bug for a workaround.

Manual build

The manual process gives you complete control on the build process but requires a bit more work.

Credit

A bug was raised asking how to cross-compile OPC UA for Rust and someone kindly answered with references. The links below were used to produce a working solution:

  1. Install cross-compile utilities as shown here
  2. Follow malbarbo's answer here

Raspberry Pi is the target architecture. I used Linux Subsystem for Windows with Debian to work through the steps.

Install toolchain for ARM7

These steps are derived from from sodiumoxide readme:

Install cross-compiler packages:

Debian has convenient packages for cross compilation and emulation.

$ sudo apt update
$ sudo apt install build-essential gcc-arm-linux-gnueabihf libc6-armhf-cross libc6-dev-armhf-cross qemu-system-arm qemu-user-static -y

Download and build OpenSSL

Derived from a Stack Overflow answer and adapted to opcua:

$ cd /tmp

$ wget https://www.openssl.org/source/openssl-1.0.1t.tar.gz
$ tar xzf openssl-1.0.1t.tar.gz

$ cat > .opcuaARMenv << EOF
export MACHINE=armv7
export ARCH=arm
export CC=arm-linux-gnueabihf-gcc
EOF

$ source .opcuaARMenv

$ cd openssl-1.0.1t && ./config shared && make && cd -

Build OPC UA for Rust

Add cross compiler to Rust

The rustup tool allows us to add another target to the Rust toolchain.

$ rustup target add armv7-unknown-linux-gnueabihf

Add target to OPC UA for Rust

With the compiler ready, we move onto the project and set up the target.

$ cd /my/path/to/opcua
$ mkdir .cargo
$ cat > .cargo/config << EOF
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
EOF

You now have the following in a opcua/.cargo/config file:

[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"

Build

Building is straightforward and just requires we specify where OpenSSL was built before invoking cargo with the correct build target.

$ cat > .opcuaSSLenv << EOF
export OPENSSL_LIB_DIR=/tmp/openssl-1.0.1t/
export OPENSSL_INCLUDE_DIR=/tmp/openssl-1.0.1t/include
export OPENSSL_STATIC=1
export QEMU_LD_PREFIX=/usr/arm-linux-gnueabihf
EOF

source .opcuaSSLenv
cargo build --target armv7-unknown-linux-gnueabihf

Note OPENSSL_STATIC=1, causes rust-openssl to link to OpenSSL's static library which saves a little effort in the next step. Alternatively you can copy the libcrypto.so, libcrypto.so.1.0.0, libssl.so and libssl.so.1.0.0 from $OPENSSL_LIB_DIR into $QEMU_LD_PREFIX/lib before running.

Run

Qemu can run Arm binaries from your host environment with a qemu-arm-static command - convenient! So now we can test if the build works:

$ source .opcuaSSLenv
$ cd samples/simple-client
$ qemu-arm-static ../../target/armv7-unknown-linux-gnueabihf/debug/opcua-simple-client

or

$ source .opcuaSSLenv
$ cd samples/demo-server
$ qemu-arm-static ../../target/armv7-unknown-linux-gnueabihf/debug/opcua-demo-server