Skip to content

Commit

Permalink
Merge pull request #527 from dbsxdbsx/master
Browse files Browse the repository at this point in the history
Avoid conflicted and redundant FFI with generation over multiple blocks of rust Api
  • Loading branch information
fzyzcjy authored Jul 5, 2022
2 parents e5a2f0b + cf2f7ff commit 797040d
Show file tree
Hide file tree
Showing 53 changed files with 2,691 additions and 495 deletions.
80 changes: 72 additions & 8 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,32 @@ jobs:
- name: Install ffigen
run: dart pub global activate ffigen ^6.0.1

- name: Install dart dependencies
- name: Install dart dependencies (single block)
working-directory: ./frb_example/pure_dart/dart
run: dart pub get

- name: Run valgrind script
- name: Install dart dependencies (multi blocks)
working-directory: ./frb_example/pure_dart_multi/dart
run: dart pub get

- name: Run valgrind script (single block)
working-directory: ./frb_example/pure_dart/dart
run: chmod +x ./run.sh ./valgrind_util.py && ./run.sh
env:
CARGO_TARGET_DIR: /home/runner # NOTE here, must be an absolute path, since in my script uses it in multiple different directories

- name: Run valgrind script (multi blocks)
working-directory: ./frb_example/pure_dart_multi/dart
run: chmod +x ./run.sh && ./run.sh
env:
CARGO_TARGET_DIR: /home/runner # NOTE here, must be an absolute path, since in my script uses it in multiple different directories



# ref https://medium.com/flutter-community/run-flutter-driver-tests-on-github-actions-13c639c7e4ab
flutter_ios_test:
name: Flutter (iOS) integration test
runs-on: macOS-latest
runs-on: macos-latest

strategy:
matrix:
Expand Down Expand Up @@ -118,15 +130,15 @@ jobs:

steps:
- uses: actions/checkout@v2

# #499, https://github.com/actions/virtual-environments/issues/5595
- name: Configure ndk
run: |
ANDROID_HOME=$HOME/Library/Android/sdk
SDKMANAGER=$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager
echo y | $SDKMANAGER "ndk;21.4.7075529"
ln -sfn $ANDROID_HOME/ndk/21.4.7075529 $ANDROID_HOME/ndk-bundle
- name: Install Rust toolchain
Expand Down Expand Up @@ -355,6 +367,13 @@ jobs:
working-directory: ./frb_example/pure_dart/rust
run: cargo test --verbose

- name: Build pure_dart_multi example
working-directory: ./frb_example/pure_dart_multi/rust
run: cargo build --verbose
- name: Run tests for pure_dart_multi example
working-directory: ./frb_example/pure_dart_multi/rust
run: cargo test --verbose

- name: Build with_flutter example
working-directory: ./frb_example/with_flutter/rust
run: cargo build --verbose
Expand Down Expand Up @@ -433,6 +452,17 @@ jobs:
command: clippy
args: --manifest-path=./frb_example/pure_dart/rust/Cargo.toml -- -D warnings

- name: Run fmt for pure_dart_multi example
uses: actions-rs/cargo@v1
with:
command: fmt
args: --manifest-path=./frb_example/pure_dart_multi/rust/Cargo.toml --all -- --check
- name: Run clippy for pure_dart_multi example
uses: actions-rs/cargo@v1
with:
command: clippy
args: --manifest-path=./frb_example/pure_dart_multi/rust/Cargo.toml -- -D warnings

- name: Run fmt for with_flutter example
uses: actions-rs/cargo@v1
with:
Expand Down Expand Up @@ -479,6 +509,16 @@ jobs:
working-directory: ./frb_example/pure_dart/dart
run: dart analyze --fatal-infos

- name: Install dependencies for pure_dart_multi example
working-directory: ./frb_example/pure_dart_multi/dart
run: dart pub get
- name: Verify formatting for pure_dart_multi example
working-directory: ./frb_example/pure_dart_multi/dart
run: dart format --output=none --set-exit-if-changed --line-length 120 .
- name: Analyze project source for pure_dart_multi example
working-directory: ./frb_example/pure_dart_multi/dart
run: dart analyze --fatal-infos

