blob: c16d47ff122f6c238807a4860ea17ff909829793 [file] [log] [blame]
// Copyright (c) 2020, 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:convert' show jsonDecode;
import 'dart:io' show File, Directory;
import 'package:logging/logging.dart';
import 'package:yaml/yaml.dart';
final _logger = Logger('ffigen.find_resource');
/// Find the `.dart_tool/` folder, returns `null` if unable to find it.
Uri? findDotDartTool() {
// HACK: Because 'dart:isolate' is unavailable in Flutter we have no means
// by which we can find the location of the package_config.json file.
// Which we need, because the binary library created by:
// flutter pub run ffigen:setup
// is located relative to this path. As a workaround we use
// `Platform.script` and traverse level-up until we find a
// `.dart_tool/package_config.json` file.
// Find script directory
var root = Directory.current.uri;
// Traverse up until we see a `.dart_tool/package_config.json` file.
do {
if (File.fromUri(root.resolve('.dart_tool/package_config.json'))
.existsSync()) {
return root.resolve('.dart_tool/');
}
} while (root != (root = root.resolve('..')));
return null;
}
/// Get [Uri] for [posixPath] inside ffigen's rootUri.
Uri? _findInPackageRoot(String posixPath) {
var root = Directory.current.uri;
// Traverse up until we see a `.dart_tool/package_config.json` file.
do {
final file = File.fromUri(root.resolve('.dart_tool/package_config.json'));
if (file.existsSync()) {
/// Read the package_config.json file to extract path of wrapper.
try {
final packageMap =
jsonDecode(file.readAsStringSync()) as Map<String, dynamic>;
if (packageMap['configVersion'] == 2) {
var ffigenRootUriString = ((packageMap['packages'] as List<dynamic>)
.cast<Map<String, dynamic>>()
.firstWhere(
(element) => element['name'] == 'ffigen')['rootUri']
as String);
ffigenRootUriString = ffigenRootUriString.endsWith('/')
? ffigenRootUriString
: ffigenRootUriString + '/';
/// [ffigenRootUri] can be relative to .dart_tool if its from
/// filesystem so we need to resolve it from .dart_tool first.
return file.parent.uri
.resolve(ffigenRootUriString)
.resolve(posixPath);
}
} catch (e, s) {
print(s);
throw Exception('Cannot resolve package:ffigen\'s rootUri.');
}
}
} while (root != (root = root.resolve('..')));
return null;
}
Uri? findWrapper(String wrapperName) {
return _findInPackageRoot('lib/src/clang_library/$wrapperName');
}
Uri? _findFfigenPubspecYaml() {
return _findInPackageRoot('pubspec.yaml');
}
String? _ffigenVersion;
/// Gets ffigen version from ffigen's pubspec.yaml
String? get ffigenVersion {
if (_ffigenVersion == null) {
try {
final yaml =
loadYaml(File.fromUri(_findFfigenPubspecYaml()!).readAsStringSync())
as YamlMap;
final rawVersion = yaml['version'] as String;
// Sanitize name to be used as a file name.
_ffigenVersion =
'v_${rawVersion.replaceAll('.', '_').replaceAll('+', '_')}';
} catch (e) {
_logger.severe('Unable to extract ffigen version.');
}
}
return _ffigenVersion;
}