blob: b605d9d55fe3dd1f336fe8c4135f487b13f30944 [file] [log] [blame]
// Copyright 2020 The Flutter Authors. 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:async';
import 'dart:io';
import 'dart:isolate';
import 'package:path/path.dart' as path;
import 'package:pigeon/pigeon_lib.dart';
/// This creates a relative path from `from` to `input`, the output being a
/// posix path on all platforms.
String _posixRelative(String input, {String from}) {
final path.Context context = path.Context(style: path.Style.posix);
final String rawInputPath = input;
final String absInputPath = File(rawInputPath).absolute.path;
// By going through URI's we can make sure paths can go between drives in
// Windows.
final Uri inputUri = path.toUri(absInputPath);
final String posixAbsInputPath = context.fromUri(inputUri);
final Uri tempUri = path.toUri(from);
final String posixTempPath = context.fromUri(tempUri);
return context.relative(posixAbsInputPath, from: posixTempPath);
}
/// This is the main entrypoint for the command-line tool. [args] are the
/// commmand line arguments and there is an optional [packageConfig] to
/// accomodate users that want to integrate pigeon with other build systems.
Future<void> runCommandLine(List<String> args, {Uri packageConfig}) async {
final PigeonOptions opts = Pigeon.parseArgs(args);
final Directory tempDir = Directory.systemTemp.createTempSync(
'flutter_pigeon.',
);
String importLine = '';
if (opts.input != null) {
final String relInputPath = _posixRelative(opts.input, from: tempDir.path);
importLine = 'import \'$relInputPath\';\n';
}
final String code = """
// @dart = 2.2
$importLine
import 'dart:io';
import 'dart:isolate';
import 'package:pigeon/pigeon_lib.dart';
void main(List<String> args, SendPort sendPort) async {
sendPort.send(await Pigeon.run(args));
}
""";
final File tempFile = File(path.join(tempDir.path, '_pigeon_temp_.dart'));
await tempFile.writeAsString(code);
final ReceivePort receivePort = ReceivePort();
Isolate.spawnUri(
// Using Uri.file instead of Uri.parse in order to parse backslashes as
// path segment separator with Windows semantics.
Uri.file(tempFile.path),
args,
receivePort.sendPort,
packageConfig: packageConfig,
);
final Completer<int> completer = Completer<int>();
receivePort.listen((dynamic message) {
try {
// ignore: avoid_as
completer.complete(message as int);
} catch (exception) {
completer.completeError(exception);
}
});
final int exitCode = await completer.future;
tempDir.deleteSync(recursive: true);
exit(exitCode);
}