Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

☂️ Native assets support #129757

Open
12 of 22 tasks
dcharkes opened this issue Jun 29, 2023 · 12 comments
Open
12 of 22 tasks

☂️ Native assets support #129757

dcharkes opened this issue Jun 29, 2023 · 12 comments
Assignees
Labels
c: new feature Nothing broken; request for a new capability c: proposal A detailed proposal for a change to Flutter P2 Important issues not at the top of the work list team-tool Owned by Flutter Tool team tool Affects the "flutter" command-line tool. See also t: labels. triaged-tool Triaged by Flutter Tool team

Comments

@dcharkes
Copy link
Contributor

dcharkes commented Jun 29, 2023

Native assets support in Flutter MacOS, iOS, Linux, and Windows is available on the master channel behind an experimental flag: flutter config --enable-native-assets and flutter create --template=package_ffi [package name].

A high level tracking issue for supporting native assets.

Native assets enables packages to specify a top-level build.dart that is invoked by launchers (dartdev and flutter_tools) to build/download native libraries and communicate back which native libraries need to be bundled and under which "asset id".

From a Flutter context, the native assets feature will enable testing native code with flutter test, which the FFI plugins do not support. From a Dart Flutter context packages will be compatible with both Dart and Flutter, removing the need for publishing two versions on pub (one for Dart and one for Flutter).

More details can be found in:

Dart standalone support has landed behind an experimental flag (dart --enable-experiment=native-assets).

This issue tracks implementing native assets in flutter tools

Use cases that should be supported

  • flutter run
    • debug
      • hot reload (1)
      • hot restart (1)
    • release/profile
  • flutter build debug/release/profile
  • flutter test / dart test
  • add-2-app (e.g. flutter build macos-framework for MacOS)
  • flutter run -dflutter-tester

Test coverage will be through end-to-end integration tests that exercise the dynamic libraries provided by packages.

Landing plan is to land this behind an experimental flag on the main branch only. This has the following benefits:

  • Support for the various OSes can be in separate CLs, simplifying code review.
  • We defer settling on the actual build.dart protocol until before we get it out of experimental. Users should not publish packages on pub.dev while this feature is in experimental phase.
  • Making this available in experimental enables users to give this feature a spin without having to build their own version of Dart or Flutter. Getting their feedback is important to us to get this feature right.

Please feel free to note additional use cases that we have missed or ask questions on this issue.

Foot notes:

  1. This does not bundle new native libraries, but the already bundled native libraries should be accessible.

References:

cc @stuartmorgan @vashworth

Ongoing work related to native assets, build.dart and link.dart hooks:

@dcharkes dcharkes self-assigned this Jun 29, 2023
@danagbemava-nc danagbemava-nc added in triage Presently being triaged by the triage team c: new feature Nothing broken; request for a new capability tool Affects the "flutter" command-line tool. See also t: labels. c: proposal A detailed proposal for a change to Flutter and removed in triage Presently being triaged by the triage team labels Jun 29, 2023
@flutter-triage-bot flutter-triage-bot bot added the team-tool Owned by Flutter Tool team label Jul 8, 2023
fluttermirroringbot pushed a commit that referenced this issue Sep 10, 2023
Support for FFI calls with `@Native external` functions through Native assets on MacOS and iOS. This enables bundling native code without any build-system boilerplate code.

For more info see:

* #129757

### Implementation details for MacOS and iOS.

Dylibs are bundled by (1) making them fat binaries if multiple architectures are targeted, (2) code signing these, and (3) copying them to the frameworks folder. These steps are done manual rather than via CocoaPods. CocoaPods would have done the same steps, but (a) needs the dylibs to be there before the `xcodebuild` invocation (we could trick it, by having a minimal dylib in the place and replace it during the build process, that works), and (b) can't deal with having no dylibs to be bundled (we'd have to bundle a dummy dylib or include some dummy C code in the build file).

The dylibs are build as a new target inside flutter assemble, as that is the moment we know what build-mode and architecture to target.

The mapping from asset id to dylib-path is passed in to every kernel compilation path. The interesting case is hot-restart where the initial kernel file is compiled by the "inner" flutter assemble, while after hot restart the "outer" flutter run compiled kernel file is pushed to the device. Both kernel files need to contain the mapping. The "inner" flutter assemble gets its mapping from the NativeAssets target which builds the native assets. The "outer" flutter run get its mapping from a dry-run invocation. Since this hot restart can be used for multiple target devices (`flutter run -d all`) it contains the mapping for all known targets.

### Example vs template

The PR includes a new template that uses the new native assets in a package and has an app importing that. Separate discussion in: #131209.

### Tests

This PR adds new tests to cover the various use cases.

* dev/devicelab/bin/tasks/native_assets_ios.dart
  * Runs an example app with native assets in all build modes, doing hot reload and hot restart in debug mode.
