ProtoCompilerOutputs.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. #region Copyright notice and license
  2. // Copyright 2018 gRPC authors.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. #endregion
  16. using System.Collections.Generic;
  17. using Microsoft.Build.Framework;
  18. using Microsoft.Build.Utilities;
  19. namespace Grpc.Tools
  20. {
  21. public class ProtoCompilerOutputs : Task
  22. {
  23. /// <summary>
  24. /// Code generator. Currently supported are "csharp", "cpp".
  25. /// </summary>
  26. [Required]
  27. public string Generator { get; set; }
  28. /// <summary>
  29. /// All Proto files in the project. The task computes possible outputs
  30. /// from these proto files, and returns them in the PossibleOutputs list.
  31. /// Not all of these might be actually produced by protoc; this is dealt
  32. /// with later in the ProtoCompile task which returns the list of
  33. /// files actually produced by the compiler.
  34. /// </summary>
  35. [Required]
  36. public ITaskItem[] Protobuf { get; set; }
  37. /// <summary>
  38. /// All Proto files in the project. A patched copy of all items from
  39. /// Protobuf that might contain updated OutputDir and GrpcOutputDir
  40. /// attributes.
  41. /// </summary>
  42. [Output]
  43. public ITaskItem[] PatchedProtobuf { get; set; }
  44. /// <summary>
  45. /// Output items per each potential output. We do not look at existing
  46. /// cached dependency even if they exist, since file may be refactored,
  47. /// affecting whether or not gRPC code file is generated from a given proto.
  48. /// Instead, all potentially possible generated sources are collected.
  49. /// It is a wise idea to generate empty files later for those potentials
  50. /// that are not actually created by protoc, so the dependency checks
  51. /// result in a minimal recompilation. The Protoc task can output the
  52. /// list of files it actually produces, given right combination of its
  53. /// properties.
  54. /// Output items will have the Source metadata set on them:
  55. /// <ItemName Include="MyProto.cs" Source="my_proto.proto" />
  56. /// </summary>
  57. [Output]
  58. public ITaskItem[] PossibleOutputs { get; private set; }
  59. public override bool Execute()
  60. {
  61. var generator = GeneratorServices.GetForLanguage(Generator, Log);
  62. if (generator == null)
  63. {
  64. // Error already logged, just return.
  65. return false;
  66. }
  67. // Get language-specific possible output. The generator expects certain
  68. // metadata be set on the proto item.
  69. var possible = new List<ITaskItem>();
  70. var patched = new List<ITaskItem>();
  71. foreach (var proto in Protobuf)
  72. {
  73. var patchedProto = generator.PatchOutputDirectory(proto);
  74. patched.Add(patchedProto);
  75. var outputs = generator.GetPossibleOutputs(patchedProto);
  76. foreach (string output in outputs)
  77. {
  78. var ti = new TaskItem(output);
  79. ti.SetMetadata(Metadata.Source, patchedProto.ItemSpec);
  80. possible.Add(ti);
  81. }
  82. }
  83. PatchedProtobuf = patched.ToArray();
  84. PossibleOutputs = possible.ToArray();
  85. return !Log.HasLoggedErrors;
  86. }
  87. };
  88. }