ProgramPreprocess.cs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.IO;
  5. namespace Google.ProtocolBuffers.ProtoGen
  6. {
  7. /// <summary>
  8. /// Preprocesses any input files with an extension of '.proto' by running protoc.exe. If arguments
  9. /// are supplied with '--' prefix they are provided to protoc.exe, otherwise they are assumed to
  10. /// be used for ProtoGen.exe which is run on the resulting output proto buffer. If the option
  11. /// --descriptor_set_out= is specified the proto buffer file is kept, otherwise it will be removed
  12. /// after code generation.
  13. /// </summary>
  14. internal class ProgramPreprocess
  15. {
  16. static int Main(string[] args)
  17. {
  18. try
  19. {
  20. return Environment.ExitCode = Run(args);
  21. }
  22. catch (Exception ex)
  23. {
  24. Console.Error.WriteLine(ex);
  25. return Environment.ExitCode = 2;
  26. }
  27. }
  28. internal static int Run(params string[] args)
  29. {
  30. bool deleteFile = false;
  31. string tempFile = null;
  32. int result = 1;
  33. bool doHelp = args.Length == 0;
  34. try
  35. {
  36. List<string> protocArgs = new List<string>();
  37. List<string> protoGenArgs = new List<string>();
  38. foreach (string arg in args)
  39. {
  40. doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/?");
  41. doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "/help");
  42. doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-?");
  43. doHelp |= StringComparer.OrdinalIgnoreCase.Equals(arg, "-help");
  44. if(arg.StartsWith("--descriptor_set_out="))
  45. {
  46. tempFile = arg.Substring("--descriptor_set_out=".Length);
  47. protoGenArgs.Add(tempFile);
  48. }
  49. }
  50. if (doHelp)
  51. {
  52. Console.WriteLine();
  53. Console.WriteLine("PROTOC.exe: Use any of the following options that begin with '--':");
  54. Console.WriteLine();
  55. try { RunProtoc("--help"); }
  56. catch (Exception ex) { Console.Error.WriteLine(ex.Message); }
  57. Console.WriteLine();
  58. Console.WriteLine();
  59. Console.WriteLine("PRTOGEN.exe: The following options are used to specify defaults for code generation.");
  60. Console.WriteLine();
  61. Program.Main(new string[0]);
  62. return 0;
  63. }
  64. foreach (string arg in args)
  65. {
  66. if (arg.StartsWith("--"))
  67. protocArgs.Add(arg);
  68. else if (File.Exists(arg) && StringComparer.OrdinalIgnoreCase.Equals(".proto", Path.GetExtension(arg)))
  69. {
  70. if (tempFile == null)
  71. {
  72. deleteFile = true;
  73. tempFile = Path.GetTempFileName();
  74. protocArgs.Add(String.Format("--descriptor_set_out={0}", tempFile));
  75. protoGenArgs.Add(tempFile);
  76. }
  77. protocArgs.Add(arg);
  78. }
  79. else
  80. protoGenArgs.Add(arg);
  81. }
  82. if (tempFile != null)
  83. {
  84. result = RunProtoc(protocArgs.ToArray());
  85. if (result != 0)
  86. return result;
  87. }
  88. result = Program.Main(protoGenArgs.ToArray());
  89. }
  90. finally
  91. {
  92. if (deleteFile && tempFile != null && File.Exists(tempFile))
  93. File.Delete(tempFile);
  94. }
  95. return result;
  96. }
  97. private static int RunProtoc(params string[] args)
  98. {
  99. const string protoc = "protoc.exe";
  100. string exePath = protoc;
  101. //why oh why is this not in System.IO.Path or Environment...
  102. List<string> searchPath = new List<string>();
  103. searchPath.Add(Environment.CurrentDirectory);
  104. searchPath.Add(AppDomain.CurrentDomain.BaseDirectory);
  105. searchPath.AddRange((Environment.GetEnvironmentVariable("PATH") ?? String.Empty).Split(Path.PathSeparator));
  106. foreach (string path in searchPath)
  107. if (File.Exists(exePath = Path.Combine(path, protoc)))
  108. break;
  109. if (!File.Exists(exePath))
  110. throw new FileNotFoundException("Unable to locate " + protoc + " make sure it is in the PATH, cwd, or exe dir.");
  111. for (int i = 0; i < args.Length; i++)
  112. if (args[i].IndexOf(' ') > 0 && args[i][0] != '"')
  113. args[i] = '"' + args[i] + '"';
  114. ProcessStartInfo psi = new ProcessStartInfo(exePath);
  115. psi.Arguments = String.Join(" ", args);
  116. psi.RedirectStandardError = true;
  117. psi.RedirectStandardInput = false;
  118. psi.RedirectStandardOutput = true;
  119. psi.ErrorDialog = false;
  120. psi.CreateNoWindow = true;
  121. psi.UseShellExecute = false;
  122. psi.WorkingDirectory = Environment.CurrentDirectory;
  123. Process process = Process.Start(psi);
  124. if (process == null) return 1;
  125. process.WaitForExit();
  126. string tmp = process.StandardOutput.ReadToEnd();
  127. if(tmp.Trim().Length > 0) Console.Out.WriteLine(tmp);
  128. tmp = process.StandardError.ReadToEnd();
  129. if (tmp.Trim().Length > 0) Console.Error.WriteLine(tmp);
  130. return process.ExitCode;
  131. }
  132. }
  133. }