Modular AOT compiler main
Issue: https://github.com/dart-lang/sdk/issues/61635 Change-Id: I55eaf5267c63d75b317276dfeab4d27e93139db3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/475407 Reviewed-by: Slava Egorov <vegorov@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
This commit is contained in:
committed by
Commit Queue
parent
19607c4a59
commit
ca604cf41a
@@ -129,6 +129,7 @@ group("runtime_precompiled") {
|
||||
}
|
||||
if (dart_dynamic_modules) {
|
||||
deps += [ "utils/dart2bytecode:dart2bytecode_snapshot" ]
|
||||
deps += [ "utils/modular_aot_compiler:modular_aot_compiler_snapshot" ]
|
||||
deps += [ "utils/dynamic_module_runner:dynamic_module_runner_snapshot" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// 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 'package:native_compiler/modular_aot_compiler.dart'
|
||||
as modular_aot_compiler;
|
||||
|
||||
void main(List<String> args) => modular_aot_compiler.main(args);
|
||||
@@ -0,0 +1,132 @@
|
||||
// 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 'package:cfg/front_end/ast_to_ir.dart';
|
||||
import 'package:cfg/front_end/recognized_methods.dart';
|
||||
import 'package:cfg/ir/flow_graph.dart';
|
||||
import 'package:cfg/ir/functions.dart';
|
||||
import 'package:kernel/ast.dart' as ast;
|
||||
import 'package:native_compiler/back_end/code_generator.dart';
|
||||
import 'package:native_compiler/configuration.dart';
|
||||
import 'package:native_compiler/snapshot/image_writer.dart';
|
||||
import 'package:native_compiler/snapshot/snapshot.dart';
|
||||
|
||||
/// Accumulates contents of the whole compilation set.
|
||||
class CompilationSet {
|
||||
final List<ast.Library> libraries;
|
||||
final Configuration config;
|
||||
final FunctionRegistry functionRegistry = FunctionRegistry();
|
||||
final RecognizedMethods recognizedMethods = CommonRecognizedMethods();
|
||||
final List<CFunction> _pendingFunctions = [];
|
||||
final ImageWriter _imageWriter;
|
||||
late final SnapshotSerializer _snapshot;
|
||||
|
||||
CompilationSet(this.libraries, this.config)
|
||||
: _imageWriter = config.createImageWriter() {
|
||||
_snapshot = SnapshotSerializer(config.targetCPU, functionRegistry);
|
||||
}
|
||||
|
||||
/// Add [function] to be compiled.
|
||||
///
|
||||
/// Can be used to queue nested local functions discovered
|
||||
/// during compilation.
|
||||
void addFunction(CFunction function) {
|
||||
_pendingFunctions.add(function);
|
||||
}
|
||||
|
||||
/// Compile all functions from [libraries].
|
||||
void compileAllFunctions() {
|
||||
for (final lib in libraries) {
|
||||
for (final cls in lib.classes) {
|
||||
for (final field in cls.fields) {
|
||||
_compileFieldFunctions(field);
|
||||
_compilePendingFunctions();
|
||||
}
|
||||
for (final constr in cls.constructors) {
|
||||
compileFunction(functionRegistry.getFunction(constr));
|
||||
_compilePendingFunctions();
|
||||
}
|
||||
for (final proc in cls.procedures) {
|
||||
compileFunction(
|
||||
functionRegistry.getFunction(
|
||||
proc,
|
||||
isGetter: proc.isGetter,
|
||||
isSetter: proc.isSetter,
|
||||
),
|
||||
);
|
||||
_compilePendingFunctions();
|
||||
}
|
||||
}
|
||||
for (final field in lib.fields) {
|
||||
_compileFieldFunctions(field);
|
||||
_compilePendingFunctions();
|
||||
}
|
||||
for (final proc in lib.procedures) {
|
||||
compileFunction(
|
||||
functionRegistry.getFunction(
|
||||
proc,
|
||||
isGetter: proc.isGetter,
|
||||
isSetter: proc.isSetter,
|
||||
),
|
||||
);
|
||||
_compilePendingFunctions();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void _compileFieldFunctions(ast.Field field) {
|
||||
if (field.hasGetter && !field.isStatic) {
|
||||
compileFunction(functionRegistry.getFunction(field, isGetter: true));
|
||||
}
|
||||
if (field.hasSetter && !field.isStatic) {
|
||||
compileFunction(functionRegistry.getFunction(field, isSetter: true));
|
||||
}
|
||||
if ((field.isStatic || field.isLate) && field.initializer != null) {
|
||||
compileFunction(functionRegistry.getFunction(field, isInitializer: true));
|
||||
}
|
||||
}
|
||||
|
||||
void _compilePendingFunctions() {
|
||||
// [_pendingFunctions] can grow over time as local functions are
|
||||
// discovered during compilation.
|
||||
for (var i = 0; i < _pendingFunctions.length; ++i) {
|
||||
compileFunction(_pendingFunctions[i]);
|
||||
}
|
||||
_pendingFunctions.clear();
|
||||
}
|
||||
|
||||
/// Compile [function] to native code.
|
||||
void compileFunction(CFunction function) {
|
||||
FlowGraph graph;
|
||||
try {
|
||||
graph = AstToIr(
|
||||
function,
|
||||
functionRegistry,
|
||||
recognizedMethods,
|
||||
enableAsserts: config.enableAsserts,
|
||||
).buildFlowGraph();
|
||||
} catch (_) {
|
||||
print('Compiler crashed while compiling $function');
|
||||
rethrow;
|
||||
}
|
||||
|
||||
config.createPipeline(functionRegistry, _consumeGeneratedCode).run(graph);
|
||||
}
|
||||
|
||||
void _consumeGeneratedCode(Code code) {
|
||||
code.instructionsImageOffset = _imageWriter.addInstructions(
|
||||
code.instructions,
|
||||
);
|
||||
_snapshot.addRoot(code);
|
||||
}
|
||||
|
||||
void writeSnapshot(Sink<List<int>> sink) {
|
||||
_snapshot.writeModuleSnapshot();
|
||||
_imageWriter.addReadOnlyData(
|
||||
_snapshot.out.getContents(),
|
||||
_snapshot.out.position,
|
||||
);
|
||||
_imageWriter.writeTo(sink);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,26 @@
|
||||
// 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 'package:cfg/ir/functions.dart';
|
||||
import 'package:cfg/ir/ssa_computation.dart';
|
||||
import 'package:cfg/passes/constant_propagation.dart';
|
||||
import 'package:cfg/passes/control_flow_optimizations.dart';
|
||||
import 'package:cfg/passes/pass.dart';
|
||||
import 'package:cfg/passes/simplification.dart';
|
||||
import 'package:cfg/passes/value_numbering.dart';
|
||||
import 'package:native_compiler/back_end/arm64/code_generator.dart';
|
||||
import 'package:native_compiler/back_end/arm64/constraints.dart';
|
||||
import 'package:native_compiler/back_end/back_end_state.dart';
|
||||
import 'package:native_compiler/back_end/code_generator.dart';
|
||||
import 'package:native_compiler/back_end/constraints.dart';
|
||||
import 'package:native_compiler/back_end/regalloc_checker.dart';
|
||||
import 'package:native_compiler/back_end/register_allocator.dart';
|
||||
import 'package:native_compiler/passes/lowering.dart';
|
||||
import 'package:native_compiler/passes/reorder_blocks.dart';
|
||||
import 'package:native_compiler/runtime/vm_defs.dart';
|
||||
import 'package:native_compiler/snapshot/image_writer.dart';
|
||||
import 'package:native_compiler/snapshot/macho/macho_image_writer.dart';
|
||||
|
||||
enum TargetCPU {
|
||||
arm64;
|
||||
|
||||
@@ -9,3 +29,78 @@ enum TargetCPU {
|
||||
static final List<String> allowedNames = [for (final v in values) v.name];
|
||||
static TargetCPU fromName(String name) => values.byName(name);
|
||||
}
|
||||
|
||||
enum ImageFormat {
|
||||
macho;
|
||||
|
||||
static final String defaultName = macho.name;
|
||||
static final List<String> allowedNames = [for (final v in values) v.name];
|
||||
static ImageFormat fromName(String name) => values.byName(name);
|
||||
}
|
||||
|
||||
abstract base class Configuration {
|
||||
final TargetCPU targetCPU;
|
||||
final ImageFormat imageFormat;
|
||||
final bool enableAsserts;
|
||||
final String outputLibraryName;
|
||||
|
||||
Configuration(
|
||||
this.targetCPU,
|
||||
this.imageFormat, {
|
||||
required this.enableAsserts,
|
||||
required this.outputLibraryName,
|
||||
});
|
||||
|
||||
Pipeline createPipeline(
|
||||
FunctionRegistry functionRegistry,
|
||||
CodeConsumer consumeGeneratedCode,
|
||||
);
|
||||
|
||||
Constraints createConstraints() => switch (targetCPU) {
|
||||
TargetCPU.arm64 => Arm64Constraints(),
|
||||
};
|
||||
|
||||
CodeGenerator createCodeGenerator(BackEndState backEndState) =>
|
||||
switch (targetCPU) {
|
||||
TargetCPU.arm64 => Arm64CodeGenerator(backEndState),
|
||||
};
|
||||
|
||||
ImageWriter createImageWriter() => switch (imageFormat) {
|
||||
ImageFormat.macho => MachoImageWriter(targetCPU, outputLibraryName),
|
||||
};
|
||||
}
|
||||
|
||||
final class DevelopmentCompilerConfiguration extends Configuration {
|
||||
DevelopmentCompilerConfiguration(
|
||||
super.targetCPU,
|
||||
super.imageFormat, {
|
||||
required super.enableAsserts,
|
||||
required super.outputLibraryName,
|
||||
});
|
||||
|
||||
VMOffsets createVMOffsets() => switch (targetCPU) {
|
||||
TargetCPU.arm64 => Arm64VMOffsets(),
|
||||
};
|
||||
|
||||
@override
|
||||
Pipeline createPipeline(
|
||||
FunctionRegistry functionRegistry,
|
||||
CodeConsumer consumeGeneratedCode,
|
||||
) {
|
||||
final backEndState = BackEndState();
|
||||
backEndState.vmOffsets = createVMOffsets();
|
||||
backEndState.consumeGeneratedCode = consumeGeneratedCode;
|
||||
final constraints = createConstraints();
|
||||
return Pipeline([
|
||||
SSAComputation(),
|
||||
ValueNumbering(simplification: Simplification()),
|
||||
ConstantPropagation(),
|
||||
ControlFlowOptimizations(),
|
||||
Lowering(functionRegistry),
|
||||
ReorderBlocks(backEndState),
|
||||
LinearScanRegisterAllocator(backEndState, constraints),
|
||||
RegisterAllocationChecker(backEndState, constraints),
|
||||
createCodeGenerator(backEndState),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,301 @@
|
||||
// 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:async';
|
||||
import 'dart:io' as io show exitCode, File, Platform;
|
||||
|
||||
import 'package:args/args.dart' show ArgParser, ArgResults;
|
||||
import 'package:cfg/ir/global_context.dart';
|
||||
import 'package:front_end/src/api_unstable/vm.dart'
|
||||
show
|
||||
CompilerOptions,
|
||||
InvocationMode,
|
||||
CfeDiagnosticMessage,
|
||||
Verbosity,
|
||||
parseExperimentalArguments,
|
||||
parseExperimentalFlags,
|
||||
resolveInputUri;
|
||||
import 'package:kernel/ast.dart' as ast show Component;
|
||||
import 'package:kernel/type_environment.dart' show TypeEnvironment;
|
||||
import 'package:native_compiler/compilation_set.dart';
|
||||
import 'package:native_compiler/configuration.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:vm/kernel_front_end.dart'
|
||||
show
|
||||
badUsageExitCode,
|
||||
compileTimeErrorExitCode,
|
||||
compileToKernel,
|
||||
convertToPackageUri,
|
||||
createFrontEndFileSystem,
|
||||
createFrontEndTarget,
|
||||
ErrorDetector,
|
||||
ErrorPrinter,
|
||||
KernelCompilationArguments,
|
||||
parseCommandLineDefines,
|
||||
successExitCode,
|
||||
writeDepfile;
|
||||
|
||||
final ArgParser _argParser = ArgParser(allowTrailingOptions: true)
|
||||
..addOption(
|
||||
'platform',
|
||||
help: 'Path to vm_platform.dill file',
|
||||
defaultsTo: null,
|
||||
)
|
||||
..addOption(
|
||||
'packages',
|
||||
help: 'Path to .dart_tool/package_config.json file',
|
||||
defaultsTo: null,
|
||||
)
|
||||
..addOption(
|
||||
'output',
|
||||
abbr: 'o',
|
||||
help: 'Path to resulting snapshot file',
|
||||
defaultsTo: null,
|
||||
)
|
||||
..addOption('depfile', help: 'Path to output Ninja depfile')
|
||||
..addOption(
|
||||
'depfile-target',
|
||||
help: 'Override the target in the generated depfile',
|
||||
hide: true,
|
||||
)
|
||||
..addMultiOption(
|
||||
'filesystem-root',
|
||||
help:
|
||||
'A base path for the multi-root virtual file system.'
|
||||
' If multi-root file system is used, the input script and .dart_tool/package_config.json file should be specified using URI.',
|
||||
)
|
||||
..addOption(
|
||||
'filesystem-scheme',
|
||||
help: 'The URI scheme for the multi-root virtual filesystem.',
|
||||
)
|
||||
..addOption(
|
||||
'target',
|
||||
help: 'Target model that determines what core libraries are available',
|
||||
allowed: <String>['vm', 'flutter', 'flutter_runner', 'dart_runner'],
|
||||
defaultsTo: 'vm',
|
||||
)
|
||||
..addOption(
|
||||
'target-arch',
|
||||
abbr: 'a',
|
||||
help: 'Target CPU architecture.',
|
||||
allowed: TargetCPU.allowedNames,
|
||||
defaultsTo: TargetCPU.defaultName,
|
||||
)
|
||||
..addOption(
|
||||
'image-format',
|
||||
help: 'Image format of the output snapshot.',
|
||||
allowed: ImageFormat.allowedNames,
|
||||
defaultsTo: ImageFormat.defaultName,
|
||||
)
|
||||
..addMultiOption(
|
||||
'define',
|
||||
abbr: 'D',
|
||||
help: 'The values for the environment constants (e.g. -Dkey=value).',
|
||||
)
|
||||
..addOption(
|
||||
'import-dill',
|
||||
help: 'Import libraries from existing dill file',
|
||||
defaultsTo: null,
|
||||
)
|
||||
..addFlag(
|
||||
'enable-asserts',
|
||||
help: 'Whether asserts will be enabled.',
|
||||
defaultsTo: false,
|
||||
)
|
||||
..addMultiOption(
|
||||
'enable-experiment',
|
||||
help: 'Comma separated list of experimental features to enable.',
|
||||
)
|
||||
..addFlag(
|
||||
'help',
|
||||
abbr: 'h',
|
||||
negatable: false,
|
||||
help: 'Print this help message.',
|
||||
)
|
||||
..addFlag(
|
||||
'track-widget-creation',
|
||||
help: 'Run a kernel transformer to track creation locations for widgets.',
|
||||
defaultsTo: false,
|
||||
)
|
||||
..addOption(
|
||||
'invocation-modes',
|
||||
help: 'Provides information to the front end about how it is invoked.',
|
||||
defaultsTo: '',
|
||||
)
|
||||
..addOption(
|
||||
'verbosity',
|
||||
help:
|
||||
'Sets the verbosity level used for filtering messages during '
|
||||
'compilation.',
|
||||
defaultsTo: Verbosity.defaultValue,
|
||||
);
|
||||
|
||||
final String _usage =
|
||||
'''
|
||||
Usage: modular_aot_compiler --platform vm_platform.dill [--import-dill other.dill] [options] input.dart
|
||||
Compiles Dart sources to modular snapshot with native code.
|
||||
|
||||
Options:
|
||||
${_argParser.usage}
|
||||
''';
|
||||
|
||||
Future<void> main(List<String> arguments) async {
|
||||
io.exitCode = await runCompilerWithCommandLineArguments(arguments);
|
||||
}
|
||||
|
||||
/// Run compiler with given [arguments]
|
||||
/// and return exit code (0 on success, non-zero on failure).
|
||||
Future<int> runCompilerWithCommandLineArguments(List<String> arguments) async {
|
||||
final ArgResults options = _argParser.parse(arguments);
|
||||
final String? platformKernel = options['platform'];
|
||||
|
||||
if (options['help']) {
|
||||
print(_usage);
|
||||
return successExitCode;
|
||||
}
|
||||
|
||||
final String? input = options.rest.singleOrNull;
|
||||
if (input == null || platformKernel == null) {
|
||||
print(_usage);
|
||||
return badUsageExitCode;
|
||||
}
|
||||
|
||||
final String outputFileName =
|
||||
options['output'] ?? "$input.$snapshotExtension";
|
||||
final String? packages = options['packages'];
|
||||
final String targetName = options['target'];
|
||||
final String? fileSystemScheme = options['filesystem-scheme'];
|
||||
final String? depfile = options['depfile'];
|
||||
final String? depfileTarget = options['depfile-target'];
|
||||
final List<String>? fileSystemRoots = options['filesystem-root'];
|
||||
final bool enableAsserts = options['enable-asserts'];
|
||||
final List<String>? experimentalFlags = options['enable-experiment'];
|
||||
final Map<String, String> environmentDefines = {};
|
||||
|
||||
if (!parseCommandLineDefines(options['define'], environmentDefines, _usage)) {
|
||||
return badUsageExitCode;
|
||||
}
|
||||
|
||||
final String? importDill = options['import-dill'];
|
||||
final String messageVerbosity = options['verbosity'];
|
||||
final String cfeInvocationModes = options['invocation-modes'];
|
||||
final bool trackWidgetCreation = options['track-widget-creation'];
|
||||
|
||||
final TargetCPU targetCPU = TargetCPU.fromName(options['target-arch']);
|
||||
final ImageFormat imageFormat = ImageFormat.fromName(options['image-format']);
|
||||
|
||||
final fileSystem = createFrontEndFileSystem(
|
||||
fileSystemScheme,
|
||||
fileSystemRoots,
|
||||
);
|
||||
|
||||
final Uri? packagesUri = packages != null ? resolveInputUri(packages) : null;
|
||||
|
||||
final platformKernelUri = Uri.base.resolveUri(new Uri.file(platformKernel));
|
||||
|
||||
final additionalDills = <Uri>[];
|
||||
if (importDill != null) {
|
||||
additionalDills.add(Uri.base.resolveUri(new Uri.file(importDill)));
|
||||
}
|
||||
|
||||
final verbosity = Verbosity.parseArgument(messageVerbosity);
|
||||
final errorPrinter = ErrorPrinter(verbosity, println: print);
|
||||
final errorDetector = ErrorDetector(previousErrorHandler: errorPrinter.call);
|
||||
|
||||
Uri mainUri = resolveInputUri(input);
|
||||
if (packagesUri != null) {
|
||||
mainUri = await convertToPackageUri(fileSystem, mainUri, packagesUri);
|
||||
}
|
||||
|
||||
final compilerOptions = CompilerOptions()
|
||||
..sdkSummary = platformKernelUri
|
||||
..fileSystem = fileSystem
|
||||
..additionalDills = additionalDills
|
||||
..packagesFileUri = packagesUri
|
||||
..explicitExperimentalFlags = parseExperimentalFlags(
|
||||
parseExperimentalArguments(experimentalFlags),
|
||||
onError: print,
|
||||
)
|
||||
..onDiagnostic = (CfeDiagnosticMessage m) {
|
||||
errorDetector(m);
|
||||
}
|
||||
..embedSourceText = false
|
||||
..invocationModes = InvocationMode.parseArguments(cfeInvocationModes)
|
||||
..verbosity = verbosity
|
||||
..target = createFrontEndTarget(
|
||||
targetName,
|
||||
trackWidgetCreation: trackWidgetCreation,
|
||||
supportMirrors: false,
|
||||
isClosureContextLoweringEnabled: false,
|
||||
);
|
||||
|
||||
if (compilerOptions.target == null) {
|
||||
print('Failed to create front-end target $targetName.');
|
||||
return badUsageExitCode;
|
||||
}
|
||||
|
||||
final results = await compileToKernel(
|
||||
KernelCompilationArguments(
|
||||
source: mainUri,
|
||||
options: compilerOptions,
|
||||
requireMain: false,
|
||||
includePlatform: false,
|
||||
environmentDefines: Map.of(environmentDefines),
|
||||
enableAsserts: enableAsserts,
|
||||
),
|
||||
);
|
||||
|
||||
errorPrinter.printCompilationMessages();
|
||||
|
||||
final ast.Component? component = results.component;
|
||||
if (errorDetector.hasCompilationErrors || component == null) {
|
||||
return compileTimeErrorExitCode;
|
||||
}
|
||||
|
||||
final libraries = component.libraries
|
||||
.where((lib) => !results.loadedLibraries.contains(lib))
|
||||
.toList();
|
||||
final typeEnvironment = TypeEnvironment(
|
||||
results.coreTypes!,
|
||||
results.classHierarchy!,
|
||||
);
|
||||
final config = DevelopmentCompilerConfiguration(
|
||||
targetCPU,
|
||||
imageFormat,
|
||||
enableAsserts: enableAsserts,
|
||||
outputLibraryName: path.basename(outputFileName),
|
||||
);
|
||||
final context = GlobalContext(typeEnvironment: typeEnvironment);
|
||||
await GlobalContext.withContext(context, () {
|
||||
final compilationSet = CompilationSet(libraries, config);
|
||||
compilationSet.compileAllFunctions();
|
||||
final sink = io.File(outputFileName).openWrite();
|
||||
compilationSet.writeSnapshot(sink);
|
||||
return sink.close();
|
||||
});
|
||||
|
||||
if (depfile != null) {
|
||||
await writeDepfile(
|
||||
fileSystem,
|
||||
results.compiledSources!,
|
||||
depfileTarget ?? outputFileName,
|
||||
depfile,
|
||||
);
|
||||
}
|
||||
|
||||
return successExitCode;
|
||||
}
|
||||
|
||||
String snapshotExtension(String name) {
|
||||
if (io.Platform.isLinux || io.Platform.isAndroid || io.Platform.isFuchsia) {
|
||||
return ".so";
|
||||
}
|
||||
if (io.Platform.isMacOS) {
|
||||
return ".dylib";
|
||||
}
|
||||
if (io.Platform.isWindows) {
|
||||
return ".dll";
|
||||
}
|
||||
throw 'Platform is not supported';
|
||||
}
|
||||
@@ -10,11 +10,13 @@ resolution: workspace
|
||||
|
||||
# Use 'any' constraints here; we get our versions from the DEPS file.
|
||||
dependencies:
|
||||
args: any
|
||||
cfg: any
|
||||
crypto: any
|
||||
front_end: any
|
||||
kernel: any
|
||||
path: any
|
||||
vm: any
|
||||
|
||||
dev_dependencies:
|
||||
front_end: any
|
||||
test: any
|
||||
vm: any
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# 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("../../runtime/runtime_args.gni")
|
||||
import("../aot_snapshot.gni")
|
||||
|
||||
group("modular_aot_compiler") {
|
||||
public_deps = [ ":modular_aot_compiler_snapshot" ]
|
||||
}
|
||||
|
||||
aot_snapshot("modular_aot_compiler_snapshot") {
|
||||
main_dart = "../../pkg/native_compiler/bin/modular_aot_compiler.dart"
|
||||
name = "modular_aot_compiler"
|
||||
|
||||
output = "$root_gen_dir/modular_aot_compiler.dart.snapshot"
|
||||
|
||||
# dartaotruntime has dart_product_config applied to it, so it is built in
|
||||
# product mode in both release and product builds, and is only built in debug
|
||||
# mode in debug builds. The following line ensures that the dartaotruntime and
|
||||
# modular_aot_compiler.dart.snapshot in an SDK build are always compatible with
|
||||
# each other.
|
||||
force_product_mode = !dart_debug
|
||||
}
|
||||
Reference in New Issue
Block a user