flutter/packages/flutter_tools/bin/fuchsia_asset_builder.dart
Andrew Kolos cbe0ceafe2
consolidate AssetBundle::entries and AssetBundle::entryKinds into a new type, AssetBundleEntry (#142029)
Part of work on https://github.com/flutter/flutter/pull/141194

The [`AssetBundle`](0833929c99/packages/flutter_tools/lib/src/asset.dart (L80)) class contains two members, `entries` and `entryKinds`. `entries` contains asset data indexed by asset key. `entryKinds` contains the "kinds" of these assets, again indexed by asset key.

**Change.** Rather than have two separate maps, this PR proposes combining these maps into one by wrapping the asset data and kind into a single data type `AssetBundleEntry`.

**Purpose.** In https://github.com/flutter/flutter/pull/141194, I am considering associating more information with an asset. In particular, what transformers are meant to be applied to it when copying it to the build output. Rather than adding another map member onto `AssetBundle` (e.g. `entryTransformers`), I decided to make things neater by introducing the `AssetBundleEntry` type.
2024-01-23 22:00:46 +00:00

117 lines
4.4 KiB
Dart

// Copyright 2014 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 'package:args/args.dart';
import 'package:flutter_tools/src/asset.dart' hide defaultManifestPath;
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/context.dart';
import 'package:flutter_tools/src/base/file_system.dart' as libfs;
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/build_system/depfile.dart';
import 'package:flutter_tools/src/bundle.dart';
import 'package:flutter_tools/src/bundle_builder.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/context_runner.dart';
import 'package:flutter_tools/src/globals.dart' as globals;
import 'package:flutter_tools/src/reporting/reporting.dart';
const String _kOptionPackages = 'packages';
const String _kOptionAsset = 'asset-dir';
const String _kOptionManifest = 'manifest';
const String _kOptionAssetManifestOut = 'asset-manifest-out';
const String _kOptionComponentName = 'component-name';
const String _kOptionDepfile = 'depfile';
const List<String> _kRequiredOptions = <String>[
_kOptionPackages,
_kOptionAsset,
_kOptionAssetManifestOut,
_kOptionComponentName,
];
Future<void> main(List<String> args) {
return runInContext<void>(() => run(args), overrides: <Type, Generator>{
Usage: () => DisabledUsage(),
});
}
Future<void> writeAssetFile(libfs.File outputFile, AssetBundleEntry asset) async {
outputFile.createSync(recursive: true);
final List<int> data = await asset.contentsAsBytes();
outputFile.writeAsBytesSync(data);
}
Future<void> run(List<String> args) async {
final ArgParser parser = ArgParser()
..addOption(_kOptionPackages, help: 'The .packages file')
..addOption(_kOptionAsset,
help: 'The directory where to put temporary files')
..addOption(_kOptionManifest, help: 'The manifest file')
..addOption(_kOptionAssetManifestOut)
..addOption(_kOptionComponentName)
..addOption(_kOptionDepfile);
final ArgResults argResults = parser.parse(args);
if (_kRequiredOptions
.any((String option) => !argResults.options.contains(option))) {
globals.printError('Missing option! All options must be specified.');
exit(1);
}
Cache.flutterRoot = globals.platform.environment['FLUTTER_ROOT'];
final String assetDir = argResults[_kOptionAsset] as String;
final AssetBundle? assets = await buildAssets(
manifestPath: argResults[_kOptionManifest] as String? ?? defaultManifestPath,
assetDirPath: assetDir,
packagesPath: argResults[_kOptionPackages] as String?,
targetPlatform: TargetPlatform.fuchsia_arm64 // This is not arch specific.
);
if (assets == null) {
throwToolExit('Unable to find assets.', exitCode: 1);
}
final List<Future<void>> calls = <Future<void>>[];
assets.entries.forEach((String fileName, AssetBundleEntry entry) {
final libfs.File outputFile = globals.fs.file(globals.fs.path.join(assetDir, fileName));
calls.add(writeAssetFile(outputFile, entry));
});
await Future.wait<void>(calls);
final String outputMan = argResults[_kOptionAssetManifestOut] as String;
await writeFuchsiaManifest(assets, argResults[_kOptionAsset] as String, outputMan, argResults[_kOptionComponentName] as String);
final String? depfilePath = argResults[_kOptionDepfile] as String?;
if (depfilePath != null) {
await writeDepfile(assets, outputMan, depfilePath);
}
}
Future<void> writeDepfile(AssetBundle assets, String outputManifest, String depfilePath) async {
final Depfile depfileContent = Depfile(
assets.inputFiles,
<libfs.File>[globals.fs.file(outputManifest)],
);
final DepfileService depfileService = DepfileService(
fileSystem: globals.fs,
logger: globals.logger,
);
final libfs.File depfile = globals.fs.file(depfilePath);
await depfile.create(recursive: true);
depfileService.writeToFile(depfileContent, depfile);
}
Future<void> writeFuchsiaManifest(AssetBundle assets, String outputBase, String fileDest, String componentName) async {
final libfs.File destFile = globals.fs.file(fileDest);
await destFile.create(recursive: true);
final libfs.IOSink outFile = destFile.openWrite();
for (final String path in assets.entries.keys) {
outFile.write('data/$componentName/$path=$outputBase/$path\n');
}
await outFile.flush();
await outFile.close();
}