{"id":13838432,"url":"https://github.com/dirien/rust-cross-compile","last_synced_at":"2025-07-15T23:45:08.123Z","repository":{"id":184900593,"uuid":"672609654","full_name":"dirien/rust-cross-compile","owner":"dirien","description":"Cross compiling Rust for different architectures and operating systems","archived":false,"fork":false,"pushed_at":"2023-07-30T21:29:10.000Z","size":14,"stargazers_count":10,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-04T23:08:56.617Z","etag":null,"topics":["cross-compile","rust"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dirien.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-07-30T16:59:46.000Z","updated_at":"2024-10-27T23:30:59.000Z","dependencies_parsed_at":"2023-07-30T21:34:51.347Z","dependency_job_id":null,"html_url":"https://github.com/dirien/rust-cross-compile","commit_stats":null,"previous_names":["dirien/rust-cross-compile"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirien%2Frust-cross-compile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirien%2Frust-cross-compile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirien%2Frust-cross-compile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dirien%2Frust-cross-compile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dirien","download_url":"https://codeload.github.com/dirien/rust-cross-compile/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248451649,"owners_count":21105904,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cross-compile","rust"],"created_at":"2024-08-04T15:01:56.867Z","updated_at":"2025-04-11T17:42:07.662Z","avatar_url":"https://github.com/dirien.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"## Introduction\n\nIn this blog post, we will have a look at how to cross-compile your Rust applications using cross-rs and GitHub Actions. We will also have a look at how to use the cross-rs Docker image to cross-compile your Rust applications locally.\n\nBut before we dig into the details, let's have a look at multi-platform support in Rust.\n\n### Motivation for multi-platform support\n\nNowadays, it is common to use different operating systems and architectures. We have IoT devices that run on ARM processors and servers which run on x86 processors. Or Apple computers that run on Apple Silicon processors. And then we have Windows, Linux and macOS. Enough reasons to support multiple platforms when developing software.\n\nBut now comes the downside: Most OS APIs are not compatible with each other. This difference in APIs is the reason why have to create platform-dependent code.\n\n### How Rust supports multi-platform\n\nThe good news is that Rust makes it easy to write multi-platform code. Rust has a built-in macro called `cfg` which enables us the conditional compilation of code. It supports a lot of options so we can easily write platform-dependent parts of our code depending on the target platform.\n\n[https://doc.rust-lang.org/reference/conditional-compilation.html](https://doc.rust-lang.org/reference/conditional-compilation.html)\n\nSome examples of `cfg`:\n\n```rust\n#[cfg(target_os = \"linux\")]\nfn main() {\n    println!(\"This is Linux\");\n}\n\n#[cfg(target_os = \"macos\")]\nfn main() {\n    println!(\"This is macOS\");\n}\n```\n\nThe `cfg` macro also supports `any`, `all` and `not`:\n\n* `any` - If any of the given predicates is true, the code is included.\n\n* `all` - If all of the given predicates are true, the code is included.\n\n* `not` - If the given predicate is false, the code is included.\n\n\n```rust\n#[cfg(any(target_os = \"linux\", target_os = \"macos\"))]\nfn main() {\n    println!(\"This is Linux or macOS\");\n}\n\n#[cfg(all(target_os = \"linux\", target_arch = \"x86_64\"))]\nfn main() {\n    println!(\"This is Linux on x86_64\");\n}\n\n#[cfg(not(target_os = \"windows\"))]\nfn main() {\n    println!(\"This is not Windows\");\n}\n```\n\nRust also supports platform-dependent dependencies. We can use the `target` attribute to specify dependencies for a specific platform. The `cfg` syntax is also supported.\n\n```toml\n[dependencies]\n# This dependency is only used on Linux\n[target.'cfg(unix)'.dependencies]\nopenssl = \"1.0.1\"\n```\n\nSame for `dev-dependencies` and `build-dependencies`:\n\n```toml\n[dev-dependencies]\n# This dev-dependency is only used on Linux\n[target.'cfg(unix)'.dev-dependencies]\nopenssl = \"1.0.1\"\n\n[build-dependencies]\n# This build-dependency is only used on Linux\n[target.'cfg(unix)'.build-dependencies]\nopenssl = \"1.0.1\"\n```\n\n### Rust support tiers\n\nRust is organized in support tiers when it comes to multi-platform support. The Rust team provides different levels of support for different platforms. The support tiers are:\n\n* \u003cmark\u003eTier 1 \u003c/mark\u003e \\- Tier 1 platforms are \"guaranteed to work\", this is the highest level of support\n\n* \u003cmark\u003eTier 2\u003c/mark\u003e - Tier 2 platforms are \"guaranteed to build\", but not necessarily to pass all tests\n\n* \u003cmark\u003eTier 3\u003c/mark\u003e - Tier 3 platforms are those for which the Rust code has support, but which are not built or tested automatically. So there is no guarantee that they work.\n\n\nAccording to the Rust team, [the following platforms are Tier 1](https://doc.rust-lang.org/nightly/rustc/platform-support.html):\n\n* aarch64-unknown-linux-gnu\n\n* i686-pc-windows-gnu\n\n* i686-pc-windows-msvc\n\n* i686-unknown-linux-gnu\n\n* x86\\_64-apple-darwin\n\n* x86\\_64-pc-windows-gnu\n\n* x86\\_64-pc-windows-msvc\n\n* x86\\_64-unknown-linux-gnu\n\n\n### `cross-rs` to the rescue\n\n%[https://github.com/cross-rs/cross] \n\nWith [`cross-rs`](https://github.com/cross-rs/cross) we have an easy way to cross-compile our Rust applications. `cross-rs` works by using pre-made Dockerfiles to build and run your application inside a Docker container. The list of supported platforms is quite long, have a look at the following link for more information:\n\n%[https://github.com/cross-rs/cross/tree/main/docker] \n\nHere is a short selection of supported platforms:\n\n1. `Dockerfile.x86_64-unknown-linux-gnu`\n\n2. `Dockerfile.x86_64-pc-windows-gnu`\n\n3. `Dockerfile.aarch64-unknown-linux-gnu`\n\n4. `Dockerfile.i686-unknown-linux-gnu`\n\n5. `Dockerfile.i686-pc-windows-gnu`\n\n6. `Dockerfile.armv7-unknown-linux-gnueabihf`\n\n7. `Dockerfile.riscv64gc-unknown-linux-gnu`\n\n8. `Dockerfile.mips64-unknown-linux-gnuabi64`\n\n9. `Dockerfile.powerpc64le-unknown-linux-gnu`\n\n10. `Dockerfile.x86_64-unknown-linux-musl`\n\n\nPretty impressive, right?\n\nLet us create a simple demo project to see `cross-rs` in action.\n\n## Prerequisites\n\n* [Rust](https://www.rust-lang.org)\n\n* An IDE or text editor of your choice\n\n* [Docker](https://www.docker.com)\n\n* GitHub account\n\n* [GitHub CLI](https://cli.github.com)\n\n\n## Initialize the demo project\n\nThe demo project is a simple Rust application that prints a [FIGlet](http://www.figlet.org/) text to the console. We use clap to parse the command line arguments. That's it. Nothing fancy!\n\n```bash\ncargo init --bin figctl\n```\n\nThen we add the `clap` dependency:\n\n```bash\ncargo add clap --features derive\n```\n\nAnd then we add a `figlet-rs` dependency:\n\n```bash\ncargo add figlet-rs\n```\n\nNow we can add the following code to `src/main.rs`:\n\n```rust\nuse clap::{Parser, Args};\nuse figlet_rs::FIGfont;\n\n#[derive(Parser, Debug)]\nstruct FigletCtl {\n    message: String,\n}\n\nfn main() {\n    let args = FigletCtl::parse();\n    let standard_font = FIGfont::standard().unwrap();\n    let figure = standard_font.convert(args.message.as_str());\n    println!(\"{}\", figure.unwrap());\n}\n```\n\nIf you run the application now, you should see the following output:\n\n```bash\n➜ cargo run -q -- 'Hello World!'\n  _   _          _   _            __        __                 _       _   _ \n | | | |   ___  | | | |   ___     \\ \\      / /   ___    _ __  | |   __| | | |\n | |_| |  / _ \\ | | | |  / _ \\     \\ \\ /\\ / /   / _ \\  | '__| | |  / _` | | |\n |  _  | |  __/ | | | | | (_) |     \\ V  V /   | (_) | | |    | | | (_| | |_|\n |_| |_|  \\___| |_| |_|  \\___/       \\_/\\_/     \\___/  |_|    |_|  \\__,_| (_)\n```\n\n## Cross-compile the demo project\n\nYou can install `cross-rs` with the following command:\n\n```bash\ncargo install cross --git https://github.com/cross-rs/cross\n```\n\nAnd let test it with a simple example.\n\n```bash\ncross build --target aarch64-unknown-linux-gnu\n```\n\nNow you should have a `target/aarch64-unknown-linux-gnu/debug/figctl` binary. Let's run it and see what happens.\n\n```bash\n➜ ./target/aarch64-unknown-linux-gnu/debug/figctl \"Hello World!\"\nzsh: exec format error: ./target/aarch64-unknown-linux-gnu/debug/figctl\n```\n\nThe binary is not executable on our host system. But we can run it inside a Docker container.\n\n```bash\ndocker run --rm -it -v $(pwd):/app  --platform=linux/arm64 -w /app rust ./target/aarch64-unknown-linux-gnu/debug/figctl 'Hello World!'\n  _   _          _   _            __        __                 _       _   _ \n | | | |   ___  | | | |   ___     \\ \\      / /   ___    _ __  | |   __| | | |\n | |_| |  / _ \\ | | | |  / _ \\     \\ \\ /\\ / /   / _ \\  | '__| | |  / _` | | |\n |  _  | |  __/ | | | | | (_) |     \\ V  V /   | (_) | | |    | | | (_| | |_|\n |_| |_|  \\___| |_| |_|  \\___/       \\_/\\_/     \\___/  |_|    |_|  \\__,_| (_)\n```\n\nIt works! So let's see how we can use `cross-rs` to build our application for multiple platforms with GitHub Actions.\n\n## GitHub Actions\n\nWe need to create a file called `.github/workflows/ci.yml` and add the following content:\n\n```yaml\nname: build and release\n\non:\n  workflow_dispatch:\n  release:\n    types: [ created ]\n\npermissions:\n  contents: write\n\njobs:\n  build:\n    name: ${{ matrix.platform.os_name }} with rust ${{ matrix.toolchain }}\n    runs-on: ${{ matrix.platform.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        platform:\n          - os_name: Linux-aarch64\n            os: ubuntu-20.04\n            target: aarch64-unknown-linux-musl\n            bin: figctl-linux-arm64\n          - os_name: Linux-x86_64\n            os: ubuntu-20.04\n            target: x86_64-unknown-linux-gnu\n            bin: figctl-linux-amd64\n          - os_name: Windows-x86_64\n            os: windows-latest\n            target: x86_64-pc-windows-msvc\n            bin: figctl-amd64.exe\n          - os_name: macOS-x86_64\n            os: macOS-latest\n            target: x86_64-apple-darwin\n            bin: figctl-darwin-amd64\n          - os_name: macOS-aarch64\n            os: macOS-latest\n            target: aarch64-apple-darwin\n            bin: figctl-darwin-arm64\n        toolchain:\n          - stable\n    steps:\n      - uses: actions/checkout@v3\n      - name: Build binary\n        uses: houseabsolute/actions-rust-cross@v0\n        with:\n          command: \"build\"\n          target: ${{ matrix.platform.target }}\n          toolchain: ${{ matrix.toolchain }}\n          args: \"--locked --release\"\n          strip: true\n      - name: Rename binary (linux and macos)\n        run: mv target/${{ matrix.platform.target }}/release/figctl target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }}\n        if: matrix.platform.os_name != 'Windows-x86_64'\n      - name: Rename binary (windows)\n        run: mv target/${{ matrix.platform.target }}/release/figctl.exe target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }}\n        if: matrix.platform.os_name == 'Windows-x86_64'\n      - name: Generate SHA-256\n        run: shasum -a 256 target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }} | cut -d ' ' -f 1 \u003e target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }}.sha256\n      - name: Release binary and SHA-256 checksum to GitHub\n        uses: softprops/action-gh-release@v1\n        with:\n          files: |\n            target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }}\n            target/${{ matrix.platform.target }}/release/${{ matrix.platform.bin }}.sha256\n```\n\nThis workflow will build the application for the following platforms:\n\n* Linux-aarch64\n\n* Linux-x86\\_64\n\n* Windows-x86\\_64\n\n* macOS-x86\\_64\n\n* macOS-aarch64\n\n\nIt will also create a GitHub release for each platform.\n\nLet's push the changes to GitHub and create a new release.\n\n```bash\ngit add .\ngit commit -m \"Add all the things\"\ngit push\n```\n\nNow go to the GitHub repository and create a new release or use the GitHub CLI.\n\n```bash\n➜ gh release create v0.1.0 \n? Title (optional) My figctl cli\n? Release notes Leave blank\n? Is this a prerelease? No\n? Submit? Publish release\nhttps://github.com/dirien/rust-cross-compile/releases/tag/v0.1.0\n```\n\nThis will trigger the GitHub Actions workflow and build the application for all the platforms.\n\n![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690752217312/ce86de1f-7439-4eca-a7a6-25ae4b9b1b06.png align=\"center\")\n\n![](https://cdn.hashnode.com/res/hashnode/image/upload/v1690752244717/c4142236-0ede-4ba8-acd5-c52f6c412fc3.png align=\"center\")\n\n## Conclusion\n\nCreating a cross-platform application with Rust is easy as Rust has a great toolchain and ecosystem. But it's not always easy to build the application for multiple platforms. With `cross-rs` and GitHub Actions, we can build our application for multiple platforms and with GitHub Releases, we can distribute the application to our users.\n\n## Links\n\n* https://github.com/cross-rs/cross\n\n* https://doc.rust-lang.org/nightly/rustc/platform-support.html\n\n* https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdirien%2Frust-cross-compile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdirien%2Frust-cross-compile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdirien%2Frust-cross-compile/lists"}