|  | // Copyright (c) 2024, 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'; | 
|  |  | 
|  | // ignore: implementation_imports | 
|  | import 'package:macros/src/bootstrap.dart'; | 
|  | // ignore: implementation_imports | 
|  | import 'package:macros/src/executor/serialization.dart'; | 
|  |  | 
|  | import 'util.dart'; | 
|  | import '../create_package_config.dart'; | 
|  | import '../io_pipeline.dart'; | 
|  | import '../pipeline.dart'; | 
|  | import '../suite.dart'; | 
|  |  | 
|  | const precompiledMacroId = DataId('macro.exe'); | 
|  |  | 
|  | /// Bootstraps a macro program and compiles it to an AOT executable. | 
|  | class PrecompileMacroAotStep implements IOModularStep { | 
|  | final bool verbose; | 
|  |  | 
|  | PrecompileMacroAotStep({required this.verbose}); | 
|  |  | 
|  | @override | 
|  | List<DataId> get resultData => const [precompiledMacroId]; | 
|  |  | 
|  | @override | 
|  | bool get needsSources => true; | 
|  |  | 
|  | @override | 
|  | List<DataId> get dependencyDataNeeded => const []; | 
|  |  | 
|  | @override | 
|  | List<DataId> get moduleDataNeeded => const []; | 
|  |  | 
|  | @override | 
|  | bool get onlyOnMain => false; | 
|  |  | 
|  | @override | 
|  | bool get onlyOnSdk => false; | 
|  |  | 
|  | @override | 
|  | bool get notOnSdk => true; | 
|  |  | 
|  | @override | 
|  | Future<void> execute(Module module, Uri root, ModuleDataToRelativeUri toUri, | 
|  | List<String> flags) async { | 
|  | if (verbose) { | 
|  | print('\nstep: precompile-macro-aot on $module'); | 
|  | } | 
|  |  | 
|  | var transitiveDependencies = computeTransitiveDependencies(module); | 
|  | var packageConfigUri = await writePackageConfig( | 
|  | module, transitiveDependencies, root, | 
|  | useRealPaths: true); | 
|  |  | 
|  | var bootstrapContent = bootstrapMacroIsolate( | 
|  | module.macroConstructors, SerializationMode.byteData) | 
|  | // TODO: Don't do this https://github.com/dart-lang/sdk/issues/55388 | 
|  | .replaceFirst('dev-dart-app:/', ''); | 
|  | var bootstrapFile = File.fromUri( | 
|  | root.replace(path: '${root.path}/${module.name}.macro.bootstrap.dart')); | 
|  | await bootstrapFile.create(recursive: true); | 
|  | await bootstrapFile.writeAsString(bootstrapContent); | 
|  |  | 
|  | var args = [ | 
|  | 'compile', | 
|  | 'exe', | 
|  | '--packages', | 
|  | packageConfigUri.toFilePath(), | 
|  | '--output', | 
|  | '${toUri(module, precompiledMacroId)}', | 
|  | ...flags.expand((String flag) => ['--enable-experiment', flag]), | 
|  | bootstrapFile.path, | 
|  | ]; | 
|  |  | 
|  | var result = await runProcess( | 
|  | Platform.resolvedExecutable, args, root.toFilePath(), verbose); | 
|  | checkExitCode(result, this, module, verbose); | 
|  | } | 
|  |  | 
|  | @override | 
|  | void notifyCached(Module module) { | 
|  | if (verbose) { | 
|  | print('\ncached step: precompile-macro-aot on $module'); | 
|  | } | 
|  | } | 
|  |  | 
|  | @override | 
|  | bool shouldExecute(Module module) => module.macroConstructors.isNotEmpty; | 
|  | } | 
|  |  | 
|  | // The value of the --precompiled-macro argument for macros coming from | 
|  | // `module`. | 
|  | String precompiledMacroArg(Module module, ModuleDataToRelativeUri toUri) { | 
|  | var executableUri = toUri(module, precompiledMacroId); | 
|  | return '$executableUri;${module.macroConstructors.keys.join(';')}'; | 
|  | } |