blob: 20292bf6dc1a21a80b410913735ca2ce6d51259e [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.
// INSTRUCTIONS:
// Builds the unminifed dart2js extension (see DDC issue:
// see DDC issue: https://github.com/dart-lang/sdk/issues/49869).
// Run from the extension root directory:
// - For dev: dart run tool/build_extension.dart
// - For prod: dart run tool/build_extension.dart prod
// - For MV3: dart run tool/build_extension.dart --mv3
import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:path/path.dart' as p;
const _prodFlag = 'prod';
const _mv3Flag = 'mv3';
void main(List<String> arguments) async {
final parser = ArgParser()
..addFlag(_prodFlag, negatable: true, defaultsTo: false)
..addFlag(_mv3Flag, negatable: true, defaultsTo: false);
final argResults = parser.parse(arguments);
exitCode = await run(
isProd: argResults[_prodFlag] as bool,
isMV3: argResults[_mv3Flag] as bool,
);
if (exitCode != 0) {
_logWarning('Run terminated unexpectedly with exit code: $exitCode');
}
}
Future<int> run({required bool isProd, required bool isMV3}) async {
_logInfo(
'Building ${isMV3 ? 'MV3' : 'MV2'} extension for ${isProd ? 'prod' : 'dev'}');
_logInfo('Compiling extension with dart2js to /compiled directory');
final compileStep = await Process.start(
'dart',
['run', 'build_runner', 'build', 'web', '--output', 'build', '--release'],
);
final compileExitCode = await _handleProcess(compileStep);
// Terminate early if compilation failed:
if (compileExitCode != 0) {
return compileExitCode;
}
final manifestFileName = isMV3 ? 'manifest_mv3' : 'manifest_mv2';
_logInfo('Copying manifest.json to /compiled directory');
try {
File(p.join('web', '$manifestFileName.json')).copySync(
p.join('compiled', 'manifest.json'),
);
} catch (error) {
_logWarning('Copying manifest file failed: $error');
// Return non-zero exit code to indicate failure:
return 1;
}
// If we're compiling for prod, skip updating the manifest.json:
if (isProd) return 0;
// Update manifest.json for dev:
_logInfo('Updating manifest.json in /compiled directory.');
final updateStep = await Process.start(
'dart',
[p.join('tool', 'update_dev_files.dart')],
);
final updateExitCode = await _handleProcess(updateStep);
// Return exit code (0 indicates success):
return updateExitCode;
}
Future<int> _handleProcess(Process process) async {
_handleOutput(process.stdout, isStdout: true);
_handleOutput(process.stderr, isStdout: false);
return process.exitCode;
}
void _handleOutput(Stream<List<int>> output, {bool isStdout = true}) {
output
.transform(utf8.decoder)
.transform(const LineSplitter())
.listen((line) => _handleOutputLine(line, isStdout: isStdout));
}
void _handleOutputLine(String line, {bool isStdout = true}) {
// Skip empty lines:
if (line.isEmpty) return;
// Log any unexpected errors and throw:
final outputName = isStdout ? 'stdout' : 'stderr';
if (line.toUpperCase().contains('SEVERE') ||
line.toUpperCase().contains('ERROR')) {
final error = 'Unexpected error in $outputName: $line';
_logWarning(error);
throw Exception(error);
}
// Log message to the terminal:
final message = '$outputName: $line';
isStdout ? _logInfo(message) : _logWarning(message);
}
void _logInfo(String message) {
stdout.writeln(message);
}
void _logWarning(String warning) {
stderr.writeln(warning);
}