3 // Copyright (c) 2004, Rodrigo B. de Oliveira (rbo@acm.org)
4 // All rights reserved.
6 // Redistribution and use in source and binary forms, with or without modification,
7 // are permitted provided that the following conditions are met:
9 // * Redistributions of source code must retain the above copyright notice,
10 // this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above copyright notice,
12 // this list of conditions and the following disclaimer in the documentation
13 // and/or other materials provided with the distribution.
14 // * Neither the name of Rodrigo B. de Oliveira nor the names of its
15 // contributors may be used to endorse or promote products derived from this
16 // software without specific prior written permission.
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
22 // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 // THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 using System
.Collections
;
33 using System
.Diagnostics
;
35 using System
.Reflection
;
36 using System
.Text
.RegularExpressions
;
38 namespace Boo
.Lang
.Compiler
41 /// Compiler parameters.
43 public class CompilerParameters
45 private static List _validFileExtensions
= new List(new string[] {".dll", ".exe"}
);
47 private TextWriter _outputWriter
;
49 private CompilerPipeline _pipeline
;
51 private CompilerInputCollection _input
;
53 private CompilerResourceCollection _resources
;
55 private AssemblyCollection _assemblyReferences
;
57 private int _maxAttributeSteps
;
59 private string _outputAssembly
;
61 private CompilerOutputType _outputType
;
67 private bool _checked
;
69 private bool _generateInMemory
;
73 private string _keyFile
;
75 private string _keyContainer
;
77 private bool _delaySign
;
79 private ArrayList _libpaths
;
81 private string _systemDir
;
83 private Assembly _booAssembly
;
85 private bool _whiteSpaceAgnostic
;
87 public readonly TraceSwitch TraceSwitch
= new TraceSwitch("booc", "boo compiler");
89 public CompilerParameters()
94 public CompilerParameters(bool loadDefaultReferences
)
96 _libpaths
= new ArrayList();
97 _systemDir
= GetSystemDir();
98 _libpaths
.Add(_systemDir
);
99 _libpaths
.Add(Directory
.GetCurrentDirectory());
102 _input
= new CompilerInputCollection();
103 _resources
= new CompilerResourceCollection();
104 _assemblyReferences
= new AssemblyCollection();
106 _maxAttributeSteps
= 2;
107 _outputAssembly
= string.Empty
;
108 _outputType
= CompilerOutputType
.ConsoleApplication
;
109 _outputWriter
= System
.Console
.Out
;
112 _generateInMemory
= true;
117 if (loadDefaultReferences
) LoadDefaultReferences();
120 public void LoadDefaultReferences()
123 _assemblyReferences
.Add(
124 LoadAssembly("mscorlib", true)
127 _assemblyReferences
.Add(
128 LoadAssembly("System", true)
131 _booAssembly
= typeof(Boo
.Lang
.Builtins
).Assembly
;
132 _assemblyReferences
.Add(_booAssembly
);
133 //boo.lang.compiler.dll
134 _assemblyReferences
.Add(GetType().Assembly
);
136 if (TraceSwitch
.TraceInfo
)
138 Trace
.WriteLine("BOO LANG DLL: " + _booAssembly
.Location
);
139 Trace
.WriteLine("BOO COMPILER DLL: " + GetType().Assembly
.Location
);
143 public Assembly BooAssembly
145 get { return _booAssembly; }
150 (_assemblyReferences
as IList
).Remove(_booAssembly
);
151 _booAssembly
= value;
152 _assemblyReferences
.Add(value);
157 public Assembly
FindAssembly(string name
)
159 return _assemblyReferences
.Find(name
);
162 public void AddAssembly(Assembly asm
)
166 _assemblyReferences
.Add(asm
);
170 public Assembly
LoadAssembly(string assembly
)
172 return LoadAssembly(assembly
, true);
175 public Assembly
LoadAssembly(string assembly
, bool throwOnError
)
177 if (TraceSwitch
.TraceInfo
)
179 Trace
.WriteLine("ATTEMPTING LOADASSEMBLY: " + assembly
);
185 if (assembly
.IndexOfAny(new char[] {'/', '\\'}
) != -1)
187 //nant passes full path to gac dlls, which compiler doesn't like:
188 //if (assembly.ToLower().StartsWith(_systemDir.ToLower()))
190 //return LoadAssemblyFromGac(Path.GetFileName(assembly));
192 //else //load using path
194 a
= Assembly
.LoadFrom(assembly
);
199 a
= LoadAssemblyFromGac(assembly
);
202 catch (FileNotFoundException
/*ignored*/)
204 return LoadAssemblyFromLibPaths(assembly
, throwOnError
);
206 catch (BadImageFormatException e
)
210 throw new ApplicationException(Boo
.Lang
.ResourceManager
.Format(
215 catch (FileLoadException e
)
219 throw new ApplicationException(Boo
.Lang
.ResourceManager
.Format(
220 "BooC.UnableToLoadAssembly",
224 catch (ArgumentNullException e
)
228 throw new ApplicationException(Boo
.Lang
.ResourceManager
.Format(
229 "BooC.NullAssembly"), e
);
234 return LoadAssemblyFromLibPaths(assembly
, throwOnError
);
239 private Assembly
LoadAssemblyFromLibPaths(string assembly
, bool throwOnError
)
243 foreach (string dir
in _libpaths
)
245 string full_path
= Path
.Combine(dir
, assembly
);
246 FileInfo file
= new FileInfo(full_path
);
247 if (!_validFileExtensions
.Contains(file
.Extension
.ToLower()))
252 a
= Assembly
.LoadFrom(full_path
);
258 catch (FileNotFoundException ff
)
260 fullLog
+= ff
.FusionLog
;
266 throw new ApplicationException(Boo
.Lang
.ResourceManager
.Format(
267 "BooC.CannotFindAssembly",
269 //assembly, total_log)); //total_log contains the fusion log
274 private Assembly
LoadAssemblyFromGac(string assemblyName
)
276 assemblyName
= NormalizeAssemblyName(assemblyName
);
277 Assembly assembly
= Assembly
.LoadWithPartialName(assemblyName
);
278 if (assembly
!= null) return assembly
;
279 return Assembly
.Load(assemblyName
);
282 private static string NormalizeAssemblyName(string assembly
)
284 if (assembly
.EndsWith(".dll") || assembly
.EndsWith(".exe"))
286 assembly
= assembly
.Substring(0, assembly
.Length
- 4);
291 public void LoadReferencesFromPackage(string package
)
293 string[] libs
= Regex
.Split(pkgconfig(package
), @"\-r\:", RegexOptions
.CultureInvariant
);
294 foreach (string r
in libs
)
296 string reference
= r
.Trim();
297 if (reference
.Length
== 0) continue;
298 Trace
.WriteLine("LOADING REFERENCE FROM PKGCONFIG '" + package
+ "' : " + reference
);
299 References
.Add(LoadAssembly(reference
));
303 private static string pkgconfig(string package
)
306 throw new System
.NotSupportedException();
311 process
= Builtins
.shellp("pkg-config", string.Format("--libs {0}", package
));
315 throw new ApplicationException(Boo
.Lang
.ResourceManager
.GetString("BooC.PkgConfigNotFound"), e
);
317 process
.WaitForExit();
318 if (process
.ExitCode
!= 0)
320 throw new ApplicationException(
321 Boo
.Lang
.ResourceManager
.Format("BooC.PkgConfigReportedErrors", process
.StandardError
.ReadToEnd()));
323 return process
.StandardOutput
.ReadToEnd();
327 private string GetSystemDir()
329 return Path
.GetDirectoryName(typeof(string).Assembly
.Location
);
333 /// Max number of steps for the resolution of AST attributes.
335 public int MaxAttributeSteps
337 get { return _maxAttributeSteps; }
339 set { _maxAttributeSteps = value; }
342 public CompilerInputCollection Input
344 get { return _input; }
347 public ArrayList LibPaths
349 get { return _libpaths; }
352 public CompilerResourceCollection Resources
354 get { return _resources; }
357 public AssemblyCollection References
359 get { return _assemblyReferences; }
363 if (null == value) throw new ArgumentNullException("References");
364 _assemblyReferences
= value;
369 /// The compilation pipeline.
371 public CompilerPipeline Pipeline
373 get { return _pipeline; }
375 set { _pipeline = value; }
379 /// The name (full or partial) for the file
380 /// that should receive the resulting assembly.
382 public string OutputAssembly
384 get { return _outputAssembly; }
388 if (string.IsNullOrEmpty(value)) throw new ArgumentNullException("OutputAssembly");
389 _outputAssembly
= value;
394 /// Type and execution subsystem for the generated portable
397 public CompilerOutputType OutputType
399 get { return _outputType; }
401 set { _outputType = value; }
404 public bool GenerateInMemory
406 get { return _generateInMemory; }
408 set { _generateInMemory = value; }
413 get { return _StdLib; }
415 set { _StdLib = value; }
418 public TextWriter OutputWriter
420 get { return _outputWriter; }
426 throw new ArgumentNullException("OutputWriter");
428 _outputWriter
= value;
434 get { return _debug; }
436 set { _debug = value; }
440 /// Use duck instead of object as the most generic type.
444 get { return _ducky; }
446 set { _ducky = value; }
451 get { return _checked; }
453 set { _checked = value; }
456 public string KeyFile
458 get { return _keyFile; }
460 set { _keyFile = value; }
463 public string KeyContainer
465 get { return _keyContainer; }
467 set { _keyContainer = value; }
470 public bool DelaySign
472 get { return _delaySign; }
474 set { _delaySign = value; }
477 public bool WhiteSpaceAgnostic
481 return _whiteSpaceAgnostic
;
485 _whiteSpaceAgnostic
= value;