PageRenderTime 39ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/Dependencies/boo/src/Boo.Lang.Compiler/CompilerParameters.cs

https://github.com/w4x/boolangstudio
C# | 514 lines | 374 code | 83 blank | 57 comment | 36 complexity | 78aa8b27494d3bf5dea87ac9c90599eb MD5 | raw file
Possible License(s): GPL-2.0
  1. #region license
  2. // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
  3. // All rights reserved.
  4. //
  5. // Redistribution and use in source and binary forms, with or without modification,
  6. // are permitted provided that the following conditions are met:
  7. //
  8. // * Redistributions of source code must retain the above copyright notice,
  9. // this list of conditions and the following disclaimer.
  10. // * Redistributions in binary form must reproduce the above copyright notice,
  11. // this list of conditions and the following disclaimer in the documentation
  12. // and/or other materials provided with the distribution.
  13. // * Neither the name of Rodrigo B. de Oliveira nor the names of its
  14. // contributors may be used to endorse or promote products derived from this
  15. // software without specific prior written permission.
  16. //
  17. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  18. // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
  21. // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  22. // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  23. // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  24. // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  25. // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. #endregion
  28. using System;
  29. using System.Collections;
  30. using System.Collections.Generic;
  31. using System.Diagnostics;
  32. using System.IO;
  33. using System.Reflection;
  34. using System.Text.RegularExpressions;
  35. namespace Boo.Lang.Compiler
  36. {
  37. /// <summary>
  38. /// Compiler parameters.
  39. /// </summary>
  40. public class CompilerParameters
  41. {
  42. private static List _validFileExtensions = new List(new string[] {".dll", ".exe"});
  43. private TextWriter _outputWriter;
  44. private CompilerPipeline _pipeline;
  45. private CompilerInputCollection _input;
  46. private CompilerResourceCollection _resources;
  47. private AssemblyCollection _assemblyReferences;
  48. private int _maxAttributeSteps;
  49. private string _outputAssembly;
  50. private CompilerOutputType _outputType;
  51. private bool _debug;
  52. private bool _ducky;
  53. private bool _checked;
  54. private bool _generateInMemory;
  55. private bool _StdLib;
  56. private string _keyFile;
  57. private string _keyContainer;
  58. private bool _delaySign;
  59. private ArrayList _libpaths;
  60. private string _systemDir;
  61. private Assembly _booAssembly;
  62. private bool _whiteSpaceAgnostic;
  63. public readonly TraceSwitch TraceSwitch = new TraceSwitch("booc", "boo compiler");
  64. private Dictionary<string, string> _defines = new Dictionary<string, string>();
  65. public CompilerParameters()
  66. : this(true)
  67. {
  68. }
  69. public CompilerParameters(bool loadDefaultReferences)
  70. {
  71. _libpaths = new ArrayList();
  72. _systemDir = GetSystemDir();
  73. _libpaths.Add(_systemDir);
  74. _libpaths.Add(Directory.GetCurrentDirectory());
  75. _pipeline = null;
  76. _input = new CompilerInputCollection();
  77. _resources = new CompilerResourceCollection();
  78. _assemblyReferences = new AssemblyCollection();
  79. _maxAttributeSteps = 2;
  80. _outputAssembly = string.Empty;
  81. _outputType = CompilerOutputType.ConsoleApplication;
  82. _outputWriter = System.Console.Out;
  83. _debug = true;
  84. _checked = true;
  85. _generateInMemory = true;
  86. _StdLib = true;
  87. _delaySign = false;
  88. if (loadDefaultReferences) LoadDefaultReferences();
  89. }
  90. public void LoadDefaultReferences()
  91. {
  92. //mscorlib
  93. _assemblyReferences.Add(
  94. LoadAssembly("mscorlib", true)
  95. );
  96. //System
  97. _assemblyReferences.Add(
  98. LoadAssembly("System", true)
  99. );
  100. //boo.lang.dll
  101. _booAssembly = typeof(Boo.Lang.Builtins).Assembly;
  102. _assemblyReferences.Add(_booAssembly);
  103. //boo.lang.extensions.dll
  104. //try loading extensions next to Boo.Lang (in the same directory)
  105. string tentative = Path.Combine(Path.GetDirectoryName(_booAssembly.Location) , "Boo.Lang.Extensions.dll");
  106. Assembly extensionsAssembly = LoadAssembly(tentative, false);
  107. if(extensionsAssembly == null)//if failed, try loading from the gac
  108. extensionsAssembly = LoadAssembly("Boo.Lang.Extensions", false);
  109. if(extensionsAssembly != null)
  110. _assemblyReferences.Add(extensionsAssembly);
  111. if (TraceSwitch.TraceInfo)
  112. {
  113. Trace.WriteLine("BOO LANG DLL: " + _booAssembly.Location);
  114. Trace.WriteLine("BOO COMPILER EXTENSIONS DLL: " +
  115. (extensionsAssembly != null ? extensionsAssembly.Location : "NOT FOUND!"));
  116. }
  117. }
  118. public Assembly BooAssembly
  119. {
  120. get { return _booAssembly; }
  121. set
  122. {
  123. if (value != null)
  124. {
  125. (_assemblyReferences as IList).Remove(_booAssembly);
  126. _booAssembly = value;
  127. _assemblyReferences.Add(value);
  128. }
  129. }
  130. }
  131. public Assembly FindAssembly(string name)
  132. {
  133. return _assemblyReferences.Find(name);
  134. }
  135. public void AddAssembly(Assembly asm)
  136. {
  137. if (asm != null)
  138. {
  139. _assemblyReferences.Add(asm);
  140. }
  141. }
  142. public Assembly LoadAssembly(string assembly)
  143. {
  144. return LoadAssembly(assembly, true);
  145. }
  146. public Assembly LoadAssembly(string assembly, bool throwOnError)
  147. {
  148. if (TraceSwitch.TraceInfo)
  149. {
  150. Trace.WriteLine("ATTEMPTING LOADASSEMBLY: " + assembly);
  151. }
  152. Assembly a = null;
  153. try
  154. {
  155. if (assembly.IndexOfAny(new char[] {'/', '\\'}) != -1)
  156. {
  157. //nant passes full path to gac dlls, which compiler doesn't like:
  158. //if (assembly.ToLower().StartsWith(_systemDir.ToLower()))
  159. {
  160. //return LoadAssemblyFromGac(Path.GetFileName(assembly));
  161. }
  162. //else //load using path
  163. {
  164. a = Assembly.LoadFrom(assembly);
  165. }
  166. }
  167. else
  168. {
  169. a = LoadAssemblyFromGac(assembly);
  170. }
  171. }
  172. catch (FileNotFoundException /*ignored*/)
  173. {
  174. return LoadAssemblyFromLibPaths(assembly, throwOnError);
  175. }
  176. catch (BadImageFormatException e)
  177. {
  178. if (throwOnError)
  179. {
  180. throw new ApplicationException(Boo.Lang.ResourceManager.Format(
  181. "BooC.BadFormat",
  182. e.FusionLog), e);
  183. }
  184. }
  185. catch (FileLoadException e)
  186. {
  187. if (throwOnError)
  188. {
  189. throw new ApplicationException(Boo.Lang.ResourceManager.Format(
  190. "BooC.UnableToLoadAssembly",
  191. e.FusionLog), e);
  192. }
  193. }
  194. catch (ArgumentNullException e)
  195. {
  196. if (throwOnError)
  197. {
  198. throw new ApplicationException(Boo.Lang.ResourceManager.Format(
  199. "BooC.NullAssembly"), e);
  200. }
  201. }
  202. if (a == null)
  203. {
  204. return LoadAssemblyFromLibPaths(assembly, throwOnError);
  205. }
  206. return a;
  207. }
  208. private Assembly LoadAssemblyFromLibPaths(string assembly, bool throwOnError)
  209. {
  210. Assembly a = null;
  211. string fullLog = "";
  212. foreach (string dir in _libpaths)
  213. {
  214. string full_path = Path.Combine(dir, assembly);
  215. FileInfo file = new FileInfo(full_path);
  216. if (!_validFileExtensions.Contains(file.Extension.ToLower()))
  217. full_path += ".dll";
  218. try
  219. {
  220. a = Assembly.LoadFrom(full_path);
  221. if (a != null)
  222. {
  223. return a;
  224. }
  225. }
  226. catch (FileNotFoundException ff)
  227. {
  228. fullLog += ff.FusionLog;
  229. continue;
  230. }
  231. }
  232. if (throwOnError)
  233. {
  234. throw new ApplicationException(Boo.Lang.ResourceManager.Format(
  235. "BooC.CannotFindAssembly",
  236. assembly));
  237. //assembly, total_log)); //total_log contains the fusion log
  238. }
  239. return a;
  240. }
  241. private Assembly LoadAssemblyFromGac(string assemblyName)
  242. {
  243. assemblyName = NormalizeAssemblyName(assemblyName);
  244. // This is an intentional attempt to load an assembly with partial name
  245. // so ignore the compiler warning
  246. #pragma warning disable 618
  247. Assembly assembly = Assembly.LoadWithPartialName(assemblyName);
  248. #pragma warning restore 618
  249. if (assembly != null) return assembly;
  250. return Assembly.Load(assemblyName);
  251. }
  252. private static string NormalizeAssemblyName(string assembly)
  253. {
  254. if (assembly.EndsWith(".dll") || assembly.EndsWith(".exe"))
  255. {
  256. assembly = assembly.Substring(0, assembly.Length - 4);
  257. }
  258. return assembly;
  259. }
  260. public void LoadReferencesFromPackage(string package)
  261. {
  262. string[] libs = Regex.Split(pkgconfig(package), @"\-r\:", RegexOptions.CultureInvariant);
  263. foreach (string r in libs)
  264. {
  265. string reference = r.Trim();
  266. if (reference.Length == 0) continue;
  267. Trace.WriteLine("LOADING REFERENCE FROM PKGCONFIG '" + package + "' : " + reference);
  268. References.Add(LoadAssembly(reference));
  269. }
  270. }
  271. private static string pkgconfig(string package)
  272. {
  273. #if NO_SYSTEM_DLL
  274. throw new System.NotSupportedException();
  275. #else
  276. Process process;
  277. try
  278. {
  279. process = Builtins.shellp("pkg-config", string.Format("--libs {0}", package));
  280. }
  281. catch (Exception e)
  282. {
  283. throw new ApplicationException(Boo.Lang.ResourceManager.GetString("BooC.PkgConfigNotFound"), e);
  284. }
  285. process.WaitForExit();
  286. if (process.ExitCode != 0)
  287. {
  288. throw new ApplicationException(
  289. Boo.Lang.ResourceManager.Format("BooC.PkgConfigReportedErrors", process.StandardError.ReadToEnd()));
  290. }
  291. return process.StandardOutput.ReadToEnd();
  292. #endif
  293. }
  294. private string GetSystemDir()
  295. {
  296. return Path.GetDirectoryName(typeof(string).Assembly.Location);
  297. }
  298. /// <summary>
  299. /// Max number of steps for the resolution of AST attributes.
  300. /// </summary>
  301. public int MaxAttributeSteps
  302. {
  303. get { return _maxAttributeSteps; }
  304. set { _maxAttributeSteps = value; }
  305. }
  306. public CompilerInputCollection Input
  307. {
  308. get { return _input; }
  309. }
  310. public ArrayList LibPaths
  311. {
  312. get { return _libpaths; }
  313. }
  314. public CompilerResourceCollection Resources
  315. {
  316. get { return _resources; }
  317. }
  318. public AssemblyCollection References
  319. {
  320. get { return _assemblyReferences; }
  321. set
  322. {
  323. if (null == value) throw new ArgumentNullException("References");
  324. _assemblyReferences = value;
  325. }
  326. }
  327. /// <summary>
  328. /// The compilation pipeline.
  329. /// </summary>
  330. public CompilerPipeline Pipeline
  331. {
  332. get { return _pipeline; }
  333. set { _pipeline = value; }
  334. }
  335. /// <summary>
  336. /// The name (full or partial) for the file
  337. /// that should receive the resulting assembly.
  338. /// </summary>
  339. public string OutputAssembly
  340. {
  341. get { return _outputAssembly; }
  342. set
  343. {
  344. if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("OutputAssembly");
  345. _outputAssembly = value;
  346. }
  347. }
  348. /// <summary>
  349. /// Type and execution subsystem for the generated portable
  350. /// executable file.
  351. /// </summary>
  352. public CompilerOutputType OutputType
  353. {
  354. get { return _outputType; }
  355. set { _outputType = value; }
  356. }
  357. public bool GenerateInMemory
  358. {
  359. get { return _generateInMemory; }
  360. set { _generateInMemory = value; }
  361. }
  362. public bool StdLib
  363. {
  364. get { return _StdLib; }
  365. set { _StdLib = value; }
  366. }
  367. public TextWriter OutputWriter
  368. {
  369. get { return _outputWriter; }
  370. set
  371. {
  372. if (null == value)
  373. {
  374. throw new ArgumentNullException("OutputWriter");
  375. }
  376. _outputWriter = value;
  377. }
  378. }
  379. public bool Debug
  380. {
  381. get { return _debug; }
  382. set { _debug = value; }
  383. }
  384. /// <summary>
  385. /// Use duck instead of object as the most generic type.
  386. /// </summary>
  387. public bool Ducky
  388. {
  389. get { return _ducky; }
  390. set { _ducky = value; }
  391. }
  392. public bool Checked
  393. {
  394. get { return _checked; }
  395. set { _checked = value; }
  396. }
  397. public string KeyFile
  398. {
  399. get { return _keyFile; }
  400. set { _keyFile = value; }
  401. }
  402. public string KeyContainer
  403. {
  404. get { return _keyContainer; }
  405. set { _keyContainer = value; }
  406. }
  407. public bool DelaySign
  408. {
  409. get { return _delaySign; }
  410. set { _delaySign = value; }
  411. }
  412. public bool WhiteSpaceAgnostic
  413. {
  414. get
  415. {
  416. return _whiteSpaceAgnostic;
  417. }
  418. set
  419. {
  420. _whiteSpaceAgnostic = value;
  421. }
  422. }
  423. public Dictionary<string, string> Defines
  424. {
  425. get
  426. {
  427. return _defines;
  428. }
  429. }
  430. }
  431. }