Because Cargokit builds the Rust crate during Flutter build, it is inherently dependend on the Rust toolchain being installed on the developer's machine.
To decrease the friction, it is possible for Cargokit to use precompiled binaries instead.
This is how the process of using precompiled binaries looks from the perspective of the build on developer machine:
-
Cargokit checks if there is
cargokit_options.yaml
file in the root folder of target application. If there is one, it will be checked foruse_precompiled_binaries
options to see if user opted out of using precompiled binaries. In which case Cargokit will insist on building from source. Cargokit will also build from source if the configuration file is absent, but user has Rustup installed. -
Cargokit checks if there is
cargokit.yaml
file placed in the Rust crate. If there is one, it will be checked forprecompiled_binaries
section to see if crate supports precompiled binaries. The configuration section must contain a public key and URL prefix. -
Cargokit computes a
crate-hash
. This is a SHA256 hash value computed from all Rust files inside crate,Cargo.toml
,Cargo.lock
andcargokit.yaml
. This uniquely identifies the crate and it is used to find the correct precompiled binaries. -
Cargokit will attempt to download the precompiled binaries for target platform and
crate_hash
combination and a signature file for each downloaded binary. If download succeeds, the binary content will be verified against the signature and public key included incargokit.yaml
(which is part of Rust crate and thus part of published Flutter package). -
If the verification succeeds, the precompiled binaries will be used. Otherwise the binary will be discarded and Cargokit will insist on building from source.
Note that this assumes that precompiled binaries will be generated during github actions and deployed as github releases.
dart run build_tool gen-key
This will print the private key and public key. Store the private key securely. It needs to be provided as a secret to github action.
The public key should be included in cargokit.yaml
file in the Rust crate.
The file must be placed alongside Cargo.toml.
precompiled_binaries:
# Uri prefix used when downloading precompiled binaries.
url_prefix: https://github.com/<repository-owner>/<repository-name>/releases/download/precompiled_
# Public key for verifying downloaded precompiled binaries.
public_key: <public key from previous step>
The github action should be run at every commit to main branch (and possibly other branches).
The action needs two secrets - private key for signing binaries and GitHub token for uploading binaries as releases. Here is example action that precompiles and uploads binaries for all supported targets.
on:
push:
branches: [ main ]
name: Precompile Binaries
jobs:
Precompile:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- macOS-latest
- windows-latest
steps:
- uses: actions/checkout@v2
- uses: dart-lang/setup-dart@v1
- name: Install GTK
if: (matrix.os == 'ubuntu-latest')
run: sudo apt-get update && sudo apt-get install libgtk-3-dev
- name: Precompile
if: (matrix.os == 'macOS-latest') || (matrix.os == 'windows-latest')
run: dart run build_tool precompile-binaries -v --manifest-dir=../../rust --repository=superlistapp/super_native_extensions
working-directory: super_native_extensions/cargokit/build_tool
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
PRIVATE_KEY: ${{ secrets.RELEASE_PRIVATE_KEY }}
- name: Precompile (with Android)
if: (matrix.os == 'ubuntu-latest')
run: dart run build_tool precompile-binaries -v --manifest-dir=../../rust --repository=superlistapp/super_native_extensions --android-sdk-location=/usr/local/lib/android/sdk --android-ndk-version=24.0.8215888 --android-min-sdk-version=23
working-directory: super_native_extensions/cargokit/build_tool
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_GITHUB_TOKEN }}
PRIVATE_KEY: ${{ secrets.RELEASE_PRIVATE_KEY }}
By default the built_tool precompile-binaries
commands build and uploads the binaries for all targets buildable from current host. This can be overriden using the --target <rust-triple>
argument.
Android binaries will be built when --android-sdk-location
and --android-ndk-version
arguments are provided.