>(paths: Vec) -> String {
9 | match paths.len() {
10 | 0 => String::default(),
11 | _ => {
12 | let mut path: PathBuf = PathBuf::new();
13 | for x in paths {
14 | path = path.join(x);
15 | }
16 | return path.to_str().unwrap().to_string();
17 | }
18 | }
19 | }
20 |
21 | pub(crate) fn create_dir_if_not_exists(path: &str) {
22 | if !Path::new(path).exists() {
23 | std::fs::create_dir_all(path).unwrap();
24 | }
25 | }
26 |
27 | lazy_static! {
28 | static ref HASH_LOCK: Vec> = {
29 | let mut mutex_vec: Vec> = vec![];
30 | for _ in 0..256 {
31 | mutex_vec.push(Mutex::<()>::new(()));
32 | }
33 | mutex_vec
34 | };
35 | }
36 |
37 | pub(crate) async fn hash_lock(url: &String) -> MutexGuard<'static, ()> {
38 | let mut s = DefaultHasher::new();
39 | s.write(url.as_bytes());
40 | HASH_LOCK[s.finish() as usize % HASH_LOCK.len()]
41 | .lock()
42 | .await
43 | }
44 |
45 | pub(crate) fn allowed_file_name(title: &str) -> String {
46 | title
47 | .replace("#", "_")
48 | .replace("'", "_")
49 | .replace("/", "_")
50 | .replace("\\", "_")
51 | .replace(":", "_")
52 | .replace("*", "_")
53 | .replace("?", "_")
54 | .replace("\"", "_")
55 | .replace(">", "_")
56 | .replace("<", "_")
57 | .replace("|", "_")
58 | .replace("&", "_")
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/rust_builder/.gitignore:
--------------------------------------------------------------------------------
1 | # Miscellaneous
2 | *.class
3 | *.log
4 | *.pyc
5 | *.swp
6 | .DS_Store
7 | .atom/
8 | .buildlog/
9 | .history
10 | .svn/
11 | migrate_working_dir/
12 |
13 | # IntelliJ related
14 | *.iml
15 | *.ipr
16 | *.iws
17 | .idea/
18 |
19 | # The .vscode folder contains launch configuration and tasks you configure in
20 | # VS Code which you may wish to be included in version control, so this line
21 | # is commented out by default.
22 | #.vscode/
23 |
24 | # Flutter/Dart/Pub related
25 | # Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26 | /pubspec.lock
27 | **/doc/api/
28 | .dart_tool/
29 | build/
30 |
--------------------------------------------------------------------------------
/rust_builder/README.md:
--------------------------------------------------------------------------------
1 | Please ignore this folder, which is just glue to build Rust with Flutter.
--------------------------------------------------------------------------------
/rust_builder/android/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .cxx
10 |
--------------------------------------------------------------------------------
/rust_builder/android/build.gradle:
--------------------------------------------------------------------------------
1 | // The Android Gradle Plugin builds the native code with the Android NDK.
2 |
3 | group 'com.flutter_rust_bridge.rust_lib_kobi'
4 | version '1.0'
5 |
6 | buildscript {
7 | repositories {
8 | google()
9 | mavenCentral()
10 | }
11 |
12 | dependencies {
13 | // The Android Gradle Plugin knows how to build native code with the NDK.
14 | classpath 'com.android.tools.build:gradle:7.3.0'
15 | }
16 | }
17 |
18 | rootProject.allprojects {
19 | repositories {
20 | google()
21 | mavenCentral()
22 | }
23 | }
24 |
25 | apply plugin: 'com.android.library'
26 |
27 | android {
28 | if (project.android.hasProperty("namespace")) {
29 | namespace 'com.flutter_rust_bridge.rust_lib_kobi'
30 | }
31 |
32 | // Bumping the plugin compileSdkVersion requires all clients of this plugin
33 | // to bump the version in their app.
34 | compileSdkVersion 33
35 |
36 | // Use the NDK version
37 | // declared in /android/app/build.gradle file of the Flutter project.
38 | // Replace it with a version number if this plugin requires a specfic NDK version.
39 | // (e.g. ndkVersion "23.1.7779620")
40 | ndkVersion android.ndkVersion
41 |
42 | compileOptions {
43 | sourceCompatibility JavaVersion.VERSION_1_8
44 | targetCompatibility JavaVersion.VERSION_1_8
45 | }
46 |
47 | defaultConfig {
48 | minSdkVersion 19
49 | }
50 | }
51 |
52 | apply from: "../cargokit/gradle/plugin.gradle"
53 | cargokit {
54 | manifestDir = "../../rust"
55 | libname = "rust_lib_kobi"
56 | }
57 |
--------------------------------------------------------------------------------
/rust_builder/android/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'rust_lib_kobi'
2 |
--------------------------------------------------------------------------------
/rust_builder/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .dart_tool
3 | *.iml
4 | !pubspec.lock
5 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/LICENSE:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | Copyright 2022 Matej Knopp
5 |
6 | ================================================================================
7 |
8 | MIT LICENSE
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
14 | of the Software, and to permit persons to whom the Software is furnished to do
15 | so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
22 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
23 | OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 |
27 | ================================================================================
28 |
29 | APACHE LICENSE, VERSION 2.0
30 |
31 | Licensed under the Apache License, Version 2.0 (the "License");
32 | you may not use this file except in compliance with the License.
33 | You may obtain a copy of the License at
34 |
35 | http://www.apache.org/licenses/LICENSE-2.0
36 |
37 | Unless required by applicable law or agreed to in writing, software
38 | distributed under the License is distributed on an "AS IS" BASIS,
39 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
40 | See the License for the specific language governing permissions and
41 | limitations under the License.
42 |
43 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/README:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | Experimental repository to provide glue for seamlessly integrating cargo build
5 | with flutter plugins and packages.
6 |
7 | See https://matejknopp.com/post/flutter_plugin_in_rust_with_no_prebuilt_binaries/
8 | for a tutorial on how to use Cargokit.
9 |
10 | Example plugin available at https://github.com/irondash/hello_rust_ffi_plugin.
11 |
12 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_pod.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | set -e
3 |
4 | BASEDIR=$(dirname "$0")
5 |
6 | # Workaround for https://github.com/dart-lang/pub/issues/4010
7 | BASEDIR=$(cd "$BASEDIR" ; pwd -P)
8 |
9 | # Remove XCode SDK from path. Otherwise this breaks tool compilation when building iOS project
10 | NEW_PATH=`echo $PATH | tr ":" "\n" | grep -v "Contents/Developer/" | tr "\n" ":"`
11 |
12 | export PATH=${NEW_PATH%?} # remove trailing :
13 |
14 | env
15 |
16 | # Platform name (macosx, iphoneos, iphonesimulator)
17 | export CARGOKIT_DARWIN_PLATFORM_NAME=$PLATFORM_NAME
18 |
19 | # Arctive architectures (arm64, armv7, x86_64), space separated.
20 | export CARGOKIT_DARWIN_ARCHS=$ARCHS
21 |
22 | # Current build configuration (Debug, Release)
23 | export CARGOKIT_CONFIGURATION=$CONFIGURATION
24 |
25 | # Path to directory containing Cargo.toml.
26 | export CARGOKIT_MANIFEST_DIR=$PODS_TARGET_SRCROOT/$1
27 |
28 | # Temporary directory for build artifacts.
29 | export CARGOKIT_TARGET_TEMP_DIR=$TARGET_TEMP_DIR
30 |
31 | # Output directory for final artifacts.
32 | export CARGOKIT_OUTPUT_DIR=$PODS_CONFIGURATION_BUILD_DIR/$PRODUCT_NAME
33 |
34 | # Directory to store built tool artifacts.
35 | export CARGOKIT_TOOL_TEMP_DIR=$TARGET_TEMP_DIR/build_tool
36 |
37 | # Directory inside root project. Not necessarily the top level directory of root project.
38 | export CARGOKIT_ROOT_PROJECT_DIR=$SRCROOT
39 |
40 | FLUTTER_EXPORT_BUILD_ENVIRONMENT=(
41 | "$PODS_ROOT/../Flutter/ephemeral/flutter_export_environment.sh" # macOS
42 | "$PODS_ROOT/../Flutter/flutter_export_environment.sh" # iOS
43 | )
44 |
45 | for path in "${FLUTTER_EXPORT_BUILD_ENVIRONMENT[@]}"
46 | do
47 | if [[ -f "$path" ]]; then
48 | source "$path"
49 | fi
50 | done
51 |
52 | sh "$BASEDIR/run_build_tool.sh" build-pod "$@"
53 |
54 | # Make a symlink from built framework to phony file, which will be used as input to
55 | # build script. This should force rebuild (podspec currently doesn't support alwaysOutOfDate
56 | # attribute on custom build phase)
57 | ln -fs "$OBJROOT/XCBuildData/build.db" "${BUILT_PRODUCTS_DIR}/cargokit_phony"
58 | ln -fs "${BUILT_PRODUCTS_DIR}/${EXECUTABLE_PATH}" "${BUILT_PRODUCTS_DIR}/cargokit_phony_out"
59 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/README.md:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | A sample command-line application with an entrypoint in `bin/`, library code
5 | in `lib/`, and example unit test in `test/`.
6 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | # This is copied from Cargokit (which is the official way to use it currently)
2 | # Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | # This file configures the static analysis results for your project (errors,
5 | # warnings, and lints).
6 | #
7 | # This enables the 'recommended' set of lints from `package:lints`.
8 | # This set helps identify many issues that may lead to problems when running
9 | # or consuming Dart code, and enforces writing Dart using a single, idiomatic
10 | # style and format.
11 | #
12 | # If you want a smaller set of lints you can change this to specify
13 | # 'package:lints/core.yaml'. These are just the most critical lints
14 | # (the recommended set includes the core lints).
15 | # The core lints are also what is used by pub.dev for scoring packages.
16 |
17 | include: package:lints/recommended.yaml
18 |
19 | # Uncomment the following section to specify additional rules.
20 |
21 | linter:
22 | rules:
23 | - prefer_relative_imports
24 | - directives_ordering
25 |
26 | # analyzer:
27 | # exclude:
28 | # - path/to/excluded/files/**
29 |
30 | # For more information about the core and recommended set of lints, see
31 | # https://dart.dev/go/core-lints
32 |
33 | # For additional information about configuring this file, see
34 | # https://dart.dev/guides/language/analysis-options
35 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/bin/build_tool.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'package:build_tool/build_tool.dart' as build_tool;
5 |
6 | void main(List arguments) {
7 | build_tool.runMain(arguments);
8 | }
9 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/build_tool.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'src/build_tool.dart' as build_tool;
5 |
6 | Future runMain(List args) async {
7 | return build_tool.runMain(args);
8 | }
9 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/build_cmake.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | import 'package:path/path.dart' as path;
7 |
8 | import 'artifacts_provider.dart';
9 | import 'builder.dart';
10 | import 'environment.dart';
11 | import 'options.dart';
12 | import 'target.dart';
13 |
14 | class BuildCMake {
15 | final CargokitUserOptions userOptions;
16 |
17 | BuildCMake({required this.userOptions});
18 |
19 | Future build() async {
20 | final targetPlatform = Environment.targetPlatform;
21 | final target = Target.forFlutterName(Environment.targetPlatform);
22 | if (target == null) {
23 | throw Exception("Unknown target platform: $targetPlatform");
24 | }
25 |
26 | final environment = BuildEnvironment.fromEnvironment(isAndroid: false);
27 | final provider =
28 | ArtifactProvider(environment: environment, userOptions: userOptions);
29 | final artifacts = await provider.getArtifacts([target]);
30 |
31 | final libs = artifacts[target]!;
32 |
33 | for (final lib in libs) {
34 | if (lib.type == AritifactType.dylib) {
35 | File(lib.path)
36 | .copySync(path.join(Environment.outputDir, lib.finalFileName));
37 | }
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/build_gradle.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | import 'package:logging/logging.dart';
7 | import 'package:path/path.dart' as path;
8 |
9 | import 'artifacts_provider.dart';
10 | import 'builder.dart';
11 | import 'environment.dart';
12 | import 'options.dart';
13 | import 'target.dart';
14 |
15 | final log = Logger('build_gradle');
16 |
17 | class BuildGradle {
18 | BuildGradle({required this.userOptions});
19 |
20 | final CargokitUserOptions userOptions;
21 |
22 | Future build() async {
23 | final targets = Environment.targetPlatforms.map((arch) {
24 | final target = Target.forFlutterName(arch);
25 | if (target == null) {
26 | throw Exception(
27 | "Unknown darwin target or platform: $arch, ${Environment.darwinPlatformName}");
28 | }
29 | return target;
30 | }).toList();
31 |
32 | final environment = BuildEnvironment.fromEnvironment(isAndroid: true);
33 | final provider =
34 | ArtifactProvider(environment: environment, userOptions: userOptions);
35 | final artifacts = await provider.getArtifacts(targets);
36 |
37 | for (final target in targets) {
38 | final libs = artifacts[target]!;
39 | final outputDir = path.join(Environment.outputDir, target.android!);
40 | Directory(outputDir).createSync(recursive: true);
41 |
42 | for (final lib in libs) {
43 | if (lib.type == AritifactType.dylib) {
44 | File(lib.path).copySync(path.join(outputDir, lib.finalFileName));
45 | }
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/cargo.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | import 'package:path/path.dart' as path;
7 | import 'package:toml/toml.dart';
8 |
9 | class ManifestException {
10 | ManifestException(this.message, {required this.fileName});
11 |
12 | final String? fileName;
13 | final String message;
14 |
15 | @override
16 | String toString() {
17 | if (fileName != null) {
18 | return 'Failed to parse package manifest at $fileName: $message';
19 | } else {
20 | return 'Failed to parse package manifest: $message';
21 | }
22 | }
23 | }
24 |
25 | class CrateInfo {
26 | CrateInfo({required this.packageName});
27 |
28 | final String packageName;
29 |
30 | static CrateInfo parseManifest(String manifest, {final String? fileName}) {
31 | final toml = TomlDocument.parse(manifest);
32 | final package = toml.toMap()['package'];
33 | if (package == null) {
34 | throw ManifestException('Missing package section', fileName: fileName);
35 | }
36 | final name = package['name'];
37 | if (name == null) {
38 | throw ManifestException('Missing package name', fileName: fileName);
39 | }
40 | return CrateInfo(packageName: name);
41 | }
42 |
43 | static CrateInfo load(String manifestDir) {
44 | final manifestFile = File(path.join(manifestDir, 'Cargo.toml'));
45 | final manifest = manifestFile.readAsStringSync();
46 | return parseManifest(manifest, fileName: manifestFile.path);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/environment.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | extension on String {
7 | String resolveSymlink() => File(this).resolveSymbolicLinksSync();
8 | }
9 |
10 | class Environment {
11 | /// Current build configuration (debug or release).
12 | static String get configuration =>
13 | _getEnv("CARGOKIT_CONFIGURATION").toLowerCase();
14 |
15 | static bool get isDebug => configuration == 'debug';
16 | static bool get isRelease => configuration == 'release';
17 |
18 | /// Temporary directory where Rust build artifacts are placed.
19 | static String get targetTempDir => _getEnv("CARGOKIT_TARGET_TEMP_DIR");
20 |
21 | /// Final output directory where the build artifacts are placed.
22 | static String get outputDir => _getEnvPath('CARGOKIT_OUTPUT_DIR');
23 |
24 | /// Path to the crate manifest (containing Cargo.toml).
25 | static String get manifestDir => _getEnvPath('CARGOKIT_MANIFEST_DIR');
26 |
27 | /// Directory inside root project. Not necessarily root folder. Symlinks are
28 | /// not resolved on purpose.
29 | static String get rootProjectDir => _getEnv('CARGOKIT_ROOT_PROJECT_DIR');
30 |
31 | // Pod
32 |
33 | /// Platform name (macosx, iphoneos, iphonesimulator).
34 | static String get darwinPlatformName =>
35 | _getEnv("CARGOKIT_DARWIN_PLATFORM_NAME");
36 |
37 | /// List of architectures to build for (arm64, armv7, x86_64).
38 | static List get darwinArchs =>
39 | _getEnv("CARGOKIT_DARWIN_ARCHS").split(' ');
40 |
41 | // Gradle
42 | static String get minSdkVersion => _getEnv("CARGOKIT_MIN_SDK_VERSION");
43 | static String get ndkVersion => _getEnv("CARGOKIT_NDK_VERSION");
44 | static String get sdkPath => _getEnvPath("CARGOKIT_SDK_DIR");
45 | static String get javaHome => _getEnvPath("CARGOKIT_JAVA_HOME");
46 | static List get targetPlatforms =>
47 | _getEnv("CARGOKIT_TARGET_PLATFORMS").split(',');
48 |
49 | // CMAKE
50 | static String get targetPlatform => _getEnv("CARGOKIT_TARGET_PLATFORM");
51 |
52 | static String _getEnv(String key) {
53 | final res = Platform.environment[key];
54 | if (res == null) {
55 | throw Exception("Missing environment variable $key");
56 | }
57 | return res;
58 | }
59 |
60 | static String _getEnvPath(String key) {
61 | final res = _getEnv(key);
62 | if (Directory(res).existsSync()) {
63 | return res.resolveSymlink();
64 | } else {
65 | return res;
66 | }
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/logging.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | import 'package:logging/logging.dart';
7 |
8 | const String kSeparator = "--";
9 | const String kDoubleSeparator = "==";
10 |
11 | bool _lastMessageWasSeparator = false;
12 |
13 | void _log(LogRecord rec) {
14 | final prefix = '${rec.level.name}: ';
15 | final out = rec.level == Level.SEVERE ? stderr : stdout;
16 | if (rec.message == kSeparator) {
17 | if (!_lastMessageWasSeparator) {
18 | out.write(prefix);
19 | out.writeln('-' * 80);
20 | _lastMessageWasSeparator = true;
21 | }
22 | return;
23 | } else if (rec.message == kDoubleSeparator) {
24 | out.write(prefix);
25 | out.writeln('=' * 80);
26 | _lastMessageWasSeparator = true;
27 | return;
28 | }
29 | out.write(prefix);
30 | out.writeln(rec.message);
31 | _lastMessageWasSeparator = false;
32 | }
33 |
34 | void initLogging() {
35 | Logger.root.level = Level.INFO;
36 | Logger.root.onRecord.listen((LogRecord rec) {
37 | final lines = rec.message.split('\n');
38 | for (final line in lines) {
39 | if (line.isNotEmpty || lines.length == 1 || line != lines.last) {
40 | _log(LogRecord(
41 | rec.level,
42 | line,
43 | rec.loggerName,
44 | ));
45 | }
46 | }
47 | });
48 | }
49 |
50 | void enableVerboseLogging() {
51 | Logger.root.level = Level.ALL;
52 | }
53 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/lib/src/verify_binaries.dart:
--------------------------------------------------------------------------------
1 | /// This is copied from Cargokit (which is the official way to use it currently)
2 | /// Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | import 'dart:io';
5 |
6 | import 'package:ed25519_edwards/ed25519_edwards.dart';
7 | import 'package:http/http.dart';
8 |
9 | import 'artifacts_provider.dart';
10 | import 'cargo.dart';
11 | import 'crate_hash.dart';
12 | import 'options.dart';
13 | import 'precompile_binaries.dart';
14 | import 'target.dart';
15 |
16 | class VerifyBinaries {
17 | VerifyBinaries({
18 | required this.manifestDir,
19 | });
20 |
21 | final String manifestDir;
22 |
23 | Future run() async {
24 | final crateInfo = CrateInfo.load(manifestDir);
25 |
26 | final config = CargokitCrateOptions.load(manifestDir: manifestDir);
27 | final precompiledBinaries = config.precompiledBinaries;
28 | if (precompiledBinaries == null) {
29 | stdout.writeln('Crate does not support precompiled binaries.');
30 | } else {
31 | final crateHash = CrateHash.compute(manifestDir);
32 | stdout.writeln('Crate hash: $crateHash');
33 |
34 | for (final target in Target.all) {
35 | final message = 'Checking ${target.rust}...';
36 | stdout.write(message.padRight(40));
37 | stdout.flush();
38 |
39 | final artifacts = getArtifactNames(
40 | target: target,
41 | libraryName: crateInfo.packageName,
42 | remote: true,
43 | );
44 |
45 | final prefix = precompiledBinaries.uriPrefix;
46 |
47 | bool ok = true;
48 |
49 | for (final artifact in artifacts) {
50 | final fileName = PrecompileBinaries.fileName(target, artifact);
51 | final signatureFileName =
52 | PrecompileBinaries.signatureFileName(target, artifact);
53 |
54 | final url = Uri.parse('$prefix$crateHash/$fileName');
55 | final signatureUrl =
56 | Uri.parse('$prefix$crateHash/$signatureFileName');
57 |
58 | final signature = await get(signatureUrl);
59 | if (signature.statusCode != 200) {
60 | stdout.writeln('MISSING');
61 | ok = false;
62 | break;
63 | }
64 | final asset = await get(url);
65 | if (asset.statusCode != 200) {
66 | stdout.writeln('MISSING');
67 | ok = false;
68 | break;
69 | }
70 |
71 | if (!verify(precompiledBinaries.publicKey, asset.bodyBytes,
72 | signature.bodyBytes)) {
73 | stdout.writeln('INVALID SIGNATURE');
74 | ok = false;
75 | }
76 | }
77 |
78 | if (ok) {
79 | stdout.writeln('OK');
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/build_tool/pubspec.yaml:
--------------------------------------------------------------------------------
1 | # This is copied from Cargokit (which is the official way to use it currently)
2 | # Details: https://fzyzcjy.github.io/flutter_rust_bridge/manual/integrate/builtin
3 |
4 | name: build_tool
5 | description: Cargokit build_tool. Facilitates the build of Rust crate during Flutter application build.
6 | publish_to: none
7 | version: 1.0.0
8 |
9 | environment:
10 | sdk: ">=3.0.0 <4.0.0"
11 |
12 | # Add regular dependencies here.
13 | dependencies:
14 | # these are pinned on purpose because the bundle_tool_runner doesn't have
15 | # pubspec.lock. See run_build_tool.sh
16 | logging: 1.2.0
17 | path: 1.8.0
18 | version: 3.0.0
19 | collection: 1.18.0
20 | ed25519_edwards: 0.3.1
21 | hex: 0.2.0
22 | yaml: 3.1.2
23 | source_span: 1.10.0
24 | github: 9.17.0
25 | args: 2.4.2
26 | crypto: 3.0.3
27 | convert: 3.1.1
28 | http: 1.1.0
29 | toml: 0.14.0
30 |
31 | dev_dependencies:
32 | lints: ^2.1.0
33 | test: ^1.24.0
34 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/cmake/resolve_symlinks.ps1:
--------------------------------------------------------------------------------
1 | function Resolve-Symlinks {
2 | [CmdletBinding()]
3 | [OutputType([string])]
4 | param(
5 | [Parameter(Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
6 | [string] $Path
7 | )
8 |
9 | [string] $separator = '/'
10 | [string[]] $parts = $Path.Split($separator)
11 |
12 | [string] $realPath = ''
13 | foreach ($part in $parts) {
14 | if ($realPath -and !$realPath.EndsWith($separator)) {
15 | $realPath += $separator
16 | }
17 | $realPath += $part
18 | $item = Get-Item $realPath
19 | if ($item.Target) {
20 | $realPath = $item.Target.Replace('\', '/')
21 | }
22 | }
23 | $realPath
24 | }
25 |
26 | $path=Resolve-Symlinks -Path $args[0]
27 | Write-Host $path
28 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/run_build_tool.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | setlocal
3 |
4 | setlocal ENABLEDELAYEDEXPANSION
5 |
6 | SET BASEDIR=%~dp0
7 |
8 | if not exist "%CARGOKIT_TOOL_TEMP_DIR%" (
9 | mkdir "%CARGOKIT_TOOL_TEMP_DIR%"
10 | )
11 | cd /D "%CARGOKIT_TOOL_TEMP_DIR%"
12 |
13 | SET BUILD_TOOL_PKG_DIR=%BASEDIR%build_tool
14 | SET DART=%FLUTTER_ROOT%\bin\cache\dart-sdk\bin\dart
15 |
16 | set BUILD_TOOL_PKG_DIR_POSIX=%BUILD_TOOL_PKG_DIR:\=/%
17 |
18 | (
19 | echo name: build_tool_runner
20 | echo version: 1.0.0
21 | echo publish_to: none
22 | echo.
23 | echo environment:
24 | echo sdk: '^>=3.0.0 ^<4.0.0'
25 | echo.
26 | echo dependencies:
27 | echo build_tool:
28 | echo path: %BUILD_TOOL_PKG_DIR_POSIX%
29 | ) >pubspec.yaml
30 |
31 | if not exist bin (
32 | mkdir bin
33 | )
34 |
35 | (
36 | echo import 'package:build_tool/build_tool.dart' as build_tool;
37 | echo void main^(List^ args^) ^{
38 | echo build_tool.runMain^(args^);
39 | echo ^}
40 | ) >bin\build_tool_runner.dart
41 |
42 | SET PRECOMPILED=bin\build_tool_runner.dill
43 |
44 | REM To detect changes in package we compare output of DIR /s (recursive)
45 | set PREV_PACKAGE_INFO=.dart_tool\package_info.prev
46 | set CUR_PACKAGE_INFO=.dart_tool\package_info.cur
47 |
48 | DIR "%BUILD_TOOL_PKG_DIR%" /s > "%CUR_PACKAGE_INFO%_orig"
49 |
50 | REM Last line in dir output is free space on harddrive. That is bound to
51 | REM change between invocation so we need to remove it
52 | (
53 | Set "Line="
54 | For /F "UseBackQ Delims=" %%A In ("%CUR_PACKAGE_INFO%_orig") Do (
55 | SetLocal EnableDelayedExpansion
56 | If Defined Line Echo !Line!
57 | EndLocal
58 | Set "Line=%%A")
59 | ) >"%CUR_PACKAGE_INFO%"
60 | DEL "%CUR_PACKAGE_INFO%_orig"
61 |
62 | REM Compare current directory listing with previous
63 | FC /B "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%" > nul 2>&1
64 |
65 | If %ERRORLEVEL% neq 0 (
66 | REM Changed - copy current to previous and remove precompiled kernel
67 | if exist "%PREV_PACKAGE_INFO%" (
68 | DEL "%PREV_PACKAGE_INFO%"
69 | )
70 | MOVE /Y "%CUR_PACKAGE_INFO%" "%PREV_PACKAGE_INFO%"
71 | if exist "%PRECOMPILED%" (
72 | DEL "%PRECOMPILED%"
73 | )
74 | )
75 |
76 | REM There is no CUR_PACKAGE_INFO it was renamed in previous step to %PREV_PACKAGE_INFO%
77 | REM which means we need to do pub get and precompile
78 | if not exist "%PRECOMPILED%" (
79 | echo Running pub get in "%cd%"
80 | "%DART%" pub get --no-precompile
81 | "%DART%" compile kernel bin/build_tool_runner.dart
82 | )
83 |
84 | "%DART%" "%PRECOMPILED%" %*
85 |
86 | REM 253 means invalid snapshot version.
87 | If %ERRORLEVEL% equ 253 (
88 | "%DART%" pub get --no-precompile
89 | "%DART%" compile kernel bin/build_tool_runner.dart
90 | "%DART%" "%PRECOMPILED%" %*
91 | )
92 |
--------------------------------------------------------------------------------
/rust_builder/cargokit/run_build_tool.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | BASEDIR=$(dirname "$0")
6 |
7 | mkdir -p "$CARGOKIT_TOOL_TEMP_DIR"
8 |
9 | cd "$CARGOKIT_TOOL_TEMP_DIR"
10 |
11 | # Write a very simple bin package in temp folder that depends on build_tool package
12 | # from Cargokit. This is done to ensure that we don't pollute Cargokit folder
13 | # with .dart_tool contents.
14 |
15 | BUILD_TOOL_PKG_DIR="$BASEDIR/build_tool"
16 |
17 | if [[ -z $FLUTTER_ROOT ]]; then # not defined
18 | DART=dart
19 | else
20 | DART="$FLUTTER_ROOT/bin/cache/dart-sdk/bin/dart"
21 | fi
22 |
23 | cat << EOF > "pubspec.yaml"
24 | name: build_tool_runner
25 | version: 1.0.0
26 | publish_to: none
27 |
28 | environment:
29 | sdk: '>=3.0.0 <4.0.0'
30 |
31 | dependencies:
32 | build_tool:
33 | path: "$BUILD_TOOL_PKG_DIR"
34 | EOF
35 |
36 | mkdir -p "bin"
37 |
38 | cat << EOF > "bin/build_tool_runner.dart"
39 | import 'package:build_tool/build_tool.dart' as build_tool;
40 | void main(List args) {
41 | build_tool.runMain(args);
42 | }
43 | EOF
44 |
45 | # Create alias for `shasum` if it does not exist and `sha1sum` exists
46 | if ! [ -x "$(command -v shasum)" ] && [ -x "$(command -v sha1sum)" ]; then
47 | shopt -s expand_aliases
48 | alias shasum="sha1sum"
49 | fi
50 |
51 | # Dart run will not cache any package that has a path dependency, which
52 | # is the case for our build_tool_runner. So instead we precompile the package
53 | # ourselves.
54 | # To invalidate the cached kernel we use the hash of ls -LR of the build_tool
55 | # package directory. This should be good enough, as the build_tool package
56 | # itself is not meant to have any path dependencies.
57 |
58 | if [[ "$OSTYPE" == "darwin"* ]]; then
59 | PACKAGE_HASH=$(ls -lTR "$BUILD_TOOL_PKG_DIR" | shasum)
60 | else
61 | PACKAGE_HASH=$(ls -lR --full-time "$BUILD_TOOL_PKG_DIR" | shasum)
62 | fi
63 |
64 | PACKAGE_HASH_FILE=".package_hash"
65 |
66 | if [ -f "$PACKAGE_HASH_FILE" ]; then
67 | EXISTING_HASH=$(cat "$PACKAGE_HASH_FILE")
68 | if [ "$PACKAGE_HASH" != "$EXISTING_HASH" ]; then
69 | rm "$PACKAGE_HASH_FILE"
70 | fi
71 | fi
72 |
73 | # Run pub get if needed.
74 | if [ ! -f "$PACKAGE_HASH_FILE" ]; then
75 | "$DART" pub get --no-precompile
76 | "$DART" compile kernel bin/build_tool_runner.dart
77 | echo "$PACKAGE_HASH" > "$PACKAGE_HASH_FILE"
78 | fi
79 |
80 | set +e
81 |
82 | "$DART" bin/build_tool_runner.dill "$@"
83 |
84 | exit_code=$?
85 |
86 | # 253 means invalid snapshot version.
87 | if [ $exit_code == 253 ]; then
88 | "$DART" pub get --no-precompile
89 | "$DART" compile kernel bin/build_tool_runner.dart
90 | "$DART" bin/build_tool_runner.dill "$@"
91 | exit_code=$?
92 | fi
93 |
94 | exit $exit_code
95 |
--------------------------------------------------------------------------------
/rust_builder/ios/Classes/dummy_file.c:
--------------------------------------------------------------------------------
1 | // This is an empty file to force CocoaPods to create a framework.
2 |
--------------------------------------------------------------------------------
/rust_builder/ios/rust_lib_kobi.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint rust_lib_kobi.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'rust_lib_kobi'
7 | s.version = '0.0.1'
8 | s.summary = 'A new Flutter FFI plugin project.'
9 | s.description = <<-DESC
10 | A new Flutter FFI plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 |
16 | # This will ensure the source files in Classes/ are included in the native
17 | # builds of apps using this FFI plugin. Podspec does not support relative
18 | # paths, so Classes contains a forwarder C file that relatively imports
19 | # `../src/*` so that the C sources can be shared among all target platforms.
20 | s.source = { :path => '.' }
21 | s.source_files = 'Classes/**/*'
22 | s.dependency 'Flutter'
23 | s.platform = :ios, '11.0'
24 |
25 | # Flutter.framework does not contain a i386 slice.
26 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
27 | s.swift_version = '5.0'
28 |
29 | s.script_phase = {
30 | :name => 'Build Rust library',
31 | # First argument is relative path to the `rust` folder, second is name of rust library
32 | :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_kobi',
33 | :execution_position => :before_compile,
34 | :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'],
35 | # Let XCode know that the static library referenced in -force_load below is
36 | # created by this build step.
37 | :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_kobi.a"],
38 | }
39 | s.pod_target_xcconfig = {
40 | 'DEFINES_MODULE' => 'YES',
41 | # Flutter.framework does not contain a i386 slice.
42 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
43 | 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_kobi.a',
44 | }
45 | end
--------------------------------------------------------------------------------
/rust_builder/linux/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have CMake 3.10 or later
2 | # installed. You should not increase this version, as doing so will cause
3 | # the plugin to fail to compile for some customers of the plugin.
4 | cmake_minimum_required(VERSION 3.10)
5 |
6 | # Project-level configuration.
7 | set(PROJECT_NAME "rust_lib_kobi")
8 | project(${PROJECT_NAME} LANGUAGES CXX)
9 |
10 | include("../cargokit/cmake/cargokit.cmake")
11 | apply_cargokit(${PROJECT_NAME} ../../rust rust_lib_kobi "")
12 |
13 | # List of absolute paths to libraries that should be bundled with the plugin.
14 | # This list could contain prebuilt libraries, or libraries created by an
15 | # external build triggered from this build file.
16 | set(rust_lib_kobi_bundled_libraries
17 | "${${PROJECT_NAME}_cargokit_lib}"
18 | PARENT_SCOPE
19 | )
20 |
--------------------------------------------------------------------------------
/rust_builder/macos/Classes/dummy_file.c:
--------------------------------------------------------------------------------
1 | // This is an empty file to force CocoaPods to create a framework.
2 |
--------------------------------------------------------------------------------
/rust_builder/macos/rust_lib_kobi.podspec:
--------------------------------------------------------------------------------
1 | #
2 | # To learn more about a Podspec see http://guides.cocoapods.org/syntax/podspec.html.
3 | # Run `pod lib lint rust_lib_kobi.podspec` to validate before publishing.
4 | #
5 | Pod::Spec.new do |s|
6 | s.name = 'rust_lib_kobi'
7 | s.version = '0.0.1'
8 | s.summary = 'A new Flutter FFI plugin project.'
9 | s.description = <<-DESC
10 | A new Flutter FFI plugin project.
11 | DESC
12 | s.homepage = 'http://example.com'
13 | s.license = { :file => '../LICENSE' }
14 | s.author = { 'Your Company' => 'email@example.com' }
15 |
16 | # This will ensure the source files in Classes/ are included in the native
17 | # builds of apps using this FFI plugin. Podspec does not support relative
18 | # paths, so Classes contains a forwarder C file that relatively imports
19 | # `../src/*` so that the C sources can be shared among all target platforms.
20 | s.source = { :path => '.' }
21 | s.source_files = 'Classes/**/*'
22 | s.dependency 'FlutterMacOS'
23 |
24 | s.platform = :osx, '10.11'
25 | s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' }
26 | s.swift_version = '5.0'
27 |
28 | s.script_phase = {
29 | :name => 'Build Rust library',
30 | # First argument is relative path to the `rust` folder, second is name of rust library
31 | :script => 'sh "$PODS_TARGET_SRCROOT/../cargokit/build_pod.sh" ../../rust rust_lib_kobi',
32 | :execution_position => :before_compile,
33 | :input_files => ['${BUILT_PRODUCTS_DIR}/cargokit_phony'],
34 | # Let XCode know that the static library referenced in -force_load below is
35 | # created by this build step.
36 | :output_files => ["${BUILT_PRODUCTS_DIR}/librust_lib_kobi.a"],
37 | }
38 | s.pod_target_xcconfig = {
39 | 'DEFINES_MODULE' => 'YES',
40 | # Flutter.framework does not contain a i386 slice.
41 | 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386',
42 | 'OTHER_LDFLAGS' => '-force_load ${BUILT_PRODUCTS_DIR}/librust_lib_kobi.a',
43 | }
44 | end
--------------------------------------------------------------------------------
/rust_builder/pubspec.yaml:
--------------------------------------------------------------------------------
1 | name: rust_lib_kobi
2 | description: "Utility to build Rust code"
3 | version: 0.0.1
4 | publish_to: none
5 |
6 | environment:
7 | sdk: '>=3.3.0 <4.0.0'
8 | flutter: '>=3.3.0'
9 |
10 | dependencies:
11 | flutter:
12 | sdk: flutter
13 | plugin_platform_interface: ^2.0.2
14 |
15 | dev_dependencies:
16 | ffi: ^2.0.2
17 | ffigen: ^11.0.0
18 | flutter_test:
19 | sdk: flutter
20 | flutter_lints: ^2.0.0
21 |
22 | flutter:
23 | plugin:
24 | platforms:
25 | android:
26 | ffiPlugin: true
27 | ios:
28 | ffiPlugin: true
29 | linux:
30 | ffiPlugin: true
31 | macos:
32 | ffiPlugin: true
33 | windows:
34 | ffiPlugin: true
35 |
--------------------------------------------------------------------------------
/rust_builder/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/rust_builder/windows/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # The Flutter tooling requires that developers have a version of Visual Studio
2 | # installed that includes CMake 3.14 or later. You should not increase this
3 | # version, as doing so will cause the plugin to fail to compile for some
4 | # customers of the plugin.
5 | cmake_minimum_required(VERSION 3.14)
6 |
7 | # Project-level configuration.
8 | set(PROJECT_NAME "rust_lib_kobi")
9 | project(${PROJECT_NAME} LANGUAGES CXX)
10 |
11 | include("../cargokit/cmake/cargokit.cmake")
12 | apply_cargokit(${PROJECT_NAME} ../../../../../../rust rust_lib_kobi "")
13 |
14 | # List of absolute paths to libraries that should be bundled with the plugin.
15 | # This list could contain prebuilt libraries, or libraries created by an
16 | # external build triggered from this build file.
17 | set(rust_lib_kobi_bundled_libraries
18 | "${${PROJECT_NAME}_cargokit_lib}"
19 | PARENT_SCOPE
20 | )
21 |
--------------------------------------------------------------------------------
/scripts/thin-payload.sh:
--------------------------------------------------------------------------------
1 | # 精简Payload文件夹 (上传到AppStore会自动区分平台, 此代码仅用于构建非签名ipa)
2 |
3 | foreachThin(){
4 | for file in $1/*
5 | do
6 | if test -f $file
7 | then
8 | mime=$(file --mime-type -b $file)
9 | if [ "$mime" == 'application/x-mach-binary' ] || [ "${file##*.}"x = "dylib"x ]
10 | then
11 | echo thin $file
12 | xcrun -sdk iphoneos lipo "$file" -thin arm64 -output "$file"
13 | xcrun -sdk iphoneos bitcode_strip "$file" -r -o "$file"
14 | strip -S -x "$file" -o "$file"
15 | fi
16 | fi
17 | if test -d $file
18 | then
19 | foreachThin $file
20 | fi
21 | done
22 | }
23 |
24 | foreachThin ./Payload
25 |
--------------------------------------------------------------------------------
/test_driver/integration_test.dart:
--------------------------------------------------------------------------------
1 | import 'package:integration_test/integration_test_driver.dart';
2 |
3 | Future main() => integrationDriver();
4 |
--------------------------------------------------------------------------------
/web/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/web/favicon.png
--------------------------------------------------------------------------------
/web/icons/Icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/web/icons/Icon-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/web/icons/Icon-512.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/web/icons/Icon-maskable-192.png
--------------------------------------------------------------------------------
/web/icons/Icon-maskable-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/web/icons/Icon-maskable-512.png
--------------------------------------------------------------------------------
/web/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | kobi
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/web/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kobi",
3 | "short_name": "kobi",
4 | "start_url": ".",
5 | "display": "standalone",
6 | "background_color": "#0175C2",
7 | "theme_color": "#0175C2",
8 | "description": "A new Flutter project.",
9 | "orientation": "portrait-primary",
10 | "prefer_related_applications": false,
11 | "icons": [
12 | {
13 | "src": "icons/Icon-192.png",
14 | "sizes": "192x192",
15 | "type": "image/png"
16 | },
17 | {
18 | "src": "icons/Icon-512.png",
19 | "sizes": "512x512",
20 | "type": "image/png"
21 | },
22 | {
23 | "src": "icons/Icon-maskable-192.png",
24 | "sizes": "192x192",
25 | "type": "image/png",
26 | "purpose": "maskable"
27 | },
28 | {
29 | "src": "icons/Icon-maskable-512.png",
30 | "sizes": "512x512",
31 | "type": "image/png",
32 | "purpose": "maskable"
33 | }
34 | ]
35 | }
36 |
--------------------------------------------------------------------------------
/windows/.gitignore:
--------------------------------------------------------------------------------
1 | flutter/ephemeral/
2 |
3 | # Visual Studio user-specific files.
4 | *.suo
5 | *.user
6 | *.userosscache
7 | *.sln.docstates
8 |
9 | # Visual Studio build-related files.
10 | x64/
11 | x86/
12 |
13 | # Visual Studio cache files
14 | # files ending in .cache can be ignored
15 | *.[Cc]ache
16 | # but keep track of directories ending in .cache
17 | !*.[Cc]ache/
18 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.cc:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #include "generated_plugin_registrant.h"
8 |
9 | #include
10 | #include
11 |
12 | void RegisterPlugins(flutter::PluginRegistry* registry) {
13 | PermissionHandlerWindowsPluginRegisterWithRegistrar(
14 | registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
15 | UrlLauncherWindowsRegisterWithRegistrar(
16 | registry->GetRegistrarForPlugin("UrlLauncherWindows"));
17 | }
18 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugin_registrant.h:
--------------------------------------------------------------------------------
1 | //
2 | // Generated file. Do not edit.
3 | //
4 |
5 | // clang-format off
6 |
7 | #ifndef GENERATED_PLUGIN_REGISTRANT_
8 | #define GENERATED_PLUGIN_REGISTRANT_
9 |
10 | #include
11 |
12 | // Registers Flutter plugins.
13 | void RegisterPlugins(flutter::PluginRegistry* registry);
14 |
15 | #endif // GENERATED_PLUGIN_REGISTRANT_
16 |
--------------------------------------------------------------------------------
/windows/flutter/generated_plugins.cmake:
--------------------------------------------------------------------------------
1 | #
2 | # Generated file, do not edit.
3 | #
4 |
5 | list(APPEND FLUTTER_PLUGIN_LIST
6 | permission_handler_windows
7 | url_launcher_windows
8 | )
9 |
10 | list(APPEND FLUTTER_FFI_PLUGIN_LIST
11 | rust_lib_kobi
12 | )
13 |
14 | set(PLUGIN_BUNDLED_LIBRARIES)
15 |
16 | foreach(plugin ${FLUTTER_PLUGIN_LIST})
17 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin})
18 | target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin)
19 | list(APPEND PLUGIN_BUNDLED_LIBRARIES $)
20 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries})
21 | endforeach(plugin)
22 |
23 | foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST})
24 | add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin})
25 | list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries})
26 | endforeach(ffi_plugin)
27 |
--------------------------------------------------------------------------------
/windows/runner/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.14)
2 | project(runner LANGUAGES CXX)
3 |
4 | # Define the application target. To change its name, change BINARY_NAME in the
5 | # top-level CMakeLists.txt, not the value here, or `flutter run` will no longer
6 | # work.
7 | #
8 | # Any new source files that you add to the application should be added here.
9 | add_executable(${BINARY_NAME} WIN32
10 | "flutter_window.cpp"
11 | "main.cpp"
12 | "utils.cpp"
13 | "win32_window.cpp"
14 | "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
15 | "Runner.rc"
16 | "runner.exe.manifest"
17 | )
18 |
19 | # Apply the standard set of build settings. This can be removed for applications
20 | # that need different build settings.
21 | apply_standard_settings(${BINARY_NAME})
22 |
23 | # Add preprocessor definitions for the build version.
24 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"")
25 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}")
26 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}")
27 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}")
28 | target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}")
29 |
30 | # Disable Windows macros that collide with C++ standard library functions.
31 | target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX")
32 |
33 | # Add dependency libraries and include directories. Add any application-specific
34 | # dependencies here.
35 | target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app)
36 | target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib")
37 | target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}")
38 |
39 | # Run the Flutter tool portions of the build. This must not be removed.
40 | add_dependencies(${BINARY_NAME} flutter_assemble)
41 |
--------------------------------------------------------------------------------
/windows/runner/flutter_window.cpp:
--------------------------------------------------------------------------------
1 | #include "flutter_window.h"
2 |
3 | #include
4 |
5 | #include "flutter/generated_plugin_registrant.h"
6 |
7 | FlutterWindow::FlutterWindow(const flutter::DartProject& project)
8 | : project_(project) {}
9 |
10 | FlutterWindow::~FlutterWindow() {}
11 |
12 | bool FlutterWindow::OnCreate() {
13 | if (!Win32Window::OnCreate()) {
14 | return false;
15 | }
16 |
17 | RECT frame = GetClientArea();
18 |
19 | // The size here must match the window dimensions to avoid unnecessary surface
20 | // creation / destruction in the startup path.
21 | flutter_controller_ = std::make_unique(
22 | frame.right - frame.left, frame.bottom - frame.top, project_);
23 | // Ensure that basic setup of the controller was successful.
24 | if (!flutter_controller_->engine() || !flutter_controller_->view()) {
25 | return false;
26 | }
27 | RegisterPlugins(flutter_controller_->engine());
28 | SetChildContent(flutter_controller_->view()->GetNativeWindow());
29 |
30 | flutter_controller_->engine()->SetNextFrameCallback([&]() {
31 | this->Show();
32 | });
33 |
34 | // Flutter can complete the first frame before the "show window" callback is
35 | // registered. The following call ensures a frame is pending to ensure the
36 | // window is shown. It is a no-op if the first frame hasn't completed yet.
37 | flutter_controller_->ForceRedraw();
38 |
39 | return true;
40 | }
41 |
42 | void FlutterWindow::OnDestroy() {
43 | if (flutter_controller_) {
44 | flutter_controller_ = nullptr;
45 | }
46 |
47 | Win32Window::OnDestroy();
48 | }
49 |
50 | LRESULT
51 | FlutterWindow::MessageHandler(HWND hwnd, UINT const message,
52 | WPARAM const wparam,
53 | LPARAM const lparam) noexcept {
54 | // Give Flutter, including plugins, an opportunity to handle window messages.
55 | if (flutter_controller_) {
56 | std::optional result =
57 | flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam,
58 | lparam);
59 | if (result) {
60 | return *result;
61 | }
62 | }
63 |
64 | switch (message) {
65 | case WM_FONTCHANGE:
66 | flutter_controller_->engine()->ReloadSystemFonts();
67 | break;
68 | }
69 |
70 | return Win32Window::MessageHandler(hwnd, message, wparam, lparam);
71 | }
72 |
--------------------------------------------------------------------------------
/windows/runner/flutter_window.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_FLUTTER_WINDOW_H_
2 | #define RUNNER_FLUTTER_WINDOW_H_
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 | #include "win32_window.h"
10 |
11 | // A window that does nothing but host a Flutter view.
12 | class FlutterWindow : public Win32Window {
13 | public:
14 | // Creates a new FlutterWindow hosting a Flutter view running |project|.
15 | explicit FlutterWindow(const flutter::DartProject& project);
16 | virtual ~FlutterWindow();
17 |
18 | protected:
19 | // Win32Window:
20 | bool OnCreate() override;
21 | void OnDestroy() override;
22 | LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam,
23 | LPARAM const lparam) noexcept override;
24 |
25 | private:
26 | // The project to run.
27 | flutter::DartProject project_;
28 |
29 | // The Flutter instance hosted by this window.
30 | std::unique_ptr flutter_controller_;
31 | };
32 |
33 | #endif // RUNNER_FLUTTER_WINDOW_H_
34 |
--------------------------------------------------------------------------------
/windows/runner/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | #include "flutter_window.h"
6 | #include "utils.h"
7 |
8 | int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
9 | _In_ wchar_t *command_line, _In_ int show_command) {
10 | // Attach to console when present (e.g., 'flutter run') or create a
11 | // new console when running with a debugger.
12 | if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) {
13 | CreateAndAttachConsole();
14 | }
15 |
16 | // Initialize COM, so that it is available for use in the library and/or
17 | // plugins.
18 | ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
19 |
20 | flutter::DartProject project(L"data");
21 |
22 | std::vector command_line_arguments =
23 | GetCommandLineArguments();
24 |
25 | project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
26 |
27 | FlutterWindow window(project);
28 | Win32Window::Point origin(10, 10);
29 | Win32Window::Size size(1280, 720);
30 | if (!window.Create(L"kobi", origin, size)) {
31 | return EXIT_FAILURE;
32 | }
33 | window.SetQuitOnClose(true);
34 |
35 | ::MSG msg;
36 | while (::GetMessage(&msg, nullptr, 0, 0)) {
37 | ::TranslateMessage(&msg);
38 | ::DispatchMessage(&msg);
39 | }
40 |
41 | ::CoUninitialize();
42 | return EXIT_SUCCESS;
43 | }
44 |
--------------------------------------------------------------------------------
/windows/runner/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by Runner.rc
4 | //
5 | #define IDI_APP_ICON 101
6 |
7 | // Next default values for new objects
8 | //
9 | #ifdef APSTUDIO_INVOKED
10 | #ifndef APSTUDIO_READONLY_SYMBOLS
11 | #define _APS_NEXT_RESOURCE_VALUE 102
12 | #define _APS_NEXT_COMMAND_VALUE 40001
13 | #define _APS_NEXT_CONTROL_VALUE 1001
14 | #define _APS_NEXT_SYMED_VALUE 101
15 | #endif
16 | #endif
17 |
--------------------------------------------------------------------------------
/windows/runner/resources/app_icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/niuhuan/kobi/3954a3bc1825c4707d79d55711c1080723912042/windows/runner/resources/app_icon.ico
--------------------------------------------------------------------------------
/windows/runner/runner.exe.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | PerMonitorV2
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/windows/runner/utils.cpp:
--------------------------------------------------------------------------------
1 | #include "utils.h"
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 |
10 | void CreateAndAttachConsole() {
11 | if (::AllocConsole()) {
12 | FILE *unused;
13 | if (freopen_s(&unused, "CONOUT$", "w", stdout)) {
14 | _dup2(_fileno(stdout), 1);
15 | }
16 | if (freopen_s(&unused, "CONOUT$", "w", stderr)) {
17 | _dup2(_fileno(stdout), 2);
18 | }
19 | std::ios::sync_with_stdio();
20 | FlutterDesktopResyncOutputStreams();
21 | }
22 | }
23 |
24 | std::vector GetCommandLineArguments() {
25 | // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use.
26 | int argc;
27 | wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);
28 | if (argv == nullptr) {
29 | return std::vector();
30 | }
31 |
32 | std::vector command_line_arguments;
33 |
34 | // Skip the first argument as it's the binary name.
35 | for (int i = 1; i < argc; i++) {
36 | command_line_arguments.push_back(Utf8FromUtf16(argv[i]));
37 | }
38 |
39 | ::LocalFree(argv);
40 |
41 | return command_line_arguments;
42 | }
43 |
44 | std::string Utf8FromUtf16(const wchar_t* utf16_string) {
45 | if (utf16_string == nullptr) {
46 | return std::string();
47 | }
48 | unsigned int target_length = ::WideCharToMultiByte(
49 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
50 | -1, nullptr, 0, nullptr, nullptr)
51 | -1; // remove the trailing null character
52 | int input_length = (int)wcslen(utf16_string);
53 | std::string utf8_string;
54 | if (target_length == 0 || target_length > utf8_string.max_size()) {
55 | return utf8_string;
56 | }
57 | utf8_string.resize(target_length);
58 | int converted_length = ::WideCharToMultiByte(
59 | CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string,
60 | input_length, utf8_string.data(), target_length, nullptr, nullptr);
61 | if (converted_length == 0) {
62 | return std::string();
63 | }
64 | return utf8_string;
65 | }
66 |
--------------------------------------------------------------------------------
/windows/runner/utils.h:
--------------------------------------------------------------------------------
1 | #ifndef RUNNER_UTILS_H_
2 | #define RUNNER_UTILS_H_
3 |
4 | #include
5 | #include
6 |
7 | // Creates a console for the process, and redirects stdout and stderr to
8 | // it for both the runner and the Flutter library.
9 | void CreateAndAttachConsole();
10 |
11 | // Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string
12 | // encoded in UTF-8. Returns an empty std::string on failure.
13 | std::string Utf8FromUtf16(const wchar_t* utf16_string);
14 |
15 | // Gets the command line arguments passed in as a std::vector,
16 | // encoded in UTF-8. Returns an empty std::vector on failure.
17 | std::vector GetCommandLineArguments();
18 |
19 | #endif // RUNNER_UTILS_H_
20 |
--------------------------------------------------------------------------------