Github Actionsとcrossを使ってReleaseでクロスコンパイルしてバイナリをアップロードする
TL;DR
rustの用途として、コマンドラインツールを作成することが多い。コマンドラインツールを創るときにrustを使うメリットとしては、シングルバイナリで配布できるので利用しやすいということがある。
ソースコードはどうせgithubで管理するので、リリースするたびに最新のバイナリを配布できるようにしておくと便利。そして、複数プラットフォームで使えるようにクロスコンパイルを自動でできるようにしておくと更に便利なので、そのやり方について説明していく。
cross build
dockerを使ってcross buildしてくれるcrossというパッケージを使う。rustのGithub Actionsのactions-rs/cargoを使うと簡単にGithub Actionsでcross buildを行うことができる。
使い方は非常に簡単で、actions-rs/cargo@v1
を使う際にwith
の中でuse-cross
をtrue
にするだけでcrossを利用できる。
- uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --target armv7-unknown-linux-gnueabihf
release and upload
releaseを作ったり、uploadしたりするアクションはあるが、バイナリをartifactにアップロードして...みたいな感じで結構長くなるので、Upload files to a GitHub releaseを使う。公式サンプルは以下のような感じで、非常に簡単にrelease作成とバイナリアップロードができる。
simple_example.yml
name: Publish
on:
push:
tags:
- '*'
jobs:
build:
name: Publish binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: cargo build --release
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: target/release/mything
asset_name: mything
tag: ${{ github.ref }}
overwrite: true
body: "This is my release text"
Release.yml
最終的にクロスビルドとrelease and uploadをあわせたymlはこちら。matrixを使って複数のプラットフォームでのビルドをしている。muslを指定しないと古いCentOSでは動かないという致命的な問題があるのでmuslとgnuを両方指定している。普通はWindowsとか入れとくといいと思う。
Windowsを入れる場合は、ubuntu上で普通にビルドできる。ただ出力ファイルに.exe
が必要なのでそこだけ注意すればいい。
Release.yml
name: Release
on:
push:
tags:
- '*'
jobs:
build:
name: Release binary
strategy:
matrix:
include:
- os: ubuntu-latest
target: x86_64-unknown-linux-gnu
artifact_name: example
asset_name: example-x86_64-unknown-linux-gnu
- os: ubuntu-latest
target: x86_64-unknown-linux-musl
artifact_name: example
asset_name: example-x86_64-unknown-linux-musl
- os: ubuntu-latest
target: x86_64-pc-windows-gnu
artifact_name: example.exe
asset_name: example-x86_64-pc-windows-gnu.exe
- os: macos-latest
target: x86_64-apple-darwin
artifact_name: example
asset_name: example-x86_64-apple-darwin
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Install stable toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- name: Cross build with all features
uses: actions-rs/cargo@v1
with:
use-cross: true
command: build
args: --release --target ${{ matrix.target }} --all-features --verbose
- name: Upload binaries to release
uses: svenstaro/upload-release-[email protected]
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: target/${{ matrix.target }}/release/${{ matrix.artifact_name }}
asset_name: ${{ matrix.asset_name }}
tag: ${{ github.ref }}
overwrite: true