| #region Copyright notice and license |
| |
| // Copyright 2018 gRPC authors. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #endregion |
| |
| using System.Collections.Generic; |
| using Microsoft.Build.Framework; |
| using Microsoft.Build.Utilities; |
| |
| namespace Grpc.Tools |
| { |
| public class ProtoCompilerOutputs : Task |
| { |
| /// <summary> |
| /// Code generator. Currently supported are "csharp", "cpp". |
| /// </summary> |
| [Required] |
| public string Generator { get; set; } |
| |
| /// <summary> |
| /// All Proto files in the project. The task computes possible outputs |
| /// from these proto files, and returns them in the PossibleOutputs list. |
| /// Not all of these might be actually produced by protoc; this is dealt |
| /// with later in the ProtoCompile task which returns the list of |
| /// files actually produced by the compiler. |
| /// </summary> |
| [Required] |
| public ITaskItem[] Protobuf { get; set; } |
| |
| /// <summary> |
| /// All Proto files in the project. A patched copy of all items from |
| /// Protobuf that might contain updated OutputDir and GrpcOutputDir |
| /// attributes. |
| /// </summary> |
| [Output] |
| public ITaskItem[] PatchedProtobuf { get; set; } |
| |
| /// <summary> |
| /// Output items per each potential output. We do not look at existing |
| /// cached dependency even if they exist, since file may be refactored, |
| /// affecting whether or not gRPC code file is generated from a given proto. |
| /// Instead, all potentially possible generated sources are collected. |
| /// It is a wise idea to generate empty files later for those potentials |
| /// that are not actually created by protoc, so the dependency checks |
| /// result in a minimal recompilation. The Protoc task can output the |
| /// list of files it actually produces, given right combination of its |
| /// properties. |
| /// Output items will have the Source metadata set on them: |
| /// <ItemName Include="MyProto.cs" Source="my_proto.proto" /> |
| /// </summary> |
| [Output] |
| public ITaskItem[] PossibleOutputs { get; private set; } |
| |
| public override bool Execute() |
| { |
| var generator = GeneratorServices.GetForLanguage(Generator, Log); |
| if (generator == null) |
| { |
| // Error already logged, just return. |
| return false; |
| } |
| |
| // Get language-specific possible output. The generator expects certain |
| // metadata be set on the proto item. |
| var possible = new List<ITaskItem>(); |
| var patched = new List<ITaskItem>(); |
| foreach (var proto in Protobuf) |
| { |
| var patchedProto = generator.PatchOutputDirectory(proto); |
| patched.Add(patchedProto); |
| |
| var outputs = generator.GetPossibleOutputs(patchedProto); |
| foreach (string output in outputs) |
| { |
| var ti = new TaskItem(output); |
| ti.SetMetadata(Metadata.Source, patchedProto.ItemSpec); |
| possible.Add(ti); |
| } |
| } |
| |
| PatchedProtobuf = patched.ToArray(); |
| PossibleOutputs = possible.ToArray(); |
| |
| return !Log.HasLoggedErrors; |
| } |
| }; |
| } |