Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
182 changes: 84 additions & 98 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ jobs:
direnv allow .
direnv export gha > "$GITHUB_ENV"

# # Rust
# - name: Rust lint
# run: cargo clippy -- -D warnings
# - name: Rust format
# run: cargo fmt --all --check
# - name: Rust tests
# run: cargo test
# Rust
- name: Rust lint
run: cargo clippy -- -D warnings
- name: Rust format
run: cargo fmt --all --check
- name: Rust tests
run: cargo test

# Dart/Flutter
- name: Dart lint
Expand All @@ -50,98 +50,84 @@ jobs:
- name: Dart tests
run: melos run test

# macos_integration_test:
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v5
# - uses: subosito/flutter-action@v2
# with:
# channel: beta # TODO remove
# - name: Create macOS boilerplate
# working-directory: packages/flutter_mimir/example
# run: flutter create . --platforms=macos
# - name: Disable macOS App Sandbox
# working-directory: packages/flutter_mimir/example
# run: /usr/libexec/PlistBuddy -c "Delete :com.apple.security.app-sandbox" macos/Runner/DebugProfile.entitlements
# - name: Run Flutter integration tests
# working-directory: packages/flutter_mimir/example
# run: flutter test -d macos integration_test
macos_integration_test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v5
- uses: subosito/flutter-action@v2
with:
channel: beta # TODO remove
- uses: bluefireteam/melos-action@v3
- run: melos run init-integration-test-boilerplate
- run: melos run integration-test -- -d macos

# windows_integration_test:
# runs-on: windows-latest
# steps:
# - uses: actions/checkout@v5
# - uses: subosito/flutter-action@v2
# with:
# channel: beta # TODO remove
# - name: Create Windows boilerplate
# working-directory: packages/flutter_mimir/example
# run: flutter create . --platforms=windows
# - name: Run Flutter integration tests
# working-directory: packages/flutter_mimir/example
# run: flutter test -d windows integration_test
windows_integration_test:
runs-on: windows-latest
steps:
- uses: actions/checkout@v5
- uses: subosito/flutter-action@v2
with:
channel: beta # TODO remove
- uses: bluefireteam/melos-action@v3
- run: melos run init-integration-test-boilerplate
- run: melos run integration-test -- -d windows

# linux_integration_test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v5
# - uses: subosito/flutter-action@v2
# with:
# channel: beta # TODO remove
# - uses: pyvista/setup-headless-display-action@v3
# - name: Install dependencies for flutter integration test
# run: sudo apt update && sudo apt-get install -y libglu1-mesa ninja-build clang cmake pkg-config libgtk-3-dev liblzma-dev
# - name: Create Linux boilerplate
# working-directory: packages/flutter_mimir/example
# run: flutter create . --platforms=linux
# - name: Run Flutter integration tests
# working-directory: packages/flutter_mimir/example
# run: flutter test -d linux integration_test
linux_integration_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: subosito/flutter-action@v2
with:
channel: beta # TODO remove
- uses: bluefireteam/melos-action@v3
- uses: pyvista/setup-headless-display-action@v3
- name: Install dependencies for flutter integration test
run: sudo apt update && sudo apt-get install -y libglu1-mesa ninja-build clang cmake pkg-config libgtk-3-dev liblzma-dev
- run: melos run init-integration-test-boilerplate
- run: melos run integration-test -- -d linux

# ios_integration_test:
# runs-on: macos-latest
# steps:
# - uses: actions/checkout@v5
# - uses: subosito/flutter-action@v2
# with:
# channel: beta # TODO remove
# - name: Start iOS Simulator
# uses: futureware-tech/simulator-action@v4
# id: start_simulator
# with:
# wait_for_boot: true
# - name: Create iOS boilerplate
# working-directory: packages/flutter_mimir/example
# run: flutter create . --platforms=ios
# - name: Run Flutter integration tests # NOTE: we often get timeouts otherwise
# uses: Wandalen/wretry.action@v3
# with:
# attempt_limit: 5
# current_path: packages/flutter_mimir/example
# command: flutter test -d ${{ steps.start_simulator.outputs.udid }} integration_test
ios_integration_test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v5
- uses: subosito/flutter-action@v2
with:
channel: beta # TODO remove
- uses: bluefireteam/melos-action@v3
- name: Start iOS Simulator
uses: futureware-tech/simulator-action@v4
id: start_simulator
with:
wait_for_boot: true
- run: melos run init-integration-test-boilerplate
# NOTE: we often get timeouts without a couple retries due to flakey macOS runners
- name: Run Flutter integration tests
uses: Wandalen/wretry.action@v3
with:
attempt_limit: 5
current_path: examples/flutter
command: melos run integration-test -- -d ${{ steps.start_simulator.outputs.udid }}

# android_integration_test:
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v5
# - uses: subosito/flutter-action@v2
# with:
# channel: beta # TODO remove
# - name: Create Android boilerplate
# working-directory: packages/flutter_mimir/example
# run: flutter create . --platforms=android
# - name: Enable KVM for Android emulator
# run: |
# echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
# sudo udevadm control --reload-rules
# sudo udevadm trigger --name-match=kvm
# - name: Run Flutter integration tests
# uses: reactivecircus/android-emulator-runner@v2
# with:
# api-level: 35
# target: default
# arch: x86_64
# ram-size: 1024M
# disk-size: 2048M
# working-directory: packages/flutter_mimir/example
# script: flutter test -d `flutter devices | grep android | tr ' ' '\n' | grep emulator-` integration_test
android_integration_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: subosito/flutter-action@v2
with:
channel: beta # TODO remove
- uses: bluefireteam/melos-action@v3
- name: Enable KVM for Android emulator
run: |
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm
- run: melos run init-integration-test-boilerplate
- name: Run Flutter integration tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
target: default
arch: x86_64
ram-size: 1024M
disk-size: 2048M
script: melos run integration-test -- -d `flutter devices | grep android | tr ' ' '\n' | grep emulator-`
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ pubspec.lock
**/doc/api/
.dart_tool/
.packages
/build/
/coverage/
build/
coverage/
.pub-cache/
.pub/
.flutter-plugins
Expand Down
3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[workspace]
resolver = "3"
members = ["examples/dart_only/rust", "examples/flutter/rust"]
11 changes: 11 additions & 0 deletions examples/dart_only/hook/build.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_rs/native_toolchain_rs.dart';

