-
Notifications
You must be signed in to change notification settings - Fork 56
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[native_assets_cli] Add example for downloading assets (#1860)
Add an example for how to download assets in a hook which are built on GitHub CI. Design approach: * `tool/build.dart` uses `package:native_toolchain_c`. * GitHub action that publishes artifacts on a tag (not the package release tag). * `hook/build.dart` downloads the artifacts. * `tool/generate_asset_hashes.dart` generates hashes that are used in `hook/build.dart` to check download integrity. GitHub actions mostly cargo culted from: * https://github.com/dart-lang/i18n/blob/83e8d08568e26888dc0252c89f5d1faf92052e44/.github/workflows/intl4x_artifacts.yml Closes: #157
- Loading branch information
Showing
19 changed files
with
615 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# A workflow that goes together with the example package:download_asset inside | ||
# package:native_assets_cli. | ||
name: package_download_asset | ||
|
||
permissions: | ||
contents: write | ||
|
||
on: | ||
pull_request: | ||
branches: [ main ] | ||
paths: | ||
- .github/workflows/package_download_asset.yaml | ||
- pkgs/native_assets_cli/example/build/download_asset/ | ||
push: | ||
tags: | ||
- 'download_asset-prebuild-assets-*' | ||
workflow_dispatch: | ||
|
||
jobs: | ||
build: | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
os: [ubuntu, macos, windows] | ||
|
||
runs-on: ${{ matrix.os }}-latest | ||
|
||
defaults: | ||
run: | ||
working-directory: pkgs/native_assets_cli/example/build/download_asset/ | ||
|
||
steps: | ||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | ||
|
||
- uses: dart-lang/setup-dart@e630b99d28a3b71860378cafdc2a067c71107f94 | ||
with: | ||
sdk: stable | ||
|
||
- uses: nttld/setup-ndk@afb4c9964b521afb97c864b7d40b11e6911bd410 | ||
with: | ||
ndk-version: r27 | ||
if: ${{ matrix.os == 'ubuntu' }} # Only build on one host. | ||
|
||
- name: Install native toolchains | ||
run: sudo apt-get update && sudo apt-get install clang-15 gcc-i686-linux-gnu gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf gcc-riscv64-linux-gnu | ||
if: ${{ matrix.os == 'ubuntu' }} | ||
|
||
- run: dart pub get | ||
|
||
# Keep this list consistent with pkgs/native_assets_cli/example/build/download_asset/lib/src/hook_helpers/target_versions.dart | ||
- name: Build Linux host | ||
if: matrix.os == 'ubuntu' | ||
run: | | ||
dart tool/build.dart -oandroid -aarm | ||
dart tool/build.dart -oandroid -aarm64 | ||
dart tool/build.dart -oandroid -aia32 | ||
dart tool/build.dart -oandroid -ariscv64 | ||
dart tool/build.dart -oandroid -ax64 | ||
dart tool/build.dart -olinux -aarm | ||
dart tool/build.dart -olinux -aarm64 | ||
dart tool/build.dart -olinux -aia32 | ||
dart tool/build.dart -olinux -ariscv64 | ||
dart tool/build.dart -olinux -ax64 | ||
- name: Build MacOS host | ||
if: matrix.os == 'macos' | ||
run: | | ||
dart tool/build.dart -omacos -aarm64 | ||
dart tool/build.dart -omacos -ax64 | ||
dart tool/build.dart -oios -iiphoneos -aarm64 | ||
dart tool/build.dart -oios -iiphonesimulator -aarm64 | ||
dart tool/build.dart -oios -iiphonesimulator -ax64 | ||
- name: Build Windows host | ||
if: matrix.os == 'windows' | ||
run: | | ||
dart tool/build.dart -owindows -aarm | ||
dart tool/build.dart -owindows -aarm64 | ||
dart tool/build.dart -owindows -aia32 | ||
dart tool/build.dart -owindows -ax64 | ||
- name: Upload artifacts | ||
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 | ||
with: | ||
name: ${{ matrix.os }}-host | ||
path: | | ||
pkgs/native_assets_cli/example/build/download_asset/.dart_tool/download_asset/**/*.dll | ||
pkgs/native_assets_cli/example/build/download_asset/.dart_tool/download_asset/**/*.dylib | ||
pkgs/native_assets_cli/example/build/download_asset/.dart_tool/download_asset/**/*.so | ||
if-no-files-found: error | ||
|
||
release: | ||
needs: build | ||
runs-on: ubuntu-latest | ||
|
||
defaults: | ||
run: | ||
working-directory: pkgs/native_assets_cli/example/build/download_asset/ | ||
|
||
steps: | ||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 | ||
with: | ||
submodules: true | ||
|
||
- name: Download assets | ||
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 | ||
with: | ||
merge-multiple: true | ||
path: pkgs/native_assets_cli/example/build/download_asset/.dart_tool/download_asset/ | ||
|
||
- name: Display structure of downloaded assets | ||
run: ls -R .dart_tool/download_asset/ | ||
|
||
- name: Release | ||
uses: softprops/action-gh-release@e7a8f85e1c67a31e6ed99a94b41bd0b71bbee6b8 | ||
if: startsWith(github.ref, 'refs/tags/download_asset-prebuild-assets') | ||
with: | ||
files: 'pkgs/native_assets_cli/example/build/download_asset/.dart_tool/download_asset/**' | ||
fail_on_unmatched_files: true |
15 changes: 15 additions & 0 deletions
15
pkgs/native_assets_cli/example/build/download_asset/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
An example of a library depending on prebuilt assets which are downloaded in | ||
the build hook. | ||
|
||
## Usage | ||
|
||
Run tests with `dart --enable-experiment=native-assets test`. | ||
|
||
## Code organization | ||
|
||
A typical layout of a package which downloads assets: | ||
|
||
* `tool/build.dart` prebuilts assets and is exercised from a GitHub workflow. | ||
* A [GitHub workflow](../../../../../.github/workflows/package_download_asset.yaml) that builds assets. | ||
* `hook/build.dart` downloads the prebuilt assets. | ||
* `lib/` contains Dart code which uses the assets. |
20 changes: 20 additions & 0 deletions
20
pkgs/native_assets_cli/example/build/download_asset/ffigen.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Run with `flutter pub run ffigen --config ffigen.yaml`. | ||
name: NativeAddBindings | ||
description: | | ||
Bindings for `src/native_add.h`. | ||
Regenerate bindings with `flutter pub run ffigen --config ffigen.yaml`. | ||
output: 'lib/native_add.dart' | ||
headers: | ||
entry-points: | ||
- 'src/native_add.h' | ||
include-directives: | ||
- 'src/native_add.h' | ||
preamble: | | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
comments: | ||
style: any | ||
length: full | ||
ffi-native: |
54 changes: 54 additions & 0 deletions
54
pkgs/native_assets_cli/example/build/download_asset/hook/build.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:download_asset/src/hook_helpers/c_build.dart'; | ||
import 'package:download_asset/src/hook_helpers/download.dart'; | ||
import 'package:download_asset/src/hook_helpers/hashes.dart'; | ||
import 'package:native_assets_cli/code_assets_builder.dart'; | ||
import 'package:native_assets_cli/native_assets_cli.dart'; | ||
|
||
void main(List<String> args) async { | ||
// TODO(https://github.com/dart-lang/native/issues/39): Use user-defines to | ||
// control this instead. | ||
const localBuild = false; | ||
|
||
await build(args, (input, output) async { | ||
// ignore: dead_code | ||
if (localBuild) { | ||
await runBuild(input, output); | ||
} else { | ||
final targetOS = input.config.code.targetOS; | ||
final targetArchitecture = input.config.code.targetArchitecture; | ||
final iOSSdk = | ||
targetOS == OS.iOS ? input.config.code.iOS.targetSdk : null; | ||
final outputDirectory = Directory.fromUri(input.outputDirectory); | ||
final file = await downloadAsset( | ||
targetOS, | ||
targetArchitecture, | ||
iOSSdk, | ||
outputDirectory, | ||
); | ||
final fileHash = await hashAsset(file); | ||
final expectedHash = assetHashes[createTargetName( | ||
targetOS.name, | ||
targetArchitecture.name, | ||
iOSSdk?.type, | ||
)]; | ||
if (fileHash != expectedHash) { | ||
throw Exception('File $file was not downloaded correctly. ' | ||
'Found hash $fileHash, expected $expectedHash.'); | ||
} | ||
output.assets.code.add(CodeAsset( | ||
package: input.packageName, | ||
name: 'native_add.dart', | ||
linkMode: DynamicLoadingBundled(), | ||
os: targetOS, | ||
architecture: targetArchitecture, | ||
file: file.uri, | ||
)); | ||
} | ||
}); | ||
} |
15 changes: 15 additions & 0 deletions
15
pkgs/native_assets_cli/example/build/download_asset/lib/native_add.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
// 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)>(symbol: 'add') | ||
external int add( | ||
int a, | ||
int b, | ||
); |
39 changes: 39 additions & 0 deletions
39
pkgs/native_assets_cli/example/build/download_asset/lib/src/hook_helpers/c_build.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import 'package:logging/logging.dart'; | ||
import 'package:native_assets_cli/code_assets_builder.dart'; | ||
import 'package:native_toolchain_c/native_toolchain_c.dart'; | ||
|
||
Future<void> runBuild(BuildInput input, BuildOutputBuilder output) async { | ||
final name = createTargetName( | ||
input.config.code.targetOS.name, | ||
input.config.code.targetArchitecture.name, | ||
input.config.code.targetOS == OS.iOS | ||
? input.config.code.iOS.targetSdk.type | ||
: null, | ||
); | ||
final cbuilder = CBuilder.library( | ||
name: name, | ||
assetName: 'native_add.dart', | ||
sources: [ | ||
'src/native_add.c', | ||
], | ||
); | ||
await cbuilder.run( | ||
input: input, | ||
output: output, | ||
logger: Logger('') | ||
..level = Level.ALL | ||
..onRecord.listen((record) => print(record.message)), | ||
); | ||
} | ||
|
||
String createTargetName(String osString, String architecture, String? iOSSdk) { | ||
var targetName = 'native_add_${osString}_$architecture'; | ||
if (iOSSdk != null) { | ||
targetName += '_$iOSSdk'; | ||
} | ||
return targetName; | ||
} |
46 changes: 46 additions & 0 deletions
46
pkgs/native_assets_cli/example/build/download_asset/lib/src/hook_helpers/download.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
import 'dart:io'; | ||
|
||
import 'package:crypto/crypto.dart'; | ||
import 'package:native_assets_cli/code_assets_builder.dart'; | ||
|
||
import 'c_build.dart'; | ||
import 'version.dart'; | ||
|
||
Uri downloadUri(String target) => Uri.parse( | ||
'https://github.com/dart-lang/native/releases/download/$version/$target'); | ||
|
||
Future<File> downloadAsset( | ||
OS targetOS, | ||
Architecture targetArchitecture, | ||
IOSSdk? iOSSdk, | ||
Directory outputDirectory, | ||
) async { | ||
final targetName = targetOS.dylibFileName(createTargetName( | ||
targetOS.name, | ||
targetArchitecture.name, | ||
iOSSdk?.type, | ||
)); | ||
final uri = downloadUri(targetName); | ||
final request = await HttpClient().getUrl(uri); | ||
final response = await request.close(); | ||
if (response.statusCode != 200) { | ||
throw ArgumentError('The request to $uri failed.'); | ||
} | ||
final library = File.fromUri(outputDirectory.uri.resolve(targetName)); | ||
await library.create(); | ||
await response.pipe(library.openWrite()); | ||
return library; | ||
} | ||
|
||
Future<String> hashAsset(File assetFile) async { | ||
// TODO(dcharkes): Should this be a strong hash to not only check for download | ||
// integrity but also safeguard against tampering? This would protected | ||
// against the case where the binary hoster is compromised but pub is not | ||
// compromised. | ||
final fileHash = md5.convert(await assetFile.readAsBytes()).toString(); | ||
return fileHash; | ||
} |
31 changes: 31 additions & 0 deletions
31
pkgs/native_assets_cli/example/build/download_asset/lib/src/hook_helpers/hashes.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
// THIS FILE IS AUTOGENERATED. TO UPDATE, RUN | ||
// | ||
// dart --enable-experiment=native-assets tool/generate_asset_hashes.dart | ||
// | ||
|
||
const assetHashes = <String, String>{ | ||
'libnative_add_android_arm.so': '2c38f3edc805a399dad866d619f9157d', | ||
'libnative_add_android_arm64.so': 'c4f0d8c4c50d1e83592e499e7434b967', | ||
'libnative_add_android_ia32.so': 'e3277144d97bd2c54beee581ed7e6665', | ||
'libnative_add_android_riscv64.so': '8c2576cbe75c9a23f2532ff895f94f76', | ||
'libnative_add_android_x64.so': '9a7bec53e1591091669ecd2bd20911d1', | ||
'libnative_add_ios_arm64_iphoneos.dylib': '1bf1473cacb7fd2778fc5bb28f0b61a2', | ||
'libnative_add_ios_arm64_iphonesimulator.dylib': | ||
'cdddffc0787e6a3a846affcb05fac3a8', | ||
'libnative_add_ios_x64_iphonesimulator.dylib': | ||
'4aea6d631350540d50452ac2bdd1a422', | ||
'libnative_add_linux_arm.so': '1a5b9e4b459e13ee85c148582b9b2252', | ||
'libnative_add_linux_arm64.so': '2b3d736e0c0ac1e1537bc43bd9b82cad', | ||
'libnative_add_linux_ia32.so': 'ed6e130e53fa18eab5572ed106cdaab1', | ||
'libnative_add_linux_riscv64.so': '7fa82325ba7803a0443ca27e3300e7f9', | ||
'libnative_add_linux_x64.so': 'f7af8d1547cdfb150a73d513a7957999', | ||
'libnative_add_macos_arm64.dylib': 'f0804ff4b55126996c180114f25ca5bd', | ||
'libnative_add_macos_x64.dylib': 'b62263803dceb3c23508cb909b5a5583', | ||
'native_add_windows_arm64.dll': '7aa6f5e0275ba1b94cd5b7356f89ef04', | ||
'native_add_windows_ia32.dll': 'ab57b5504d92b5b5dc09732d990fd5e7', | ||
'native_add_windows_x64.dll': 'be9ba2125800aa2e3481a759b1845a50', | ||
}; |
7 changes: 7 additions & 0 deletions
7
.../native_assets_cli/example/build/download_asset/lib/src/hook_helpers/target_versions.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
|
||
const androidTargetNdkApi = 30; | ||
const int macOSTargetVersion = 13; | ||
const iOSTargetVersion = 16; |
31 changes: 31 additions & 0 deletions
31
pkgs/native_assets_cli/example/build/download_asset/lib/src/hook_helpers/targets.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Copyright (c, null) 2025, the Dart project authors. Please see the AUTHORS | ||
// file for details. All rights reserved. Use of this source code is governed by | ||
// a BSD-style license that can be found in the LICENSE file. | ||
|
||
// THIS FILE IS AUTOGENERATED. TO UPDATE, RUN | ||
// | ||
// dart --enable-experiment=native-assets tool/generate_asset_hashes.dart | ||
// | ||
|
||
import 'package:native_assets_cli/code_assets_builder.dart'; | ||
|
||
const supportedTargets = [ | ||
(OS.android, Architecture.arm, null), | ||
(OS.android, Architecture.arm64, null), | ||
(OS.android, Architecture.ia32, null), | ||
(OS.android, Architecture.riscv64, null), | ||
(OS.android, Architecture.x64, null), | ||
(OS.iOS, Architecture.arm64, IOSSdk.iPhoneOS), | ||
(OS.iOS, Architecture.arm64, IOSSdk.iPhoneSimulator), | ||
(OS.iOS, Architecture.x64, IOSSdk.iPhoneSimulator), | ||
(OS.linux, Architecture.arm, null), | ||
(OS.linux, Architecture.arm64, null), | ||
(OS.linux, Architecture.ia32, null), | ||
(OS.linux, Architecture.riscv64, null), | ||
(OS.linux, Architecture.x64, null), | ||
(OS.macOS, Architecture.arm64, null), | ||
(OS.macOS, Architecture.x64, null), | ||
(OS.windows, Architecture.arm64, null), | ||
(OS.windows, Architecture.ia32, null), | ||
(OS.windows, Architecture.x64, null), | ||
]; |
Oops, something went wrong.