import tor package
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2024 Foundation Devices Inc.
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
-->
|
||||
|
||||
# Cargokit Architecture
|
||||
|
||||
Note: This is mostly relevant for plugins authors that want to see a bit under the hood rather then just following a tutorial.
|
||||
|
||||
In ideal conditions the end-developer using the plugin should not even be aware of Cargokit existence.
|
||||
|
||||
## Integration
|
||||
|
||||
Cargokit is meant to be included in Flutter plugin (or application) that contains the Rust crate to be built during the Flutter build process.
|
||||
|
||||
Cargokit can be either incuded as git submodule or git subtree (required for plugins - as pub does not support submodules for git dependencies).
|
||||
|
||||
For a step by step tutorial on integrating Cargokit with a Flutter plugin see https://matejknopp.com/post/flutter_plugin_in_rust_with_no_prebuilt_binaries/.
|
||||
|
||||
## build_tool
|
||||
|
||||
Build tool is the core of cargokit. It is a Dart command line package that facilitates the build of Rust crate. It is invoked during the Flutter build process to build (or download) Rust artifacts, but it can be also used as a standalone tool.
|
||||
|
||||
It handles the following commands:
|
||||
|
||||
### build-cmake
|
||||
|
||||
This is invoked from `cargokit.cmake` and it is used to build the Rust crate into a dynamic library on Linux and Windows (which use CMake as build system).
|
||||
|
||||
The command takes no additional arguments, everything is controlled during environment variables set by `cargokit.cmake`.
|
||||
|
||||
### build-gradle
|
||||
|
||||
This is invoked from `plugin.gradle` and it is used to build the Rust crate into a dynamic library on Android. The command takes no additional arguments, everything is controlled during environment variables set by `plugin.gradle`.
|
||||
|
||||
The build_tool installs NDK if needed, configures the Rust environment for cross compilation and then invokes `cargo build` with appropriate arguments and environment variables.
|
||||
|
||||
The build-tool also acts a linker driver.
|
||||
|
||||
### build-pod
|
||||
|
||||
This is invoked from plugin's podspec `script_phase` through `build_pod.sh`. Bundle tool will build the Rust crate into a static library that gets linked into the plugin Framework. In this case must have `:execution_position` set to `:before_compile`.
|
||||
|
||||
Cargokit will build binaries for all active architectures from XCode build and lipo them togherer.
|
||||
|
||||
When using Cargokit to integrate Rust code with an application (not a plugin) you can also configure the `Cargo.toml` to just build a dynamic library. When Cargokit finds that the crate only built a dylib and no static lib, it will attempt to replace the Cocoapod framework binary with the dylib. In this case the script `:execution_position` must be set to `:after_compile`. This is *not* recommended for plugins and it's quite experimental.
|
||||
|
||||
### gen-key, precompile-binaries, verify-binaries
|
||||
|
||||
These are used as when providing precompiled binaries for Plugin. See [precompiled_binaries.md](precompiled_binaries.md) for more information.
|
||||
|
||||
## Launching the build_tool during build.
|
||||
|
||||
During Flutter build, the build tool can not be launched directly using `dart run`. Rather it is launched through `run_build_tool.sh` and `run_build_tool.cmd`. Because the `build_tool` is shipped as part of plugin, we generally don't want to write into the plugin directory during build, which would happen if the `build_tool` was simply invoked through `dart run` (For example the `.dart_tool/package_config.json` file would get written inside the `build_tool` directory).
|
||||
|
||||
Instead the `run_build_tool` script creates a minimal Dart command line package in the build directory and references the `build_tool` as package. That way the `.dart_tool/package_config.json` file is created in the temporary build folder and not in the plugin itself. The script also precompiles the Dart code to speed up subsequent invocations.
|
||||
|
||||
## Configuring Cargokit
|
||||
|
||||
### Configuration for the Rust crate
|
||||
|
||||
Cargokit can be configured through a `cargokit.yaml` file, which can be used to control the build of the Rust package and is placed into the Rust crate next to `Cargo.toml`.
|
||||
|
||||
Here is an example `cargokit.yaml` with comments:
|
||||
```yaml
|
||||
cargo:
|
||||
debug: # Configuration of cargo execution during debug builds
|
||||
toolchain: stable # default
|
||||
release: # Configuration of cargo execution for release builds
|
||||
toolchain: nightly # rustup will be invoked with nightly toolchain
|
||||
extra_flags: # extra arguments passed to cargo build
|
||||
- -Z
|
||||
- build-std=panic_abort,std
|
||||
|
||||
# If crate ships with precompiled binaries, they can be configured here.
|
||||
precompiled_binaries:
|
||||
# Uri prefix used when downloading precompiled binaries.
|
||||
url_prefix: https://github.com/superlistapp/super_native_extensions/releases/download/precompiled_
|
||||
|
||||
# Public key for verifying downloaded precompiled binaries.
|
||||
public_key: 3a257ef1c7d72d84225ac4658d24812ada50a7a7a8a2138c2a91353389fdc514
|
||||
```
|
||||
|
||||
### Configuration for the application consuming the plugin
|
||||
|
||||
A `cargokit_options.yaml` file can also be placed by developer using plugin to the root of the application package. In which case the file can be used to specify following options:
|
||||
|
||||
```yaml
|
||||
# Enables verbose logging of Cargokit during build
|
||||
verbose_logging: true
|
||||
|
||||
# Opts out of using precompiled binaries. If crate has configured
|
||||
# and deployed precompiled binaries, these will be by default used whenever Rustup
|
||||
# is not installed. With `use_precompiled_binaries` set to false, the build will
|
||||
# instead be aborted prompting user to install Rustup.
|
||||
use_precompiled_binaries: false
|
||||
```
|
||||
|
||||
## Detecting Rustup
|
||||
|
||||
When the plugin doesn't come with precompiled libraries (or user opt-out), `build_tool` will need to invoke Rustup during build to ensure that required Rust targets and toolchain are installed for current build and to build the Rust crate.
|
||||
|
||||
Cargokit will attempt to detect Rustup in the default Rustup installation location (`~/.cargo/rustup`) as well as in PATH. This is done so that if user install Rustup but doesn't properly configure PATH, Cargokit will still work.
|
||||
|
||||
If `build_tool` doesn't find Rustup, it will about the build with a message showing instructions to install Rustup specific to current platform.
|
||||
|
||||
On macOS it will also detect a homebrew Rust installation in PATH and will prompt user to call `brew unlink rust` first to remove homebrew Rust installation from PATH, because it may interfere with Rustup.
|
||||
|
||||
Homebrew Rust installation can not be used by Cargokit, because it can only build for host platform. Cargokit needs to be able to cross compile the Rust crate for iOS and Android and thus needs full Rustup installation.
|
||||
@@ -0,0 +1,101 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2024 Foundation Devices Inc.
|
||||
|
||||
SPDX-License-Identifier: MIT
|
||||
-->
|
||||
|
||||
# Precompiled Binaries
|
||||
|
||||
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:
|
||||
|
||||
1. Cargokit checks if there is `cargokit_options.yaml` file in the root folder of target application. If there is one, it will be checked for `use_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.
|
||||
|
||||
2. Cargokit checks if there is `cargokit.yaml` file placed in the Rust crate. If there is one, it will be checked for `precompiled_binaries` section to see if crate supports precompiled binaries. The configuration section must contain a public key and URL prefix.
|
||||
|
||||
3. Cargokit computes a `crate-hash`. This is a SHA256 hash value computed from all Rust files inside crate, `Cargo.toml`, `Cargo.lock` and `cargokit.yaml`. This uniquely identifies the crate and it is used to find the correct precompiled binaries.
|
||||
|
||||
4. 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 in `cargokit.yaml` (which is part of Rust crate and thus part of published Flutter package).
|
||||
|
||||
5. If the verification succeeds, the precompiled binaries will be used. Otherwise the binary will be discarded and Cargokit will insist on building from source.
|
||||
|
||||
## Providing precompiled binaries
|
||||
|
||||
Note that this assumes that precompiled binaries will be generated during github actions and deployed as github releases.
|
||||
|
||||
### Use `build_tool` to generate a key-pair:
|
||||
|
||||
```
|
||||
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.
|
||||
|
||||
### Provide a `cargokit.yaml` file in the Rust crate
|
||||
|
||||
The file must be placed alongside Cargo.toml.
|
||||
|
||||
```yaml
|
||||
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>
|
||||
```
|
||||
|
||||
### Configure a github action to build and upload precompiled binaries.
|
||||
|
||||
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.
|
||||
|
||||
```yaml
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user