Rust makes cross compilation child's play
Tags: rust, cross
Published: 2020-12-05 22:47:48

---
title: Rust makes cross compilation child's play
published: true
date: 2020-12-05 00:00:00 UTC
tags: rust,cross
canonical_url: 
---

## Why do I care about this

Recently I solved [this](https://github.com/dandavison/delta/issues/396) delta issue, where the maintainer asked to switch from Travis CI to GitHub actions.

These are all the pull requests I’ve done if you want to have a look at this journey:[#399](https://github.com/dandavison/delta/pull/399), [#400](https://github.com/dandavison/delta/pull/400),[#409](https://github.com/dandavison/delta/pull/409), [#411](https://github.com/dandavison/delta/pull/411),[#413](https://github.com/dandavison/delta/pull/413), [#417](https://github.com/dandavison/delta/pull/417)and finally [#418](https://github.com/dandavison/delta/pull/418).

And yes..As you can see I like small incremental work and early feedback instead of giant pull requests. 😁

Anyway, the delta project has a lot of compilation targets and the binaries are automatically released in the GitHub releases [page](https://github.com/dandavison/delta/releases) every time the project is tagged. Sweet. 😌

![delta releases](https://www.marcoieni.com/2020/12/rust-makes-cross-compilation-childs-play/delta.png "Releases")

From an x86\_64 architecture (TLDR: common 64 bit Intel or AMD processors) it is really straightforward to compile for a different operating system with `cargo` if you are targeting the same architecture. For example if you want to compile for macOS you just need to run:

```
rustup target add x86_64-apple-darwin
cargo build --target x86_64-apple-darwin
```

The problems start to arise when you want to compile for a different architecture, such as i686 (32 bit) or ARM processors. In this case, you have to install some dependencies and set some environment variables, which may be painful. For example, in the old continuous integrations scripts of delta,[this](https://github.com/dandavison/delta/blob/15d06cbf7584570ec3b5beaba99cb8898f9ec3dc/etc/ci/before_install.sh) was the way dependencies were installed. Ugly, I know. As rust developers we are used to great tools, so there must be a better way right?

## Meet Cross

> “Zero setup” cross compilation and “cross testing” of Rust crates.

This is the description of the [Cross](https://github.com/rust-embedded/cross) tool.

The TLDR is that it let you compile and test rust projects for architectures other than i686 and x86\_64.

Instead of doing `cargo build --target <YOUR_TARGET>` you simply do `cross build --target <YOUR_TARGET>`. Based on the target, in fact, cross will run a docker image that has all the right dependencies already installed and configured by the rust-embedded team itself. 😉 And that’s it..just run `cargo install cross` and you are ready to cross-compile for all[these](https://github.com/rust-embedded/cross#supported-targets) targets in rust, no other dependency is required, except docker of course!

Obviously this was not an exhaustive overview about cross and I encourage you to have a look at the GitHub page if you are interested.

## Cross in GitHub actions

Of course, after a whole morning getting mad trying to setup weird ubuntu dependencies for the delta issue, when I found out about cross I felt very stupid for not knowing it in advance and I tried to integrate it in the Continuous Deployment delta pipeline.

It turns out that this is like the easiest thing in the world! The [action-rs/cargo](https://github.com/actions-rs/cargo) action I was already using had built-in [support](https://github.com/actions-rs/cargo#cross-compilation) for cross. Now I even felt more stupid, but anyway..you just need to set the `use-cross` variable to `true` and you are done!

[This](https://github.com/dandavison/delta/blob/e198c0d841d9fb660e59e0329235a8601b407c69/.github/workflows/cd.yml#L32-L37) is the step that builds the whole delta project for all its different targets..easy, right? 😀

## Cross in Rust GitHub template

You may or (probably) may not be aware of [Rust GitHub Template](https://rust-github.github.io/).

> Rust GitHub Template is a template for cargo generate that aims to be a starting point suitable for the vast majority of rust projects that will be hosted on GitHub.

Beyond all its nice goodies, this template will setup Continuous Deployment for you, therefore whenever you tag your project, it will be published on `crates.io` and the binaries will be released in the GitHub Releases page, just like in delta. 😁

Until today, Rust GitHub template only supported x86\_64 windows, linux and mac, but after I found out Cross I couldn’t resist and I added support for i686 and aarch64 linux architectures, which are both two [tier 1](https://doc.rust-lang.org/nightly/rustc/platform-support.html) rust targets. In practice, this means your “old thinkpad” and “raspberry pi” users will thank you a lot. 😛

![gh template releases](https://www.marcoieni.com/2020/12/rust-makes-cross-compilation-childs-play/rust-gh.png "Releases")

[This](https://github.com/rust-github/rust-gh-example/blob/01e0aae91f83e1e932f4498a0eddb2905c8fffc3/.github/workflows/cd.yml#L57-L63) is an example of the resulting Continuous Deployment step.

And that was it, after I spent a lot of _very useful_ time trying to setup compilation dependencies basically I just wanted to share my love for the `cross`tool with the rest of the world in order to avoid this pain to as many people as possible. 😅

Thanks for reading this far! You can find me on [twitter](https://twitter.com/MarcoIeni) or [YouTube](https://www.youtube.com/MarcoIeni), bye! 👋