blob: 31edfc54f1744da79b1854a9564a94995ca8df3f [file] [log] [blame]
// Copyright (c) 2023, 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:logging/logging.dart';
import 'package:native_assets_cli/native_assets_cli.dart';
import '../tool/tool.dart';
import '../tool/tool_instance.dart';
import '../tool/tool_resolver.dart';
import 'clang.dart';
final androidNdk = Tool(
name: 'Android NDK',
defaultResolver: _AndroidNdkResolver(),
);
/// [clang] with [Tool.defaultResolver] for the [OS.android] NDK.
final androidNdkClang = Tool(
name: clang.name,
defaultResolver: _AndroidNdkResolver(),
);
/// [llvmAr] with [Tool.defaultResolver] for the [OS.android] NDK.
final androidNdkLlvmAr = Tool(
name: llvmAr.name,
defaultResolver: _AndroidNdkResolver(),
);
/// [lld] with [Tool.defaultResolver] for the [OS.android] NDK.
final androidNdkLld = Tool(
name: lld.name,
defaultResolver: _AndroidNdkResolver(),
);
class _AndroidNdkResolver implements ToolResolver {
final installLocationResolver = PathVersionResolver(
wrappedResolver: ToolResolvers([
RelativeToolResolver(
toolName: 'Android NDK',
wrappedResolver: PathToolResolver(
toolName: 'ndk-build',
executableName: Platform.isWindows ? 'ndk-build.cmd' : 'ndk-build',
),
relativePath: Uri(path: ''),
),
InstallLocationResolver(
toolName: 'Android NDK',
paths: [
if (Platform.isLinux) ...[
'\$HOME/Android/Sdk/ndk/*/',
'\$HOME/Android/Sdk/ndk-bundle/',
],
if (Platform.isMacOS) ...[
'\$HOME/Library/Android/sdk/ndk/*/',
],
if (Platform.isWindows) ...[
'\$HOME/AppData/Local/Android/Sdk/ndk/*/',
],
],
),
]),
);
@override
Future<List<ToolInstance>> resolve({required Logger? logger}) async {
final ndkInstances = await installLocationResolver.resolve(logger: logger);
return [
for (final ndkInstance in ndkInstances) ...[
ndkInstance,
...await tryResolveClang(
ndkInstance,
logger: logger,
)
]
];
}
Future<List<ToolInstance>> tryResolveClang(
ToolInstance androidNdkInstance, {
required Logger? logger,
}) async {
final result = <ToolInstance>[];
final prebuiltUri =
androidNdkInstance.uri.resolve('toolchains/llvm/prebuilt/');
final prebuiltDir = Directory.fromUri(prebuiltUri);
final hostArchDirs =
(await prebuiltDir.list().toList()).whereType<Directory>().toList();
for (final hostArchDir in hostArchDirs) {
final clangUri = hostArchDir.uri
.resolve('bin/')
.resolve(Target.current.os.executableFileName('clang'));
if (await File.fromUri(clangUri).exists()) {
result.add(await CliVersionResolver.lookupVersion(
ToolInstance(
tool: androidNdkClang,
uri: clangUri,
),
logger: logger,
));
}
final arUri = hostArchDir.uri
.resolve('bin/')
.resolve(Target.current.os.executableFileName('llvm-ar'));
if (await File.fromUri(arUri).exists()) {
result.add(await CliVersionResolver.lookupVersion(
ToolInstance(
tool: androidNdkLlvmAr,
uri: arUri,
),
logger: logger,
));
}
final ldUri = hostArchDir.uri
.resolve('bin/')
.resolve(Target.current.os.executableFileName('ld.lld'));
if (await File.fromUri(arUri).exists()) {
result.add(await CliVersionResolver.lookupVersion(
ToolInstance(
tool: androidNdkLld,
uri: ldUri,
),
logger: logger,
));
}
}
return result;
}
}