execute method
Execute the build recipe.
Returns the NativeBuildResult containing the built artifacts.
Implementation
@override
Future<NativeBuildResult> execute(
NativeBuildContext context,
ResolvedSource source,
) async {
final logger = context.logger ?? Logger('StepBuildRecipe');
logger.fine('Starting build recipe for ${context.target.label}');
logger.fine(
'Recipe has ${steps.length} steps: ${steps.map((s) => s.id).join(', ')}',
);
final orderedSteps = _orderedSteps();
final artifacts = <BuiltNativeArtifact>[];
for (final step in orderedSteps) {
logger.info('Executing step: ${step.id}');
final stopwatch = Stopwatch()..start();
// Check cache if available
if (cache != null) {
final stepContext = NativeStepContext(
buildContext: context,
source: source,
stepId: step.id,
);
final fingerprint = await step.fingerprint(stepContext);
final cached = await cache!.isCached(fingerprint);
if (cached) {
logger.info('Step ${step.id} skipped (cache hit)');
// Reconstruct artifacts from cached declarations
final cachedDecls = await cache!.getCachedArtifacts(fingerprint);
for (final decl in cachedDecls) {
final artifact = _reconstructArtifact(decl, context);
if (artifact != null) artifacts.add(artifact);
}
stopwatch.stop();
continue;
}
// Execute the step
final result = await step.execute(context, source);
stopwatch.stop();
logger.info(
'Step ${step.id} completed in ${stopwatch.elapsedMilliseconds}ms',
);
// Record in cache with artifact declarations
final artifactDecls = result.artifacts
.map((a) => _serializeArtifact(a))
.toList();
await cache!.record(
fingerprint: fingerprint,
artifactDeclarations: artifactDecls,
);
// Collect artifacts from step results
artifacts.addAll(result.artifacts);
} else {
// No cache: just execute
final result = await step.execute(context, source);
stopwatch.stop();
logger.info(
'Step ${step.id} completed in ${stopwatch.elapsedMilliseconds}ms',
);
// Collect artifacts from step results
artifacts.addAll(result.artifacts);
}
}
return NativeBuildResult(artifacts: artifacts);
}