- uses: subosito/flutter-action@v2
with:
channel: "stable"
Expand Down Expand Up @@ -549,6 +589,30 @@ jobs:
env:
RUST_LOG: debug

# NOTE in windows, need "\\" instead of "/"
- name: Run codegen to pure_dart_multi example (non-windows)
if: ${{ matrix.os.family != 'windows' }}
working-directory: ./frb_codegen
run: cargo run --package flutter_rust_bridge_codegen --bin flutter_rust_bridge_codegen --
--rust-input ../frb_example/pure_dart_multi/rust/src/api_1.rs ../frb_example/pure_dart_multi/rust/src/api_2.rs
--dart-output ../frb_example/pure_dart_multi/dart/lib/bridge_generated_api_1.dart ../frb_example/pure_dart_multi/dart/lib/bridge_generated_api_2.dart
--dart-format-line-length 120
--rust-output ../frb_example/pure_dart_multi/rust/src/generated_api_1.rs ../frb_example/pure_dart_multi/rust/src/generated_api_2.rs
--class-name ApiClass1 ApiClass2
env:
RUST_LOG: debug
- name: Run codegen to pure_dart_multi example (windows)
if: ${{ matrix.os.family == 'windows' }}
working-directory: ./frb_codegen
run: cargo run --package flutter_rust_bridge_codegen --bin flutter_rust_bridge_codegen --
--rust-input ..\\frb_example\\pure_dart_multi\\rust\\src\\api_1.rs ..\\frb_example\\pure_dart_multi\\rust\\src\\api_2.rs
--dart-output ..\\frb_example\\pure_dart_multi\\dart\\lib\\bridge_generated_api_1.dart ..\\frb_example\\pure_dart_multi\\dart\\lib\\bridge_generated_api_2.dart
--dart-format-line-length 120
--rust-output ..\\frb_example\\pure_dart_multi\\rust\\src\\generated_api_1.rs ..\\frb_example\\pure_dart_multi\\rust\\src\\generated_api_2.rs
--class-name ApiClass1 ApiClass2
env:
RUST_LOG: debug

- name: Run codegen to with_flutter example (non-windows)
if: ${{ matrix.os.family != 'windows' }}
working-directory: ./frb_codegen
Expand All @@ -563,11 +627,11 @@ jobs:
RUST_LOG: debug

# #467
- name: "Modify cross-platform code (osx)"
- name: "Modify cross-platform code (osx) (single block)"
if: ${{ matrix.os.family == 'osx' }}
# note the "-i '' -e" is a bug of sed specific to MacOS https://stackoverflow.com/questions/19456518
run: sed -i '' -e 's/^typedef uintptr_t =.*$/typedef uintptr_t = ffi.UnsignedLong;/g' frb_example/pure_dart/dart/lib/bridge_generated.dart
- name: "Modify cross-platform code (non-osx)"
- name: "Modify cross-platform code (non-osx) (single block)"
if: ${{ matrix.os.family != 'osx' }}
run: sed -i -e 's/^typedef uintptr_t =.*$/typedef uintptr_t = ffi.UnsignedLong;/g' frb_example/pure_dart/dart/lib/bridge_generated.dart

Expand Down
41 changes: 25 additions & 16 deletions frb_codegen/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,30 @@ pub fn ensure_tools_available() -> Result {
Ok(())
}

pub fn bindgen_rust_to_dart(
rust_crate_dir: &str,
c_output_path: &str,
dart_output_path: &str,
dart_class_name: &str,
c_struct_names: Vec<String>,
llvm_install_path: &[String],
llvm_compiler_opts: &str,
) -> anyhow::Result<()> {
cbindgen(rust_crate_dir, c_output_path, c_struct_names)?;
pub(crate) struct BindgenRustToDartArg<'a> {
pub rust_crate_dir: &'a str,
pub c_output_path: &'a str,
pub dart_output_path: &'a str,
pub dart_class_name: &'a str,
pub c_struct_names: Vec<String>,
pub exclude_symbols: Vec<String>,
pub llvm_install_path: &'a [String],
pub llvm_compiler_opts: &'a str,
}