void main(List<String> args) async {
await build(args, (input, output) async {
await const RustBuilder(assetName: 'src/ffi.g.dart').run(
input: input,
output: output,
);
});
}
1 change: 1 addition & 0 deletions examples/dart_only/lib/dart_only_example.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'package:dart_only_example/src/ffi.g.dart' show rust_add;
11 changes: 11 additions & 0 deletions examples/dart_only/lib/src/ffi.g.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// AUTO GENERATED FILE, DO NOT EDIT.
//
// Generated by `package:ffigen`.
// ignore_for_file: type=lint
import 'dart:ffi' as ffi;

@ffi.Native<ffi.Int32 Function(ffi.Int32, ffi.Int32)>()
external int rust_add(
int a,
int b,
);
20 changes: 20 additions & 0 deletions examples/dart_only/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: dart_only_example
publish_to: none
resolution: workspace

environment:
sdk: ^3.9.0

dependencies:
hooks: ^0.20.1
native_toolchain_rs: ^0.1.1

dev_dependencies:
# TODO use released version
# ffigen: ^20.0.0-dev.0
ffigen:
git:
url: https://github.com/dart-lang/native
path: pkgs/ffigen
ref: 85fa542
test: ^1.26.3
10 changes: 10 additions & 0 deletions examples/dart_only/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "dart-only-example"
edition = "2024"

[lib]
crate-type = ["staticlib", "cdylib"]

[build-dependencies]
cc = "1.2.39"
cbindgen = "0.29.0"
10 changes: 10 additions & 0 deletions examples/dart_only/rust/bindings.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
This file is automatically generated by build.rs; DO NOT MANUALLY EDIT!
This header is designed to be consumed by ffigen over on the Dart side.
*/

#include <stdint.h>

extern int32_t c_add(int32_t a, int32_t b);

int32_t rust_add(int32_t a, int32_t b);
32 changes: 32 additions & 0 deletions examples/dart_only/rust/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::env;

use cbindgen::Language;

fn main() {
println!("cargo:rerun-if-changed=c/c_add.h");
println!("cargo:rerun-if-changed=c/c_add.c");

cc::Build::new()
.file("c/c_add.c")
.include("c")
.compile("c_add");

println!("cargo:rustc-link-lib=static=c_add");

let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();

cbindgen::Builder::new()
.with_crate(crate_dir)
.with_language(Language::C)
.with_no_includes()
.with_sys_include("stdint.h")
.with_autogen_warning(
"/*
This file is automatically generated by build.rs; DO NOT MANUALLY EDIT!
This header is designed to be consumed by ffigen over on the Dart side.
*/",
)
.generate()
.expect("Unable to generate bindings")
.write_to_file("bindings.h");
}
5 changes: 5 additions & 0 deletions examples/dart_only/rust/c/c_add.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include "c_add.h"

int32_t c_add(int32_t a, int32_t b) {
return a + b;
}
8 changes: 8 additions & 0 deletions examples/dart_only/rust/c/c_add.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#ifndef C_ADD_H
#define C_ADD_H

#include <stdint.h>

int32_t c_add(int32_t a, int32_t b);

#endif // C_ADD_H
1 change: 1 addition & 0 deletions examples/dart_only/rust/rust-toolchain.toml
16 changes: 16 additions & 0 deletions examples/dart_only/rust/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
unsafe extern "C" {
fn c_add(a: i32, b: i32) -> i32;
}

#[unsafe(no_mangle)]
pub extern "C" fn rust_add(a: i32, b: i32) -> i32 {
unsafe { c_add(a, b) }
}

#[cfg(test)]
mod tests {
#[test]
fn test_rust_add() {
assert_eq!(crate::rust_add(1, 1), 2);
}
}
8 changes: 8 additions & 0 deletions examples/dart_only/test/dart_only_example_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:dart_only_example/dart_only_example.dart';
import 'package:test/test.dart';

void main() {
test('rust_add correctly adds', () {
expect(rust_add(1, 1), equals(2));
});
}
12 changes: 12 additions & 0 deletions examples/dart_only/tool/ffigen.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import 'dart:io';

import 'package:ffigen/ffigen.dart';

void main() {
final packageRoot = Platform.script.resolve('../');
FfiGenerator(
headers: Headers(entryPoints: [packageRoot.resolve('rust/bindings.h')]),
output: Output(dartFile: packageRoot.resolve('lib/src/ffi.g.dart')),
functions: Functions.includeSet({'rust_add'}),
).generate(logger: null);
}
11 changes: 11 additions & 0 deletions examples/flutter/hook/build.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_rs/native_toolchain_rs.dart';

void main(List<String> args) async {
await build(args, (input, output) async {
await const RustBuilder(assetName: 'src/ffi.g.dart').run(
input: input,
output: output,
);
});
}
Loading
Loading