* dev/devicelab/bin/tasks/native_assets_ios_simulator.dart
  * Runs an example app with native assets, doing hot reload and hot restart.
* packages/flutter_tools/test/integration.shard/native_assets_test.dart
  * Runs (incl hot reload/hot restart), builds, builds frameworks for iOS, MacOS and flutter-tester.
* packages/flutter_tools/test/general.shard/build_system/targets/native_assets_test.dart
  * Unit tests the new Target in the backend.
* packages/flutter_tools/test/general.shard/ios/native_assets_test.dart
* packages/flutter_tools/test/general.shard/macos/native_assets_test.dart
  * Unit tests the native assets being packaged on a iOS/MacOS build.

It also extends various existing tests:

* dev/devicelab/bin/tasks/module_test_ios.dart
   * Exercises the add2app scenario.
* packages/flutter_tools/test/general.shard/features_test.dart
   * Unit test the new feature flag.
auto-submit bot pushed a commit that referenced this issue Sep 18, 2023
Support for FFI calls with `@Native external` functions through Native assets on Linux. This enables bundling native code without any build-system boilerplate code.

For more info see:

* #129757

### Implementation details for Linux.

Mainly follows the design of #130494.

Some differences are:

* Linux does not support cross compiling or compiling for multiple architectures, so this has not been implemented.
* Linux has no add2app.

The assets copying is done in the install-phase of the CMake build of a flutter app.
CMake requires the native assets folder to exist, so we create it also when the feature is disabled or there are no assets.

### Tests

This PR adds new tests to cover the various use cases.

* packages/flutter_tools/test/general.shard/linux/native_assets_test.dart
  * Unit tests the Linux-specific part of building native assets.

It also extends various existing tests:

* packages/flutter_tools/test/integration.shard/native_assets_test.dart
  * Runs (incl hot reload/hot restart), builds, builds frameworks for Linux and flutter-tester.
auto-submit bot pushed a commit that referenced this issue Sep 19, 2023
Move test added in #130494 out of staging.

* https://ci.chromium.org/ui/p/flutter/builders/luci.flutter.staging/Mac_ios native_assets_ios
* https://ci.chromium.org/ui/p/flutter/builders/luci.flutter.staging/Mac_ios native_assets_ios_simulator

> Monitor the CI results of the new shard on the [Flutter build dashboard](https://flutter-dashboard.appspot.com/#/build). After 50 consecutive passing builds without any flakes, the flake bot will create a PR to remove the bringup: true parameter from .ci.yaml in the Framework tree. This will allow the test to block the tree, preventing breakages. With this change, the new shard will start running in presubmit automatically, unless specify presubmit: false.

https://github.com/flutter/flutter/wiki/Adding-a-new-Test-Shard#steps-to-add-a-new-framework-test-shard

Umbrella issue:

* #129757
@amorenew
Copy link

amorenew commented Feb 6, 2024

@dcharkes I wonder if you could give me an example of use cases for this feature?

@dcharkes
Copy link
Contributor Author

dcharkes commented Feb 6, 2024

@dcharkes I wonder if you could give me an example of use cases for this feature?

dart-lang/sdk#50565

Any use case in which you want to call native code and bundle that native code:

@amorenew
Copy link

amorenew commented Feb 6, 2024

@dcharkes Thanks a lot for clarification

@nmfisher
Copy link

nmfisher commented Mar 4, 2024

@dcharkes does this also support compiling code then linking to third-party/precompiled static libraries (and by extension, specifying the platform-specific path to these libraries in build.dart)?

@dcharkes
Copy link
Contributor Author

dcharkes commented Mar 4, 2024

@dcharkes does this also support compiling code then linking to third-party/precompiled static libraries (and by extension, specifying the platform-specific path to these libraries in build.dart)?

Currently the only constraint is that the output must be a dynamic library. So as long as that static library is linked into a dynamic library everything works. We can invoke arbitrary native tools in your build.dart script, so we can invoke the linker to do this.

@nmfisher
Copy link

nmfisher commented Mar 4, 2024

@dcharkes thanks for the quick response. Are there any examples for invoking the native build tools, or do you mean simply using regular Dart like Process.run?

@dcharkes
Copy link
Contributor Author

dcharkes commented Mar 4, 2024

Simply Process.run, or use a helper package that uses Process.run under the hood.

The helper package native_toolchain_c wraps the C compilers. It doesn't have an API yet to invoke the linker separately, but you're welcome to make a PR.

Let's move the discussion there. Please open an issue (or PR!) on that repo.

@nmfisher
Copy link

nmfisher commented May 9, 2024

There's two errors thrown by Xcode 15.3 when submitting Flutter apps built with native_assets to the App Store.

First is:

 This bundle is invalid. The bundle at path Payload/Runner.app/Frameworks/sherpa_onnx_dart.framework has an invalid CFBundleIdentifier 'io.flutter.flutter.native_assets.sherpa_onnx_dart' There are invalid characters(characters that are not dots, hyphen and alphanumerics) that have been replaced with their code point 'io.flutter.flutter.native\\u005fassets.sherpa\\u005fonnx\\u005fdart' CFBundleIdentifier must be present, must contain only alphanumerics, dots, hyphens and must not end with a dot.

Per the Apple reference, underscores can't be used in CFBundleIdentifier, so perhaps we could replace hyphens with underscores here, e.g.

<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.native-assets.${name.replaceAll("_", "-")}</string>

The second issue is similar, the generated Info.plist does not contain an entry for MinimumOSVersion, so trying to publish via XCode will throw the following error:

Asset validation failed. Missing Info.plist value. A value for the key 'MinimumOSVersion' in bundle Runner.app/Frameworks/sherpa-onnx-dart.framework is required.

Workaround is to add the following to native_assets_host.dart

  <key>MinimumOSVersion</key>
  <string>13.0</string>

I haven't submitted a PR because I suspect there's a broader fix to the native_assets framework build process to consume some user-specified configuration (e.g. this may be contemplated by this issue here.

@knopp
Copy link
Member

knopp commented Jun 10, 2024

@dcharkes, is there any timeline or estimation for when native assets will move out of the experimental flag?

@dcharkes
Copy link
Contributor Author

@dcharkes, is there any timeline or estimation for when native assets will move out of the experimental flag?

Unfortunately I cannot give an estimation.

We're working hard on getting some other pieces in place that are needed for the build and link hooks. And these will likely cause breaking changes to the hook APIs and the protocol between the Dart/Flutter SDK and the hooks. Some issues to follow besides this one:

@Attempt3035
Copy link

Attempt3035 commented Jul 4, 2024

Hi all! I've been working on a little utility to help make it easier to build native assets with bazel and incorporate them into flutter or dart applications. Currently, it's working for Android, iOS & MacOS, haven't had a chance to test on Linux and Windows yet.

It's main role is to build dynamic libs for the defined platforms, bundle in the assets, plus give a typesafe & platform independent abstraction to load the libraries in code.

Give it a go at bazel_builder

I'm wondering if:
A) This will be somehow natively supported (having alternate build systems such as Bazel)
B) If not, are there community suggestions on how to improve this system using build hooks to automate it and feeding the artifacts back through to flutter to bundle with the app
C) Is anyone else interested in this? For many of my projects, it's proving awesome to be able to basically use anything from registry.bazel.build plus the great Bazel build system in my flutter apps on all platforms. Curious to see if anyone else thinks this is valuable!

