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

[WIP] Add Dart support #4627

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions mediapipe/dart/dart_builder/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# https://dart.dev/guides/libraries/private-files
# Created by `dart pub`
.dart_tool/
cc/*
3 changes: 3 additions & 0 deletions mediapipe/dart/dart_builder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## 1.0.0

- Initial version.
2 changes: 2 additions & 0 deletions mediapipe/dart/dart_builder/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
A sample command-line application with an entrypoint in `bin/`, library code
in `lib/`, and example unit test in `test/`.
30 changes: 30 additions & 0 deletions mediapipe/dart/dart_builder/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.

include: package:lints/recommended.yaml

# Uncomment the following section to specify additional rules.

# linter:
# rules:
# - camel_case_types

# analyzer:
# exclude:
# - path/to/excluded/files/**

# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints

# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options
36 changes: 36 additions & 0 deletions mediapipe/dart/dart_builder/bin/cpp_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2019, 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:ffi' as ffi;
import 'dart:io' show Platform, Directory;

import 'package:path/path.dart' as path;

// FFI signature of the hello_world C function
typedef IncrementFunc = ffi.Int32 Function(ffi.Int32);
typedef Increment = int Function(int);

void main() {
// Open the dynamic library
var libraryPath =
path.join(Directory.current.absolute.path, 'cpp', 'main.dylib');

// if (Platform.isMacOS) {
// libraryPath =
// path.join(Directory.current.path, 'hello_library', 'libhello.dylib');
// }

// if (Platform.isWindows) {
// libraryPath = path.join(
// Directory.current.path, 'hello_library', 'Debug', 'hello.dll');
// }

final dylib = ffi.DynamicLibrary.open(libraryPath);

// Look up the C function 'hello_world'
final Increment increment =
dylib.lookup<ffi.NativeFunction<IncrementFunc>>('increment').asFunction();
// Call the function
print(increment(99));
}
26 changes: 26 additions & 0 deletions mediapipe/dart/dart_builder/bin/dart_builder.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import 'package:args/args.dart';
import 'package:dart_builder/dart_builder.dart' as db;

final argParser = ArgParser()
..addOption(
'protoc',
help: 'Override the path to protoc',
)
..addOption(
'protobuf',
help: 'Supply a path to google/protobuf if it is not '
'next to google/mediapipe',
)
..addOption('output', abbr: 'o');

Future<void> main(List<String> arguments) async {
final results = argParser.parse(arguments);
final options = db.DartProtoBuilderOptions(
protocPath: results['protoc'],
protobufPath: results['protobuf'],
outputPath: results['output'],
);

final protoBuilder = db.DartProtoBuilder(options);
await protoBuilder.run();
}
108 changes: 108 additions & 0 deletions mediapipe/dart/dart_builder/lib/commands.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'dart:io' as io;
import 'package:io/ansi.dart' as ansi;

class Command {
Command(
this.arguments, {
this.stdOutHandler,
this.stdErrHandler,
this.workingDirectory,
bool? debug,
}) : assert(arguments.isNotEmpty),
_debug = debug ?? false;

final bool _debug;
final String? workingDirectory;
final List<String> arguments;
void Function(String)? stdOutHandler;
void Function(String)? stdErrHandler;

io.ProcessResult? _result;

/// Runs a command and scans its stdout contents for a given needle.
/// If the needle is found, the command is considered to have completed
/// successfully.
factory Command.needleInOutput(
List<String> arguments, {
required String needle,
List<String> ifMissing = const <String>[],
bool shouldExitIfMissing = true,
}) {
return Command(
arguments,
stdOutHandler: (String output) {
bool foundNeedle = false;
bool contains(String line) => line.contains(needle);
if (output.split('\n').any(contains)) {
foundNeedle = true;
}
if (!foundNeedle) {
for (String line in ifMissing) {
io.stderr.writeln(ansi.wrapWith(line, [ansi.red]));
}
if (shouldExitIfMissing) {
io.exit(1);
}
}
},
);
}

factory Command.which(
String commandName, {
String? documentationUrl,
bool shouldExitIfMissing = true,
}) {
return Command(
['which', commandName],
stdOutHandler: (String output) {
if (output.isEmpty) {
io.stderr.writeAll([
ansi.wrapWith(
'$commandName not installed or not on path\n',
[ansi.red],
),
if (documentationUrl != null)
ansi.wrapWith(
'Visit $documentationUrl for installation instructions\n',
[ansi.red],
),
]);
if (shouldExitIfMissing) {
io.exit(1);
}
}
},
);
}

factory Command.run(
List<String> command, {
bool? debug,
String? workingDirectory,
}) =>
Command(
command,
stdOutHandler: (String output) =>
output.trim().isNotEmpty ? io.stdout.writeln(output.trim()) : null,
stdErrHandler: (String output) =>
output.trim().isNotEmpty ? io.stderr.writeln(output.trim()) : null,
debug: debug,
workingDirectory: workingDirectory,
);

Future<void> run() async {
if (_debug) {
io.stdout.writeln('>>> ${arguments.join(' ')}');
}
_result = await io.Process.run(
arguments.first,
arguments.sublist(1),
workingDirectory: workingDirectory,
);
stdOutHandler?.call(_result!.stdout);
stdErrHandler?.call(_result!.stderr);
}

int? get exitCode => _result?.exitCode;
}