pub(crate) fn bindgen_rust_to_dart(arg: BindgenRustToDartArg) -> anyhow::Result<()> {
cbindgen(
arg.rust_crate_dir,
arg.c_output_path,
arg.c_struct_names,
arg.exclude_symbols,
)?;
ffigen(
c_output_path,
dart_output_path,
dart_class_name,
llvm_install_path,
llvm_compiler_opts,
arg.c_output_path,
arg.dart_output_path,
arg.dart_class_name,
arg.llvm_install_path,
arg.llvm_compiler_opts,
)
}

Expand Down Expand Up @@ -100,12 +108,12 @@ fn cbindgen(
rust_crate_dir: &str,
c_output_path: &str,
c_struct_names: Vec<String>,
exclude_symbols: Vec<String>,
) -> anyhow::Result<()> {
debug!(
"execute cbindgen rust_crate_dir={} c_output_path={}",
rust_crate_dir, c_output_path
);

let config = cbindgen::Config {
language: cbindgen::Language::C,
sys_includes: vec![
Expand All @@ -119,6 +127,7 @@ fn cbindgen(
.iter()
.map(|name| format!("\"{}\"", name))
.collect::<Vec<_>>(),
exclude: exclude_symbols,
..Default::default()
},
..Default::default()
Expand Down
29 changes: 17 additions & 12 deletions frb_codegen/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ use structopt::clap::AppSettings;
use structopt::StructOpt;
use toml::Value;

use crate::ir::IrFile;
use crate::parser;
use crate::utils::BlockIndex;

#[derive(StructOpt, Debug, PartialEq, Deserialize, Default)]
#[structopt(setting(AppSettings::DeriveDisplayOrder))]
pub struct RawOpts {
Expand Down Expand Up @@ -58,8 +62,6 @@ pub struct RawOpts {
/// Show debug messages.
#[structopt(short, long)]
pub verbose: bool,
#[structopt(long)]
pub exclude_sync_execution_mode_utility: Option<Vec<bool>>,
}

#[derive(Debug)]
Expand All @@ -78,9 +80,7 @@ pub struct Opts {
pub manifest_path: String,
pub dart_root: Option<String>,
pub build_runner: bool,

// due to conflict of dart api of multiple blocks, keep it temporarily
pub exclude_sync_execution_mode_utility: bool,
pub block_index: BlockIndex,
}

pub fn parse(raw: RawOpts) -> Vec<Opts> {
Expand Down Expand Up @@ -185,12 +185,6 @@ pub fn parse(raw: RawOpts) -> Vec<Opts> {
.collect::<Vec<_>>(),
};

// exclude_sync_execution_mode_utility(s)
// (due to conflict of dart api of multiple blocks, keep it temporarily)
let exclude_sync_execution_mode_utilities = raw
.exclude_sync_execution_mode_utility
.unwrap_or_else(|| (0..rust_input_paths.len()).map(|i| i != 0).collect());

// build Opt for each rust api block
let dart_decl_output_path = raw
.dart_decl_output
Expand Down Expand Up @@ -222,7 +216,7 @@ pub fn parse(raw: RawOpts) -> Vec<Opts> {
manifest_path: manifest_paths[i].clone(),
dart_root: dart_roots[i].clone(),
build_runner, //same for all rust api blocks
exclude_sync_execution_mode_utility: exclude_sync_execution_mode_utilities[i],
block_index: BlockIndex(i),
}
})
.collect()
Expand Down Expand Up @@ -380,6 +374,17 @@ fn path_to_string(path: PathBuf) -> Result<String, OsString> {
}

impl Opts {
pub fn get_ir_file(&self) -> IrFile {
// info!("Phase: Parse source code to AST");
let source_rust_content = fs::read_to_string(&self.rust_input_path)
.unwrap_or_else(|_| panic!("panic with file: {}", &self.rust_input_path));
let file_ast = syn::parse_file(&source_rust_content).unwrap();

// info!("Phase: Parse AST to IR");

parser::parse(&source_rust_content, file_ast, &self.manifest_path)
}

pub fn dart_api_class_name(&self) -> String {
self.class_name.clone()
}
Expand Down
12 changes: 7 additions & 5 deletions frb_codegen/src/generator/dart/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use log::debug;
use crate::ir::IrType::*;
use crate::ir::*;
use crate::others::*;
use crate::utils::BlockIndex;

pub struct Output {
pub file_prelude: DartBasicCode,
Expand All @@ -39,6 +40,7 @@ pub fn generate(
dart_api_impl_class_name: &str,
dart_wire_class_name: &str,
dart_output_file_root: &str,
block_index: BlockIndex,
) -> (Output, bool) {
let DartApiSpec {
dart_funcs,
Expand All @@ -47,7 +49,7 @@ pub fn generate(
dart_api_fill_to_wire_funcs,
dart_wire2api_funcs,
needs_freezed,
} = get_dart_api_spec_from_ir_file(ir_file);
} = get_dart_api_spec_from_ir_file(ir_file, block_index);

let common_header = generate_common_header();

Expand Down Expand Up @@ -92,7 +94,7 @@ struct DartApiSpec {
needs_freezed: bool,
}

fn get_dart_api_spec_from_ir_file(ir_file: &IrFile) -> DartApiSpec {
fn get_dart_api_spec_from_ir_file(ir_file: &IrFile, block_index: BlockIndex) -> DartApiSpec {
let distinct_types = ir_file.distinct_types(true, true);
let distinct_input_types = ir_file.distinct_types(true, false);
let distinct_output_types = ir_file.distinct_types(false, true);
Expand All @@ -110,7 +112,7 @@ fn get_dart_api_spec_from_ir_file(ir_file: &IrFile) -> DartApiSpec {
.collect::<Vec<_>>();
let dart_api2wire_funcs = distinct_input_types
.iter()
.map(|ty| generate_api2wire_func(ty, ir_file))
.map(|ty| generate_api2wire_func(ty, ir_file, block_index))
.collect::<Vec<_>>();
let dart_api_fill_to_wire_funcs = distinct_input_types
.iter()
Expand Down Expand Up @@ -434,8 +436,8 @@ fn generate_api_func(func: &IrFunc) -> GeneratedApiFunc {
}
}

fn generate_api2wire_func(ty: &IrType, ir_file: &IrFile) -> String {
if let Some(body) = TypeDartGenerator::new(ty.clone(), ir_file).api2wire_body() {
fn generate_api2wire_func(ty: &IrType, ir_file: &IrFile, block_index: BlockIndex) -> String {
if let Some(body) = TypeDartGenerator::new(ty.clone(), ir_file).api2wire_body(block_index) {
format!(
"{} _api2wire_{}({} raw) {{
{}
Expand Down
2 changes: 1 addition & 1 deletion frb_codegen/src/generator/dart/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use enum_dispatch::enum_dispatch;

#[enum_dispatch]
pub trait TypeDartGeneratorTrait {
fn api2wire_body(&self) -> Option<String>;
fn api2wire_body(&self, block_index: BlockIndex) -> Option<String>;

fn api_fill_to_wire_body(&self) -> Option<String> {
None
Expand Down
12 changes: 9 additions & 3 deletions frb_codegen/src/generator/dart/ty_boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,27 @@ use crate::generator::dart::ty::*;
use crate::ir::IrType::{EnumRef, Primitive, StructRef};
use crate::ir::*;
use crate::type_dart_generator_struct;
use crate::utils::BlockIndex;

type_dart_generator_struct!(TypeBoxedGenerator, IrTypeBoxed);

impl TypeDartGeneratorTrait for TypeBoxedGenerator<'_> {
fn api2wire_body(&self) -> Option<String> {
fn api2wire_body(&self, block_index: BlockIndex) -> Option<String> {
Some(match &*self.ir.inner {
Primitive(_) => {
format!("return inner.new_{}(raw);", self.ir.safe_ident())
format!(
"return inner.new_{}_{}(raw);",
self.ir.safe_ident(),
block_index
)
}
inner => {
format!(
"final ptr = inner.new_{}();
"final ptr = inner.new_{}_{}();
_api_fill_to_wire_{}(raw, ptr.ref);
return ptr;",
self.ir.safe_ident(),
block_index,
inner.safe_ident(),
)
}
Expand Down
Loading

0 comments on commit 797040d

Please sign in to comment.