These instructions show how to use Linux (Debian in this case) to build the SAFE Network Rust code to run on ARMv7 processor, such as the Odroid-U3. This involves cross-compiling on the Linux/Intel machine, and transferring the results to the Odroid afterwards.
Pre-requisites
This assumes you’ve already been building the Rust compiler from source (Nightly), and using it to build the MaidSafe Rust libraries on Linux/Intel, so if not you need to do that first. This post about building CRUST that has everything in it you’ll need.
Build Libsodium For ARM
You’ll already have libsodium, but will now need a version compiled for ARM. Below I assume libsodium is in ~/src/libsodium-1.0.3. You’ll also need a cross compiling C compiler such as gcc or clang, plus the cross compiler tools for your compiler.
I have gcc-4.9. To add the cross compiler tools, I did:
sudo apt-get install gcc-arm-linux-gnueabihf
Static or Dynamic Linking?
If you link libsodium statically, you end up with only one file, the executable, to install and run on your target device. Its a bit bigger if you do this, but saves you having to install both the executable and the library needed for dynamic linking. Below are two sets of instructions, 1) Static Linked libsodium and 2) Dynamically Linked libsodium. This is either/or, choose which you want and just do that one.
1) Static Linked libsodium
To build libsodium you need to tell it to use the ARM version of the compiler by setting environment variable CC, and then running ‘configure’:
mkdir ~/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf cd ~/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf export CC=arm-linux-gnueabihf-gcc-4.9 ../../configure --enable-static LDFLAGS=-static --build=x86_64-unknown-linux-gnu --host=arm-unknown-linux-gnueabihf --target=arm-unknown-linux-gnueabihf
[*Note: I wasn’t able to get libsodium to take notice of the --host directive, which is supposedly all that is needed see issue #274 comment. Instead I set the compiler directly with “export CC=…”, but left the “-host” etc directives I’d been trying in place. Setting CC is not ideal because I haven’t specfied any compiler flags, and I believe it makes the --host, --build, and --target directives redundant. I’ve left them in because this is what I used and it did work! You might like to try without specifying the compiler, and using only “–host=arm-linux-gnueabihf” which is supposed to be what libsodium needs. However, if you do get this working, you may need to use the same triplet (i.e. “arm-linux-gnueabihf”), instead of “arm-unknown-linux-gnueabihf” as I’ve used elsewhere in these instructions. So when you build the rust libraries and maidsafe code for ARM, substituting “–target arm-linux-gnueabihf” instead of “–target arm-unknown-linux-gnueabihf”, and similarly when you create symbolic links etc otherwise things might not match up and you’ll get errors somewhere. I ended up using “arm-unknown-linux-gnueabihf” because that’s now the convention for configuration names, and is what was given in the examples I found for compiling Rust for ARM, and “arm-linux-gnueabihf” wasn’t working in libsodium anyway.]
Build libsodium for ARM:
make v=1
The “v=1” is not needed but tells make to be “verbose” and so is more informative. If make succeeds, you will now have created static library as “libsodium.a”. For Rust to find and link with it, create a symbolic link from /usr/local/lib to the file. Like this:
sudo ln -s $HOME/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf/src/libsodium/.libs/libsodium.a /usr/local/lib/libsodium.a
2) Dynamically Linked libsodium
To build libsodium you need to tell it to use the ARM version of the compiler by setting environment variable CC, and then running ‘configure’:
mkdir ~/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf cd ~/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf export CC=arm-linux-gnueabihf-gcc-4.9 ../../configure --build=x86_64-unknown-linux-gnu --host=arm-unknown-linux-gnueabihf --target=arm-unknown-linux-gnueabihf
[*See the note under 1) Static Linked libsodium (above) regarding --build, --host and --target directives.]
Build libsodium for ARM and install it in /usr/lib:
make v=1 sudo make install sudo ln -s $HOME/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf/src/libsodium/.libs/libsodium.so /usr/lib/arm-linux-gnueabihf/libsodium.so sudo ln -s $HOME/src/libsodium-1.0.3/target/arm-unknown-linux-gnueabihf/src/libsodium/.libs/libsodium.so.13 /usr/lib/arm-linux-gnueabihf/libsodium.so.13
At this point you’ve build libsodium, either as a dynamic or a static library, and created symbolic links so the rust compiler can find it.
Before you can compile with Rust for ARM you will also need to build the std Rust library crates for ARM because these are not shipped with the compiler, as follows.
Get/update rust nightly from github so you can build the std crates for ARM
cd ~/src git clone https://github.com/rust-lang/rust.git cd rust
[For information only: the instructions below are adapted from: https://github.com/japaric/ruststrap/blob/master/1-how-to-cross-compile.md. See also: GitHub - japaric-archived/ruststrap: [SUPERSEDED] by https://github.com/warricksothr/RustBuild]
This next bit takes a while to compile, so if you have 8GB or more RAM on your build machine try “make -j4” instead of “make” in what follows, as this will speed compilation by using multiple CPU cores:
cd ~/src/rust ./configure --target=arm-unknown-linux-gnueabihf,x86_64-unknown-linux-gnu make sudo make install
Now install your ARM Rust libraries with the rest of the Rust compiler libraries:
sudo ln -s $HOME/src/rust/arm-unknown-linux-gnueabihf /usr/lib/rustlib/arm-unknown-linux-gnueabihf
At this point everything is done. The rest of this post explains how to cross compile some test code and try it out on an ARM device, and then how to build a maidsafe example and try that out as well.
Try Cross Compiling with rustc
You should now have a rustc installation that can cross compile for ARM, so let’s test it out.
Create a test file “hello.rs” containing:
pub fn main() { println!("Hello, world!"); }
Tell rustc the name of the cross-compiler (which must be in your PATH), and compile it:
$ rustc -C linker=arm-linux-gnueabihf-gcc-4.9 --target=arm-unknown-linux-gnueabihf hello.rs
Check it produced an ARM binary
$ file hello hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=8ecf390faf2b65d29d3292a3cb78d9ada788d6c0, not stripped
Looking good
Check it works on your ARM device:
$ scp hello me@arm:~ $ ssh me@arm ./hello Hello, world!
Cross Compiling with Cargo
Now let’s build with cargo, but we can specify a different linker for each target architecture using ~/.cargo/config
Create ~/.cargo/config containing
[target.arm-unknown-linux-gnueabihf] linker = "arm-linux-gnueabihf-gcc-4.9"
Test with Cargo
$ cargo new --bin hello $ cd hello $ cargo build --target=arm-unknown-linux-gnueabihf $ file target/arm-unknown-linux-gnueabihf/debug/hello target/arm-unknown-linux-gnueabihf/release/hello: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 2.6.32, BuildID[sha1]=8088b28a2818b4a2c55c3638b71d2f805833e17f, not stripped
SUCCESS!
Ok, so we seem to have everything working to build for ARM with Rust. Finally we are ready to build the SAFE Network code for ARM.
Building A MaidSafe Example
This will work in your existing MaidSafe directories, but this example clones the code from github for a fresh start:
mkdir ~/src/maidsafe-rust cd ~/src/maidsafe-rust git clone https://github.com/maidsafe/self_encryption cd self_encryption cargo build --target=arm-unknown-linux-gnueabihf
That should build the library (in ~/src/maidsafe-rust/self_encryption/target/arm-unknown-linux-gnueabihf/debug).
Now build an example - something we can run on the ARM device.
cargo build --target=arm-unknown-linux-gnueabihf --example basic_encryptor
Finally try the example out on your ARM device (e.g. Odroid-U3):
Test MaidSafe Example on Odroid / ARM
Still working on the Linux/Intel build machine. In the following example, the Odroid is on the local network at IP address 192.168.43.46, and the user name for it is “odroid”.
Copy libsodium to Odroid…
scp /usr/lib/arm-linux-gnueabihf/libsodium.so.13 odroid@192.168.43.46:~
Copy basic_encryptor example to Odroid…
scp ~/src/maidsafe-rust/self_encryption/target/target/arm-unknown-linux-gnueabihf/debug/examples/basic_encryptor odroid@192.168.43.46:~
Login to Odroid…
ssh odroid@192.168.43.46
Install libsodium…
sudo cp libsodium.so.13 /usr/lib
Create test file, encrypt it, decrypt it, and compare…
man ls > ls.txt ./basic_encryptor -e ls.txt ./basic_encryptor -d data_map blah.txt diff ls.txt blah.txt
If you list the directory you’ll find the data_map file and a directory called chunk_store_test. The directory will contain the encrypted chunks of “ls.txt” and the data_map contains the self_encryption map needed to decrypt them.
ls.txt and blah.txt should be identical, so diff will not produce any output.