Note: This is also relevant for dart-lang/sdk#50565, I haven't had a chance to test how assets should be bundled with dart yet though.

@dcharkes
Copy link
Contributor Author

dcharkes commented Jul 4, 2024

Hi all! I've been working on a little utility to help make it easier to build native assets with bazel and incorporate them into flutter or dart applications. Currently, it's working for Android, iOS & MacOS, haven't had a chance to test on Linux and Windows yet.

It's main role is to build dynamic libs for the defined platforms, bundle in the assets, plus give a typesafe & platform independent abstraction to load the libraries in code.

Give it a go at bazel_builder

Very cool!

I'm wondering if: A) This will be somehow natively supported (having alternate build systems such as Bazel)

We have considered making Dart and Flutter bazel builds, but this seems out of reach for now. Maybe @mraleph can comment.

With native assets we have at least a well-defined protocol. But of course it is not as powerful as arbitrary bazel build files.

B) If not, are there community suggestions on how to improve this system using build hooks to automate it and feeding the artifacts back through to flutter to bundle with the app

Native assets would be the way to go. The native assets (build hooks) are the well-defined extension point. (Note it's currently only available in an experiment.)

C) Is anyone else interested in this? For many of my projects, it's proving awesome to be able to basically use anything from registry.bazel.build plus the great Bazel build system in my flutter apps on all platforms. Curious to see if anyone else thinks this is valuable!

I'd love it. But I don't actually build any apps. 🙃 Every once in a while people give it a shot. Some shots in the past: https://github.com/dart-archive/bazel/tree/master/dazel, https://github.com/scalio/bazel-flutter.

Note: This is also relevant for dart-lang/sdk#50565, I haven't had a chance to test how assets should be bundled with dart yet though.

Flutter also supports native assets. You're replying to the native assets tracking issue, but your example doesn't use hook/build.dart (what this issue is tracking) and still have OS-specific build files. I'd love to see a class BazelBuilder to be used from hook/build.dart. Let's continue such discussion in:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: new feature Nothing broken; request for a new capability c: proposal A detailed proposal for a change to Flutter P2 Important issues not at the top of the work list team-tool Owned by Flutter Tool team tool Affects the "flutter" command-line tool. See also t: labels. triaged-tool Triaged by Flutter Tool team
Projects
None yet
Development

No branches or pull requests

7 participants