blob: af4d467c93e092f8dda9fd5354cc71d9c5c8c71a [file]
// Copyright (c) 2026, 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:code_assets/code_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_cmake/native_toolchain_cmake.dart';
const _assetName = 'boring.dart';
Future<void> main(List<String> args) async {
await build(args, (input, output) async {
if (!input.config.buildCodeAssets) {
stdout.writeln(
'boring: skipping native asset build (code assets not requested).',
);
return;
}
await _buildLocalCMake(input, output);
output.dependencies.addAll([
input.packageRoot.resolve('pubspec.yaml'),
input.packageRoot.resolve('hook/build.dart'),
]);
});
}
/// Adds [library] as the `package:boring/boring.dart` code asset.
void _addLibrary(BuildInput input, BuildOutputBuilder output, Uri library) {
output.assets.code.add(
CodeAsset(
package: input.packageName,
name: _assetName,
linkMode: DynamicLoadingBundled(),
file: library,
),
);
}
Future<void> _buildLocalCMake(
BuildInput input,
BuildOutputBuilder output,
) async {
final packageRoot = input.packageRoot;
final installDir = input.outputDirectory.resolve('install/');
final sourceDir = packageRoot.resolve('src/');
final targetOS = input.config.code.targetOS;
final targetArch = input.config.code.targetArchitecture;
stdout.writeln(
'boring: building native asset with CMake for $targetOS-$targetArch.',
);
final builder = CMakeBuilder.create(
name: 'bssl_dart',
sourceDir: sourceDir,
defines: {
'CMAKE_BUILD_TYPE': 'Release',
'CMAKE_INSTALL_PREFIX': installDir.toFilePath(),
},
targets: ['install'],
parallelUseAllProcessors: true,
);
await builder.run(input: input, output: output);
final fileName = targetOS.dylibFileName('bssl_dart');
final library = installDir.resolve(fileName);
if (!File.fromUri(library).existsSync()) {
throw BuildError(
message:
'Failed to locate the built $fileName in '
'${installDir.toFilePath()}',
);
}
_addLibrary(input, output, library);
output.dependencies.addAll(_buildDependencies(packageRoot));
}
final _buildDependencyExtensions = {
'.S',
'.asm',
'.c',
'.cc',
'.cmake',
'.cpp',
'.h',
'.s',
'CMakeLists.txt',
};
Iterable<Uri> _buildDependencies(Uri packageRoot) sync* {
yield* _filesForBuild(Directory.fromUri(packageRoot.resolve('src/')));
yield* _filesForBuild(
Directory.fromUri(packageRoot.resolve('third_party/boringssl/')),
);
}
Iterable<Uri> _filesForBuild(Directory root) sync* {
if (!root.existsSync()) {
return;
}
for (final entity in root.listSync(recursive: true, followLinks: false)) {
if (entity is! File) {
continue;
}
if (!_buildDependencyExtensions.any(entity.uri.path.endsWith)) {
continue;
}
yield entity.uri;
}
}