build method
Generates the outputs for a given BuildStep
.
Implementation
@override
Future<void> build(BuildStep buildStep) async {
// When "useInstalledProtoc", we will not fetch any external resources
final protoc = useInstalledProtoc
? File('protoc')
: await fetchProtoc(protobufVersion);
final protocPlugin = useInstalledProtoc
? File('')
: await fetchProtocPlugin(protocPluginVersion, precompileProtocPlugin);
final inputPath = path.normalize(buildStep.inputId.path);
final pluginParameters = grpcEnabled ? 'grpc:' : '';
// Read the input path to signal to the build graph that if the file changes
// then it should be rebuilt.
await buildStep.readAsString(buildStep.inputId);
// Create the output directory (if necessary)
await Directory(outputDirectory).create(recursive: true);
// And run the "protoc" process
await ProcessExtensions.runSafely(
protoc.path,
collectProtocArguments(protocPlugin, pluginParameters, inputPath),
);
// Just as with the read, the build runner spies on what we write, so we
// need to write each output file explicitly, even though they've already
// been written by protoc. This will ensure that if an output file is
// deleted, a future build will recreate it. This also checks that the files
// we were expected to write were actually written, since this will fail if
// an output file wasn't created by protoc.
await Future.wait(buildStep.allowedOutputs.map((AssetId out) async {
var file = loadOutputFile(out);
// When there is no service definition in a .proto file, the respective
// .pbgrpc.dart file is not generated. So, we will tolerate its absence.
if (file.path.endsWith('.pbgrpc.dart') && !await file.exists()) {
return;
}
await buildStep.writeAsBytes(out, file.readAsBytes());
}));
}