aeroson

C# referenced mcs.exe usage

Apr 9th, 2015
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.99 KB | None | 0 0
  1. //
  2. // Mono.CSharp CSharpCodeCompiler Class implementation
  3. //
  4. // Authors:
  5. // Sean Kasun ([email protected])
  6. // Gonzalo Paniagua Javier ([email protected])
  7. //
  8. // Copyright (c) Novell, Inc. (http://www.novell.com)
  9. //
  10.  
  11. //
  12. // Permission is hereby granted, free of charge, to any person obtaining
  13. // a copy of this software and associated documentation files (the
  14. // "Software"), to deal in the Software without restriction, including
  15. // without limitation the rights to use, copy, modify, merge, publish,
  16. // distribute, sublicense, and/or sell copies of the Software, and to
  17. // permit persons to whom the Software is furnished to do so, subject to
  18. // the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be
  21. // included in all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  24. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  25. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  26. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  27. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  28. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  29. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  30. //
  31.  
  32. namespace Modified_Mono_CSharp
  33. {
  34.  
  35. using System;
  36. using System.CodeDom;
  37. using System.CodeDom.Compiler;
  38. using System.ComponentModel;
  39. using System.IO;
  40. using System.Text;
  41. using System.Reflection;
  42. using System.Collections;
  43. using System.Collections.Specialized;
  44. using System.Diagnostics;
  45. using System.Text.RegularExpressions;
  46. using System.Linq;
  47.  
  48. using Mono.CSharp;
  49.  
  50. #if NET_2_0
  51. using System.Threading;
  52. using System.Collections.Generic;
  53. #endif
  54.  
  55. internal class CSharpCodeCompiler : ICodeCompiler
  56. {
  57. static string windowsMcsPath;
  58. static string windowsMonoPath;
  59.  
  60. #if NET_2_0
  61. Mutex mcsOutMutex;
  62. StringCollection mcsOutput;
  63. #endif
  64.  
  65. static CSharpCodeCompiler()
  66. {
  67. if (Path.DirectorySeparatorChar == '\\')
  68. {
  69.  
  70. // default mono install directory
  71. string monoFolderPath = "C:\\Program Files (x86)\\Mono";
  72.  
  73. if (UnityEngine.Application.isEditor == false)
  74. {
  75. monoFolderPath = Path.Combine(Path.GetDirectoryName(UnityEngine.Application.dataPath), "Mono");
  76. }
  77.  
  78.  
  79. windowsMonoPath = Path.Combine(monoFolderPath, "bin\\mono.bat");
  80. if (!File.Exists(windowsMonoPath)) windowsMonoPath = Path.Combine(monoFolderPath, "bin\\mono.exe");
  81.  
  82. if (!File.Exists(windowsMonoPath))
  83. throw new FileNotFoundException("Windows mono path not found: " + windowsMonoPath);
  84. /*#if NET_4_0
  85. windowsMcsPath =
  86. Path.Combine (p, "4.0\\dmcs.exe");
  87. #elif NET_2_0
  88. windowsMcsPath =
  89. Path.Combine (p, "2.0\\gmcs.exe");
  90. #else*/
  91. windowsMcsPath =
  92. Path.Combine(monoFolderPath, "lib\\mono\\4.5\\mcs.exe");
  93. //#endif
  94.  
  95.  
  96. if (!File.Exists(windowsMcsPath))
  97. throw new FileNotFoundException("Windows mcs path not found: " + windowsMcsPath);
  98. }
  99. }
  100.  
  101. //
  102. // Constructors
  103. //
  104. public CSharpCodeCompiler()
  105. {
  106. }
  107.  
  108. #if NET_2_0
  109. public CSharpCodeCompiler (IDictionary <string, string> providerOptions) :
  110. base (providerOptions)
  111. {
  112. }
  113. #endif
  114.  
  115. //
  116. // Methods
  117. //
  118. public CompilerResults CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit e)
  119. {
  120. return CompileAssemblyFromDomBatch(options, new CodeCompileUnit[] { e });
  121. }
  122.  
  123. public CompilerResults CompileAssemblyFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
  124. {
  125. if (options == null)
  126. {
  127. throw new ArgumentNullException("options");
  128. }
  129.  
  130. try
  131. {
  132. return CompileFromDomBatch(options, ea);
  133. }
  134. finally
  135. {
  136. options.TempFiles.Delete();
  137. }
  138. }
  139.  
  140. public CompilerResults CompileAssemblyFromFile(CompilerParameters options, string fileName)
  141. {
  142. return CompileAssemblyFromFileBatch(options, new string[] { fileName });
  143. }
  144.  
  145. public CompilerResults CompileAssemblyFromFileBatch(CompilerParameters options, string[] fileNames)
  146. {
  147. if (options == null)
  148. {
  149. throw new ArgumentNullException("options");
  150. }
  151.  
  152. try
  153. {
  154. return CompileFromFileBatch(options, fileNames);
  155. }
  156. finally
  157. {
  158. options.TempFiles.Delete();
  159. }
  160. }
  161.  
  162. public CompilerResults CompileAssemblyFromSource(CompilerParameters options, string source)
  163. {
  164. return CompileAssemblyFromSourceBatch(options, new string[] { source });
  165. }
  166.  
  167. public CompilerResults CompileAssemblyFromSourceBatch(CompilerParameters options, string[] sources)
  168. {
  169. if (options == null)
  170. {
  171. throw new ArgumentNullException("options");
  172. }
  173.  
  174. try
  175. {
  176. return CompileFromSourceBatch(options, sources);
  177. }
  178. finally
  179. {
  180. options.TempFiles.Delete();
  181. }
  182. }
  183.  
  184. private CompilerResults CompileFromFileBatch(CompilerParameters options, string[] fileNames)
  185. {
  186. if (null == options)
  187. throw new ArgumentNullException("options");
  188. if (null == fileNames)
  189. throw new ArgumentNullException("fileNames");
  190.  
  191. CompilerResults results = new CompilerResults(options.TempFiles);
  192.  
  193.  
  194.  
  195. var args = BuildArgs(options, fileNames).Split(' ');
  196. var errorout = new StringWriter();
  197.  
  198. CompilerCallableEntryPoint.InvokeCompiler(args, errorout);
  199.  
  200. string mcs_output = errorout.ToString();
  201. #if NET_2_0
  202. StringCollection sc = mcsOutput;
  203. #else
  204. var mcsOutput = mcs_output.Split(System.Environment.NewLine.ToCharArray());
  205. StringCollection sc = new StringCollection();
  206. #endif
  207.  
  208. bool loadIt = true;
  209. foreach (string error_line in mcsOutput)
  210. {
  211. #if !NET_2_0
  212. sc.Add(error_line);
  213. #endif
  214. CompilerError error = CreateErrorFromString(error_line);
  215. if (error != null)
  216. {
  217. results.Errors.Add(error);
  218. if (!error.IsWarning)
  219. loadIt = false;
  220. }
  221. }
  222.  
  223.  
  224.  
  225. if (loadIt)
  226. {
  227. if (!File.Exists(options.OutputAssembly))
  228. {
  229. StringBuilder sb = new StringBuilder();
  230. foreach (string s in sc)
  231. sb.Append(s + Environment.NewLine);
  232.  
  233. throw new Exception("Compiler failed to produce the assembly. Output: '" + sb.ToString() + "'");
  234. }
  235.  
  236. if (options.GenerateInMemory)
  237. {
  238. using (FileStream fs = File.OpenRead(options.OutputAssembly))
  239. {
  240. byte[] buffer = new byte[fs.Length];
  241. fs.Read(buffer, 0, buffer.Length);
  242. results.CompiledAssembly = Assembly.Load(buffer, null, options.Evidence);
  243. fs.Close();
  244. }
  245. }
  246. else
  247. {
  248. // Avoid setting CompiledAssembly right now since the output might be a netmodule
  249. results.PathToAssembly = options.OutputAssembly;
  250. }
  251. }
  252. else
  253. {
  254. results.CompiledAssembly = null;
  255. }
  256.  
  257. return results;
  258. }
  259.  
  260. #if NET_2_0
  261. void McsStderrDataReceived (object sender, DataReceivedEventArgs args)
  262. {
  263. if (args.Data != null) {
  264. mcsOutMutex.WaitOne ();
  265. mcsOutput.Add (args.Data);
  266. mcsOutMutex.ReleaseMutex ();
  267. }
  268. }
  269.  
  270. private static string BuildArgs(CompilerParameters options,string[] fileNames, IDictionary <string, string> providerOptions)
  271. #else
  272. private static string BuildArgs(CompilerParameters options, string[] fileNames)
  273. #endif
  274. {
  275. StringBuilder args = new StringBuilder();
  276. if (options.GenerateExecutable)
  277. args.Append("/target:exe ");
  278. else
  279. args.Append("/target:library ");
  280.  
  281. string privateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath;
  282. if (privateBinPath != null && privateBinPath.Length > 0)
  283. args.AppendFormat("/lib:\"{0}\" ", privateBinPath);
  284.  
  285. if (options.Win32Resource != null)
  286. args.AppendFormat("/win32res:\"{0}\" ",
  287. options.Win32Resource);
  288.  
  289. if (options.IncludeDebugInformation)
  290. args.Append("/debug+ /optimize- ");
  291. else
  292. args.Append("/debug- /optimize+ ");
  293.  
  294. if (options.TreatWarningsAsErrors)
  295. args.Append("/warnaserror ");
  296.  
  297. if (options.WarningLevel >= 0)
  298. args.AppendFormat("/warn:{0} ", options.WarningLevel);
  299.  
  300. if (options.OutputAssembly == null || options.OutputAssembly.Length == 0)
  301. {
  302. string extension = (options.GenerateExecutable ? "exe" : "dll");
  303. options.OutputAssembly = GetTempFileNameWithExtension(options.TempFiles, extension,
  304. !options.GenerateInMemory);
  305. }
  306. args.AppendFormat("/out:\"{0}\" ", options.OutputAssembly);
  307.  
  308. string[] mcsDefaultReferencedAssemblies = { "mscorlib.dll", "System.dll", "System.Xml.dll", "System.Core.dll" };
  309.  
  310. foreach (string import in options.ReferencedAssemblies)
  311. {
  312. if (mcsDefaultReferencedAssemblies.Contains(Path.GetFileName(import)))
  313. continue;
  314.  
  315. if (import == null || import.Length == 0)
  316. continue;
  317.  
  318. args.AppendFormat("/r:\"{0}\" ", import);
  319. }
  320.  
  321. if (options.CompilerOptions != null)
  322. {
  323. args.Append(options.CompilerOptions);
  324. args.Append(" ");
  325. }
  326.  
  327. #if NET_2_0
  328. foreach (string embeddedResource in options.EmbeddedResources) {
  329. args.AppendFormat("/resource:\"{0}\" ", embeddedResource);
  330. }
  331.  
  332. foreach (string linkedResource in options.LinkedResources) {
  333. args.AppendFormat("/linkresource:\"{0}\" ", linkedResource);
  334. }
  335.  
  336. if (providerOptions != null && providerOptions.Count > 0) {
  337. string langver;
  338.  
  339. if (!providerOptions.TryGetValue ("CompilerVersion", out langver))
  340. #if NET_4_0
  341. langver = "3.5";
  342. #else
  343. langver = "2.0";
  344. #endif
  345.  
  346. if (langver.Length >= 1 && langver [0] == 'v')
  347. langver = langver.Substring (1);
  348.  
  349. switch (langver) {
  350. case "2.0":
  351. args.Append ("/langversion:ISO-2");
  352. break;
  353.  
  354. case "3.5":
  355. // current default, omit the switch
  356. break;
  357. }
  358. }
  359. #endif
  360.  
  361. args.Append(" -- ");
  362. foreach (string source in fileNames)
  363. args.AppendFormat("\"{0}\" ", source);
  364. return args.ToString();
  365. }
  366. private static CompilerError CreateErrorFromString(string error_string)
  367. {
  368. #if NET_2_0
  369. if (error_string.StartsWith ("BETA"))
  370. return null;
  371. #endif
  372. if (error_string == null || error_string == "")
  373. return null;
  374.  
  375. CompilerError error = new CompilerError();
  376. Regex reg = new Regex(@"^(\s*(?<file>.*)\((?<line>\d*)(,(?<column>\d*))?\)(:)?\s+)*(?<level>\w+)\s*(?<number>.*):\s(?<message>.*)",
  377. RegexOptions.Compiled | RegexOptions.ExplicitCapture);
  378. Match match = reg.Match(error_string);
  379. if (!match.Success)
  380. {
  381. // We had some sort of runtime crash
  382. error.ErrorText = error_string;
  383. error.IsWarning = false;
  384. error.ErrorNumber = "";
  385. return error;
  386. }
  387. if (String.Empty != match.Result("${file}"))
  388. error.FileName = match.Result("${file}");
  389. if (String.Empty != match.Result("${line}"))
  390. error.Line = Int32.Parse(match.Result("${line}"));
  391. if (String.Empty != match.Result("${column}"))
  392. error.Column = Int32.Parse(match.Result("${column}"));
  393.  
  394. string level = match.Result("${level}");
  395. if (level == "warning")
  396. error.IsWarning = true;
  397. else if (level != "error")
  398. return null; // error CS8028 will confuse the regex.
  399.  
  400. error.ErrorNumber = match.Result("${number}");
  401. error.ErrorText = match.Result("${message}");
  402. return error;
  403. }
  404.  
  405. private static string GetTempFileNameWithExtension(TempFileCollection temp_files, string extension, bool keepFile)
  406. {
  407. return temp_files.AddExtension(extension, keepFile);
  408. }
  409.  
  410. private static string GetTempFileNameWithExtension(TempFileCollection temp_files, string extension)
  411. {
  412. return temp_files.AddExtension(extension);
  413. }
  414.  
  415. private CompilerResults CompileFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
  416. {
  417. if (options == null)
  418. {
  419. throw new ArgumentNullException("options");
  420. }
  421.  
  422. if (ea == null)
  423. {
  424. throw new ArgumentNullException("ea");
  425. }
  426.  
  427. string[] fileNames = new string[ea.Length];
  428. StringCollection assemblies = options.ReferencedAssemblies;
  429.  
  430. for (int i = 0; i < ea.Length; i++)
  431. {
  432. CodeCompileUnit compileUnit = ea[i];
  433. fileNames[i] = GetTempFileNameWithExtension(options.TempFiles, i + ".cs");
  434. FileStream f = new FileStream(fileNames[i], FileMode.OpenOrCreate);
  435. StreamWriter s = new StreamWriter(f, Encoding.UTF8);
  436. if (compileUnit.ReferencedAssemblies != null)
  437. {
  438. foreach (string str in compileUnit.ReferencedAssemblies)
  439. {
  440. if (!assemblies.Contains(str))
  441. assemblies.Add(str);
  442. }
  443. }
  444.  
  445. ((ICodeGenerator)this).GenerateCodeFromCompileUnit(compileUnit, s, new CodeGeneratorOptions());
  446. s.Close();
  447. f.Close();
  448. }
  449. return CompileAssemblyFromFileBatch(options, fileNames);
  450. }
  451.  
  452. private CompilerResults CompileFromSourceBatch(CompilerParameters options, string[] sources)
  453. {
  454. if (options == null)
  455. {
  456. throw new ArgumentNullException("options");
  457. }
  458.  
  459. if (sources == null)
  460. {
  461. throw new ArgumentNullException("sources");
  462. }
  463.  
  464. string[] fileNames = new string[sources.Length];
  465.  
  466. for (int i = 0; i < sources.Length; i++)
  467. {
  468. fileNames[i] = GetTempFileNameWithExtension(options.TempFiles, i + ".cs");
  469. FileStream f = new FileStream(fileNames[i], FileMode.OpenOrCreate);
  470. using (StreamWriter s = new StreamWriter(f, Encoding.UTF8))
  471. {
  472. s.Write(sources[i]);
  473. s.Close();
  474. }
  475. f.Close();
  476. }
  477. return CompileFromFileBatch(options, fileNames);
  478. }
  479. }
  480. }
Advertisement
Add Comment
Please, Sign In to add comment