2002-12-18 19:00:25 +03:00
|
|
|
/*
|
2008-01-03 12:39:12 +03:00
|
|
|
Copyright (C) 2002-2008 Jeroen Frijters
|
2002-12-18 19:00:25 +03:00
|
|
|
|
|
|
|
This software is provided 'as-is', without any express or implied
|
|
|
|
warranty. In no event will the authors be held liable for any damages
|
|
|
|
arising from the use of this software.
|
|
|
|
|
|
|
|
Permission is granted to anyone to use this software for any purpose,
|
|
|
|
including commercial applications, and to alter it and redistribute it
|
|
|
|
freely, subject to the following restrictions:
|
|
|
|
|
|
|
|
1. The origin of this software must not be misrepresented; you must not
|
|
|
|
claim that you wrote the original software. If you use this software
|
|
|
|
in a product, an acknowledgment in the product documentation would be
|
|
|
|
appreciated but is not required.
|
|
|
|
2. Altered source versions must be plainly marked as such, and must not be
|
|
|
|
misrepresented as being the original software.
|
|
|
|
3. This notice may not be removed or altered from any source distribution.
|
|
|
|
|
|
|
|
Jeroen Frijters
|
|
|
|
jeroen@frijters.net
|
|
|
|
|
|
|
|
*/
|
|
|
|
using System;
|
|
|
|
using System.Collections;
|
2004-09-15 17:35:44 +04:00
|
|
|
using System.Collections.Specialized;
|
2002-12-18 19:00:25 +03:00
|
|
|
using System.IO;
|
|
|
|
using System.Reflection;
|
2004-09-05 13:37:58 +04:00
|
|
|
using System.Threading;
|
2003-01-08 16:35:05 +03:00
|
|
|
using ICSharpCode.SharpZipLib.Zip;
|
2004-09-09 15:17:55 +04:00
|
|
|
using IKVM.Internal;
|
2002-12-18 19:00:25 +03:00
|
|
|
|
2006-04-10 13:09:09 +04:00
|
|
|
class IkvmcCompiler
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2003-12-20 01:19:18 +03:00
|
|
|
private static string manifestMainClass;
|
2006-08-29 10:28:34 +04:00
|
|
|
private static Hashtable classes = new Hashtable();
|
2004-02-02 12:46:13 +03:00
|
|
|
private static Hashtable resources = new Hashtable();
|
2007-03-11 16:31:32 +03:00
|
|
|
private static bool time;
|
2003-12-20 01:19:18 +03:00
|
|
|
|
2002-12-18 19:00:25 +03:00
|
|
|
private static ArrayList GetArgs(string[] args)
|
|
|
|
{
|
|
|
|
ArrayList arglist = new ArrayList();
|
|
|
|
foreach(string s in args)
|
|
|
|
{
|
|
|
|
if(s.StartsWith("@"))
|
|
|
|
{
|
|
|
|
using(StreamReader sr = new StreamReader(s.Substring(1)))
|
|
|
|
{
|
|
|
|
string line;
|
|
|
|
while((line = sr.ReadLine()) != null)
|
|
|
|
{
|
|
|
|
arglist.Add(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
arglist.Add(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return arglist;
|
|
|
|
}
|
|
|
|
|
2007-11-26 19:00:15 +03:00
|
|
|
static int Main(string[] args)
|
2004-05-25 11:14:39 +04:00
|
|
|
{
|
2007-03-11 16:31:32 +03:00
|
|
|
DateTime start = DateTime.Now;
|
|
|
|
int rc = RealMain(args);
|
|
|
|
if (time)
|
|
|
|
{
|
|
|
|
Console.WriteLine("Total cpu time: {0}", System.Diagnostics.Process.GetCurrentProcess().TotalProcessorTime);
|
|
|
|
Console.WriteLine("Total wall clock time: {0}", DateTime.Now - start);
|
|
|
|
}
|
2007-11-26 19:00:15 +03:00
|
|
|
return rc;
|
2004-05-25 11:14:39 +04:00
|
|
|
}
|
|
|
|
|
2006-08-17 11:33:38 +04:00
|
|
|
static string GetVersionAndCopyrightInfo()
|
|
|
|
{
|
|
|
|
Assembly asm = Assembly.GetEntryAssembly();
|
|
|
|
object[] desc = asm.GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
|
|
|
if (desc.Length == 1)
|
|
|
|
{
|
|
|
|
object[] copyright = asm.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
|
|
|
|
if (copyright.Length == 1)
|
|
|
|
{
|
|
|
|
return string.Format("{0} version {1}{2}{3}{2}http://www.ikvm.net/",
|
|
|
|
((AssemblyTitleAttribute)desc[0]).Title,
|
|
|
|
asm.GetName().Version,
|
|
|
|
Environment.NewLine,
|
|
|
|
((AssemblyCopyrightAttribute)copyright[0]).Copyright);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
|
2004-05-25 11:14:39 +04:00
|
|
|
static int RealMain(string[] args)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2005-12-07 12:06:32 +03:00
|
|
|
AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
2004-03-08 18:18:47 +03:00
|
|
|
System.Threading.Thread.CurrentThread.Name = "compiler";
|
|
|
|
Tracer.EnableTraceForDebug();
|
2006-02-23 16:20:51 +03:00
|
|
|
CompilerOptions options = new CompilerOptions();
|
2005-01-05 15:32:00 +03:00
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.ConsoleApplication;
|
|
|
|
options.guessFileKind = true;
|
|
|
|
options.version = "0.0.0.0";
|
|
|
|
options.apartment = ApartmentState.STA;
|
2004-03-08 18:18:47 +03:00
|
|
|
string defaultAssemblyName = null;
|
2003-08-21 14:06:34 +04:00
|
|
|
ArrayList classesToExclude = new ArrayList();
|
2002-12-18 19:00:25 +03:00
|
|
|
ArrayList references = new ArrayList();
|
|
|
|
ArrayList arglist = GetArgs(args);
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props = new Hashtable();
|
2002-12-18 19:00:25 +03:00
|
|
|
if(arglist.Count == 0)
|
|
|
|
{
|
2006-08-17 11:33:38 +04:00
|
|
|
Console.Error.WriteLine(GetVersionAndCopyrightInfo());
|
2006-01-31 13:13:12 +03:00
|
|
|
Console.Error.WriteLine();
|
2002-12-18 19:00:25 +03:00
|
|
|
Console.Error.WriteLine("usage: ikvmc [-options] <classOrJar1> ... <classOrJarN>");
|
|
|
|
Console.Error.WriteLine();
|
|
|
|
Console.Error.WriteLine("options:");
|
2006-07-26 18:16:52 +04:00
|
|
|
Console.Error.WriteLine(" @<filename> Read more options from file");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -out:<outputfile> Specify the output filename");
|
|
|
|
Console.Error.WriteLine(" -assembly:<name> Specify assembly name");
|
|
|
|
Console.Error.WriteLine(" -target:exe Build a console executable");
|
|
|
|
Console.Error.WriteLine(" -target:winexe Build a windows executable");
|
|
|
|
Console.Error.WriteLine(" -target:library Build a library");
|
|
|
|
Console.Error.WriteLine(" -target:module Build a module for use by the linker");
|
2008-01-03 12:39:12 +03:00
|
|
|
Console.Error.WriteLine(" -platform:<string> Limit which platforms this code can run on: x86,");
|
|
|
|
Console.Error.WriteLine(" Itanium, x64, or anycpu. The default is anycpu.");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -keyfile:<keyfilename> Use keyfile to sign the assembly");
|
2005-01-07 12:34:19 +03:00
|
|
|
Console.Error.WriteLine(" -key:<keycontainer> Use keycontainer to sign the assembly");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -version:<M.m.b.r> Assembly version");
|
2005-06-16 11:38:08 +04:00
|
|
|
Console.Error.WriteLine(" -fileversion:<version> File version");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -main:<class> Specify the class containing the main method");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -reference:<filespec> Reference an assembly (short form -r:<filespec>)");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -recurse:<filespec> Recurse directory and include matching files");
|
|
|
|
Console.Error.WriteLine(" -nojni Do not generate JNI stub for native methods");
|
|
|
|
Console.Error.WriteLine(" -resource:<name>=<path> Include file as Java resource");
|
2006-12-05 10:52:25 +03:00
|
|
|
Console.Error.WriteLine(" -externalresource:<name>=<path>");
|
|
|
|
Console.Error.WriteLine(" Reference file as Java resource");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -exclude:<filename> A file containing a list of classes to exclude");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -debug Generate debug info for the output file");
|
2005-08-12 19:18:24 +04:00
|
|
|
Console.Error.WriteLine(" (Note that this also causes the compiler to");
|
|
|
|
Console.Error.WriteLine(" generated somewhat less efficient CIL code.)");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -srcpath:<path> Prepend path and package name to source file");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -apartment:sta (default) Apply STAThreadAttribute to main");
|
|
|
|
Console.Error.WriteLine(" -apartment:mta Apply MTAThreadAttribute to main");
|
|
|
|
Console.Error.WriteLine(" -apartment:none Don't apply STAThreadAttribute to main");
|
2004-09-15 17:35:44 +04:00
|
|
|
Console.Error.WriteLine(" -noglobbing Don't glob the arguments");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -D<name>=<value> Set system property (at runtime)");
|
|
|
|
Console.Error.WriteLine(" -ea[:<packagename>...|:<classname>]");
|
|
|
|
Console.Error.WriteLine(" -enableassertions[:<packagename>...|:<classname>]");
|
|
|
|
Console.Error.WriteLine(" Set system property to enable assertions");
|
|
|
|
Console.Error.WriteLine(" -da[:<packagename>...|:<classname>]");
|
|
|
|
Console.Error.WriteLine(" -disableassertions[:<packagename>...|:<classname>]");
|
|
|
|
Console.Error.WriteLine(" Set system property to disable assertions");
|
2004-10-19 17:43:55 +04:00
|
|
|
Console.Error.WriteLine(" -nostacktraceinfo Don't create metadata to emit rich stack traces");
|
2005-01-05 15:32:00 +03:00
|
|
|
Console.Error.WriteLine(" -opt:fields Remove unused private fields");
|
2004-09-05 13:37:58 +04:00
|
|
|
Console.Error.WriteLine(" -Xtrace:<string> Displays all tracepoints with the given name");
|
2004-10-04 23:30:53 +04:00
|
|
|
Console.Error.WriteLine(" -Xmethodtrace:<string> Build tracing into the specified output methods");
|
2005-05-23 12:24:07 +04:00
|
|
|
Console.Error.WriteLine(" -compressresources Compress resources");
|
2005-07-07 17:10:09 +04:00
|
|
|
Console.Error.WriteLine(" -strictfinalfieldsemantics Don't allow final fields to be modified outside");
|
|
|
|
Console.Error.WriteLine(" of initializer methods");
|
2006-04-05 12:18:58 +04:00
|
|
|
Console.Error.WriteLine(" -privatepackage:<prefix> Mark all classes with a package name starting");
|
|
|
|
Console.Error.WriteLine(" with <prefix> as internal to the assembly");
|
2006-07-26 18:16:52 +04:00
|
|
|
Console.Error.WriteLine(" -nowarn:<warning[:key]> Suppress specified warnings");
|
2007-01-06 00:22:55 +03:00
|
|
|
Console.Error.WriteLine(" -warnaserror:<warning[:key]> Treat specified warnings as errors");
|
2007-03-11 16:31:32 +03:00
|
|
|
Console.Error.WriteLine(" -time Display timing statistics");
|
2007-10-21 11:15:40 +04:00
|
|
|
Console.Error.WriteLine(" -classloader:<class> Set custom class loader class for assembly");
|
2002-12-18 19:00:25 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
foreach(string s in arglist)
|
|
|
|
{
|
|
|
|
if(s[0] == '-')
|
|
|
|
{
|
|
|
|
if(s.StartsWith("-out:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.path = s.Substring(5);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2004-03-08 18:18:47 +03:00
|
|
|
else if(s.StartsWith("-Xtrace:"))
|
|
|
|
{
|
|
|
|
Tracer.SetTraceLevel(s.Substring(8));
|
|
|
|
}
|
|
|
|
else if(s.StartsWith("-Xmethodtrace:"))
|
|
|
|
{
|
|
|
|
Tracer.HandleMethodTrace(s.Substring(14));
|
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
else if(s.StartsWith("-assembly:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.assembly = s.Substring(10);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
else if(s.StartsWith("-target:"))
|
|
|
|
{
|
|
|
|
switch(s)
|
|
|
|
{
|
|
|
|
case "-target:exe":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.ConsoleApplication;
|
|
|
|
options.guessFileKind = false;
|
2002-12-18 19:00:25 +03:00
|
|
|
break;
|
|
|
|
case "-target:winexe":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.WindowApplication;
|
|
|
|
options.guessFileKind = false;
|
2002-12-18 19:00:25 +03:00
|
|
|
break;
|
2004-01-11 16:14:42 +03:00
|
|
|
case "-target:module":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.targetIsModule = true;
|
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.Dll;
|
|
|
|
options.guessFileKind = false;
|
2004-01-11 16:14:42 +03:00
|
|
|
break;
|
2002-12-18 19:00:25 +03:00
|
|
|
case "-target:library":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.Dll;
|
|
|
|
options.guessFileKind = false;
|
2003-12-20 01:19:18 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Console.Error.WriteLine("Warning: unrecognized option: {0}", s);
|
2002-12-18 19:00:25 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-01-03 12:39:12 +03:00
|
|
|
else if(s.StartsWith("-platform:"))
|
|
|
|
{
|
|
|
|
switch(s)
|
|
|
|
{
|
|
|
|
case "-platform:x86":
|
|
|
|
options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.Required32Bit;
|
|
|
|
options.imageFileMachine = ImageFileMachine.I386;
|
|
|
|
break;
|
|
|
|
case "-platform:Itanium":
|
|
|
|
options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.PE32Plus;
|
|
|
|
options.imageFileMachine = ImageFileMachine.IA64;
|
|
|
|
break;
|
|
|
|
case "-platform:x64":
|
|
|
|
options.pekind = PortableExecutableKinds.ILOnly | PortableExecutableKinds.PE32Plus;
|
|
|
|
options.imageFileMachine = ImageFileMachine.AMD64;
|
|
|
|
break;
|
|
|
|
case "-platform:anycpu":
|
|
|
|
options.pekind = PortableExecutableKinds.ILOnly;
|
|
|
|
options.imageFileMachine = ImageFileMachine.I386;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Console.Error.WriteLine("Warning: unrecognized option: {0}", s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-05 13:37:58 +04:00
|
|
|
else if(s.StartsWith("-apartment:"))
|
|
|
|
{
|
|
|
|
switch(s)
|
|
|
|
{
|
|
|
|
case "-apartment:sta":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.apartment = ApartmentState.STA;
|
2004-09-05 13:37:58 +04:00
|
|
|
break;
|
|
|
|
case "-apartment:mta":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.apartment = ApartmentState.MTA;
|
2004-09-05 13:37:58 +04:00
|
|
|
break;
|
|
|
|
case "-apartment:none":
|
2005-01-05 15:32:00 +03:00
|
|
|
options.apartment = ApartmentState.Unknown;
|
2004-09-05 13:37:58 +04:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
Console.Error.WriteLine("Warning: unrecognized option: {0}", s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2004-09-15 17:35:44 +04:00
|
|
|
else if(s == "-noglobbing")
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.noglobbing = true;
|
2004-09-15 17:35:44 +04:00
|
|
|
}
|
|
|
|
else if(s.StartsWith("-D"))
|
|
|
|
{
|
|
|
|
string[] keyvalue = s.Substring(2).Split('=');
|
|
|
|
if(keyvalue.Length != 2)
|
|
|
|
{
|
|
|
|
keyvalue = new string[] { keyvalue[0], "" };
|
|
|
|
}
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props[keyvalue[0]] = keyvalue[1];
|
2004-09-15 17:35:44 +04:00
|
|
|
}
|
2004-10-04 23:30:53 +04:00
|
|
|
else if(s == "-ea" || s == "-enableassertions")
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props["ikvm.assert.default"] = "true";
|
2004-10-04 23:30:53 +04:00
|
|
|
}
|
|
|
|
else if(s == "-da" || s == "-disableassertions")
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props["ikvm.assert.default"] = "false";
|
2004-10-04 23:30:53 +04:00
|
|
|
}
|
|
|
|
else if(s.StartsWith("-ea:") || s.StartsWith("-enableassertions:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props["ikvm.assert.enable"] = s.Substring(s.IndexOf(':') + 1);
|
2004-10-04 23:30:53 +04:00
|
|
|
}
|
|
|
|
else if(s.StartsWith("-da:") || s.StartsWith("-disableassertions:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.props["ikvm.assert.disable"] = s.Substring(s.IndexOf(':') + 1);
|
2004-10-04 23:30:53 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
else if(s.StartsWith("-main:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.mainClass = s.Substring(6);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2004-10-04 23:30:53 +04:00
|
|
|
else if(s.StartsWith("-reference:") || s.StartsWith("-r:"))
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2004-10-04 23:30:53 +04:00
|
|
|
string r = s.Substring(s.IndexOf(':') + 1);
|
2004-02-06 22:09:32 +03:00
|
|
|
string path = Path.GetDirectoryName(r);
|
|
|
|
string[] files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(r));
|
|
|
|
if(files.Length == 0)
|
|
|
|
{
|
2007-11-26 08:50:57 +03:00
|
|
|
#pragma warning disable 618
|
|
|
|
// Assembly.LoadWithPartialName is obsolete
|
2006-10-06 10:53:34 +04:00
|
|
|
Assembly asm = Assembly.LoadWithPartialName(r);
|
2007-11-26 08:50:57 +03:00
|
|
|
#pragma warning restore
|
2006-10-06 10:53:34 +04:00
|
|
|
if(asm == null)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: reference not found: {0}", r);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
files = new string[] { asm.Location };
|
2004-02-06 22:09:32 +03:00
|
|
|
}
|
2003-08-28 17:19:39 +04:00
|
|
|
foreach(string f in files)
|
|
|
|
{
|
|
|
|
references.Add(f);
|
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
else if(s.StartsWith("-recurse:"))
|
|
|
|
{
|
|
|
|
string spec = s.Substring(9);
|
2004-10-19 17:43:55 +04:00
|
|
|
bool exists = false;
|
|
|
|
// MONOBUG On Mono 1.0.2, Directory.Exists throws an exception if we pass an invalid directory name
|
|
|
|
try
|
|
|
|
{
|
|
|
|
exists = Directory.Exists(spec);
|
|
|
|
}
|
|
|
|
catch(IOException)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
if(exists)
|
2003-04-26 16:13:02 +04:00
|
|
|
{
|
2004-12-12 17:36:25 +03:00
|
|
|
DirectoryInfo dir = new DirectoryInfo(spec);
|
2004-02-02 12:46:13 +03:00
|
|
|
Recurse(dir, dir, "*");
|
2003-04-26 16:13:02 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-10-19 17:43:55 +04:00
|
|
|
try
|
|
|
|
{
|
2004-12-12 17:36:25 +03:00
|
|
|
DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(spec));
|
2004-10-19 17:43:55 +04:00
|
|
|
Recurse(dir, dir, Path.GetFileName(spec));
|
|
|
|
}
|
|
|
|
catch(PathTooLongException)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: path too long: {0}", spec);
|
|
|
|
return 1;
|
|
|
|
}
|
2006-10-05 12:26:27 +04:00
|
|
|
catch(DirectoryNotFoundException)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: path not found: {0}", spec);
|
|
|
|
return 1;
|
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
catch(ArgumentException)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: invalid path: {0}", spec);
|
|
|
|
return 1;
|
|
|
|
}
|
2003-04-26 16:13:02 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2003-02-25 18:43:25 +03:00
|
|
|
else if(s.StartsWith("-resource:"))
|
|
|
|
{
|
|
|
|
string[] spec = s.Substring(10).Split('=');
|
2006-08-21 09:15:51 +04:00
|
|
|
try
|
2003-02-25 18:43:25 +03:00
|
|
|
{
|
2006-08-21 09:15:51 +04:00
|
|
|
using(FileStream fs = new FileStream(spec[1], FileMode.Open, FileAccess.Read))
|
2003-02-25 18:43:25 +03:00
|
|
|
{
|
2006-08-21 09:15:51 +04:00
|
|
|
byte[] b = new byte[fs.Length];
|
|
|
|
fs.Read(b, 0, b.Length);
|
2006-09-08 11:26:26 +04:00
|
|
|
string name = spec[0];
|
|
|
|
if(name.StartsWith("/"))
|
|
|
|
{
|
|
|
|
// a leading slash is not required, so strip it
|
|
|
|
name = name.Substring(1);
|
|
|
|
}
|
|
|
|
AddResource(name, b);
|
2003-02-25 18:43:25 +03:00
|
|
|
}
|
|
|
|
}
|
2006-08-21 09:15:51 +04:00
|
|
|
catch(Exception x)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: {0}: {1}", x.Message, spec[1]);
|
|
|
|
return 1;
|
|
|
|
}
|
2003-02-25 18:43:25 +03:00
|
|
|
}
|
2006-12-05 10:52:25 +03:00
|
|
|
else if(s.StartsWith("-externalresource:"))
|
|
|
|
{
|
|
|
|
string[] spec = s.Substring(18).Split('=');
|
|
|
|
if(!File.Exists(spec[1]))
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: external resource file does not exist: {0}", spec[1]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(Path.GetFileName(spec[1]) != spec[1])
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: external resource file may not include path specification: {0}", spec[1]);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if(options.externalResources == null)
|
|
|
|
{
|
|
|
|
options.externalResources = new Hashtable();
|
|
|
|
}
|
|
|
|
// TODO resource name clashes should be tested
|
|
|
|
options.externalResources.Add(spec[0], spec[1]);
|
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
else if(s == "-nojni")
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.codegenoptions |= CodeGenOptions.NoJNI;
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2003-08-21 14:06:34 +04:00
|
|
|
else if(s.StartsWith("-exclude:"))
|
|
|
|
{
|
|
|
|
ProcessExclusionFile(classesToExclude, s.Substring(9));
|
|
|
|
}
|
2004-01-11 16:14:42 +03:00
|
|
|
else if(s.StartsWith("-version:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.version = s.Substring(9);
|
|
|
|
if(options.version.EndsWith(".*"))
|
2004-07-10 11:19:42 +04:00
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.version = options.version.Substring(0, options.version.Length - 1);
|
|
|
|
int count = options.version.Split('.').Length;
|
2004-07-10 11:19:42 +04:00
|
|
|
// NOTE this is the published algorithm for generating automatic build and revision numbers
|
|
|
|
// (see AssemblyVersionAttribute constructor docs), but it turns out that the revision
|
|
|
|
// number is off an hour (on my system)...
|
|
|
|
DateTime now = DateTime.Now;
|
|
|
|
int seconds = (int)(now.TimeOfDay.TotalSeconds / 2);
|
|
|
|
int days = (int)(now - new DateTime(2000, 1, 1)).TotalDays;
|
|
|
|
if(count == 3)
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.version += days + "." + seconds;
|
2004-07-10 11:19:42 +04:00
|
|
|
}
|
|
|
|
else if(count == 4)
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.version += seconds;
|
2004-07-10 11:19:42 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
Console.Error.WriteLine("Error: Invalid version specified: {0}*", options.version);
|
2004-07-10 11:19:42 +04:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
2004-01-11 16:14:42 +03:00
|
|
|
}
|
2005-06-16 11:38:08 +04:00
|
|
|
else if(s.StartsWith("-fileversion:"))
|
|
|
|
{
|
|
|
|
options.fileversion = s.Substring(13);
|
|
|
|
}
|
2004-01-11 16:14:42 +03:00
|
|
|
else if(s.StartsWith("-keyfile:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.keyfilename = s.Substring(9);
|
2004-01-11 16:14:42 +03:00
|
|
|
}
|
2005-01-07 12:34:19 +03:00
|
|
|
else if(s.StartsWith("-key:"))
|
|
|
|
{
|
|
|
|
options.keycontainer = s.Substring(5);
|
|
|
|
}
|
2003-08-21 14:06:34 +04:00
|
|
|
else if(s == "-debug")
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.codegenoptions |= CodeGenOptions.Debug;
|
2003-08-21 14:06:34 +04:00
|
|
|
}
|
2004-03-26 13:19:21 +03:00
|
|
|
else if(s.StartsWith("-srcpath:"))
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.sourcepath = s.Substring(9);
|
2004-03-26 13:19:21 +03:00
|
|
|
}
|
2004-03-08 18:18:47 +03:00
|
|
|
else if(s.StartsWith("-remap:"))
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.remapfile = s.Substring(7);
|
2004-03-08 18:18:47 +03:00
|
|
|
}
|
2004-10-19 17:43:55 +04:00
|
|
|
else if(s == "-nostacktraceinfo")
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.codegenoptions |= CodeGenOptions.NoStackTraceInfo;
|
2005-01-05 15:32:00 +03:00
|
|
|
}
|
|
|
|
else if(s == "-opt:fields")
|
|
|
|
{
|
|
|
|
options.removeUnusedFields = true;
|
2004-10-19 17:43:55 +04:00
|
|
|
}
|
2005-05-23 12:24:07 +04:00
|
|
|
else if(s == "-compressresources")
|
|
|
|
{
|
2006-08-30 15:13:33 +04:00
|
|
|
options.compressedResources = true;
|
2005-05-23 12:24:07 +04:00
|
|
|
}
|
2005-07-07 17:10:09 +04:00
|
|
|
else if(s == "-strictfinalfieldsemantics")
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.codegenoptions |= CodeGenOptions.StrictFinalFieldSemantics;
|
2005-07-07 17:10:09 +04:00
|
|
|
}
|
2006-04-05 12:18:58 +04:00
|
|
|
else if(s.StartsWith("-privatepackage:"))
|
|
|
|
{
|
|
|
|
string prefix = s.Substring(16);
|
|
|
|
if(options.privatePackages == null)
|
|
|
|
{
|
|
|
|
options.privatePackages = new string[] { prefix };
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
string[] temp = new string[options.privatePackages.Length + 1];
|
|
|
|
Array.Copy(options.privatePackages, 0, temp, 0, options.privatePackages.Length);
|
|
|
|
temp[temp.Length - 1] = prefix;
|
|
|
|
options.privatePackages = temp;
|
|
|
|
}
|
|
|
|
}
|
2006-07-26 18:16:52 +04:00
|
|
|
else if(s.StartsWith("-nowarn:"))
|
|
|
|
{
|
|
|
|
foreach(string w in s.Substring(8).Split(','))
|
|
|
|
{
|
|
|
|
string ws = w;
|
|
|
|
// lame way to chop off the leading zeroes
|
|
|
|
while(ws.StartsWith("0"))
|
|
|
|
{
|
|
|
|
ws = ws.Substring(1);
|
|
|
|
}
|
|
|
|
StaticCompiler.SuppressWarning(ws);
|
|
|
|
}
|
|
|
|
}
|
2007-01-06 00:22:55 +03:00
|
|
|
else if(s.StartsWith("-warnaserror:"))
|
|
|
|
{
|
|
|
|
foreach(string w in s.Substring(13).Split(','))
|
|
|
|
{
|
|
|
|
string ws = w;
|
|
|
|
// lame way to chop off the leading zeroes
|
|
|
|
while(ws.StartsWith("0"))
|
|
|
|
{
|
|
|
|
ws = ws.Substring(1);
|
|
|
|
}
|
|
|
|
StaticCompiler.WarnAsError(ws);
|
|
|
|
}
|
|
|
|
}
|
2005-12-19 18:12:49 +03:00
|
|
|
else if(s.StartsWith("-runtime:"))
|
|
|
|
{
|
|
|
|
// NOTE this is an undocumented option
|
|
|
|
options.runtimeAssembly = s.Substring(9);
|
|
|
|
}
|
2007-03-11 16:31:32 +03:00
|
|
|
else if(s == "-time")
|
|
|
|
{
|
|
|
|
time = true;
|
|
|
|
}
|
2007-10-21 11:15:40 +04:00
|
|
|
else if(s.StartsWith("-classloader:"))
|
|
|
|
{
|
|
|
|
options.classLoader = s.Substring(13);
|
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
else
|
|
|
|
{
|
2003-12-20 01:19:18 +03:00
|
|
|
Console.Error.WriteLine("Warning: unrecognized option: {0}", s);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-03-08 18:18:47 +03:00
|
|
|
if(defaultAssemblyName == null)
|
2003-12-20 01:19:18 +03:00
|
|
|
{
|
2004-05-27 11:12:04 +04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
defaultAssemblyName = new FileInfo(Path.GetFileName(s)).Name;
|
|
|
|
}
|
|
|
|
catch(ArgumentException)
|
|
|
|
{
|
|
|
|
// if the filename contains a wildcard (or any other invalid character), we ignore
|
|
|
|
// it as a potential default assembly name
|
|
|
|
}
|
2003-12-20 01:19:18 +03:00
|
|
|
}
|
2004-10-04 23:30:53 +04:00
|
|
|
string[] files;
|
|
|
|
try
|
|
|
|
{
|
|
|
|
string path = Path.GetDirectoryName(s);
|
|
|
|
files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(s));
|
|
|
|
}
|
|
|
|
catch(Exception)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: invalid filename: {0}", s);
|
|
|
|
return 1;
|
|
|
|
}
|
2003-12-20 01:19:18 +03:00
|
|
|
if(files.Length == 0)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: file not found: {0}", s);
|
|
|
|
return 1;
|
|
|
|
}
|
2003-04-26 16:13:02 +04:00
|
|
|
foreach(string f in files)
|
|
|
|
{
|
2004-02-02 12:46:13 +03:00
|
|
|
ProcessFile(null, f);
|
2003-04-26 16:13:02 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
}
|
2005-01-05 15:32:00 +03:00
|
|
|
if(options.assembly == null)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
string basename = options.path == null ? defaultAssemblyName : new FileInfo(options.path).Name;
|
2004-09-17 13:32:06 +04:00
|
|
|
if(basename == null)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine("Error: no output file specified");
|
|
|
|
return 1;
|
|
|
|
}
|
2003-12-20 01:19:18 +03:00
|
|
|
int idx = basename.LastIndexOf('.');
|
2002-12-18 19:00:25 +03:00
|
|
|
if(idx > 0)
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.assembly = basename.Substring(0, idx);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.assembly = basename;
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
}
|
2005-01-05 15:32:00 +03:00
|
|
|
if(options.path != null && options.guessFileKind)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
if(options.path.ToLower().EndsWith(".dll"))
|
2003-12-20 01:19:18 +03:00
|
|
|
{
|
2005-01-05 15:32:00 +03:00
|
|
|
options.target = System.Reflection.Emit.PEFileKinds.Dll;
|
2003-12-20 01:19:18 +03:00
|
|
|
}
|
2005-01-05 15:32:00 +03:00
|
|
|
options.guessFileKind = false;
|
2003-12-20 01:19:18 +03:00
|
|
|
}
|
2005-01-05 15:32:00 +03:00
|
|
|
if(options.mainClass == null && manifestMainClass != null && (options.guessFileKind || options.target != System.Reflection.Emit.PEFileKinds.Dll))
|
2003-12-20 01:19:18 +03:00
|
|
|
{
|
2006-07-26 18:16:52 +04:00
|
|
|
StaticCompiler.IssueMessage(Message.MainMethodFromManifest, manifestMainClass);
|
2005-01-05 15:32:00 +03:00
|
|
|
options.mainClass = manifestMainClass;
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2003-02-20 17:18:38 +03:00
|
|
|
try
|
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
options.classes = classes;
|
2005-01-05 15:32:00 +03:00
|
|
|
options.references = (string[])references.ToArray(typeof(string));
|
|
|
|
options.resources = resources;
|
|
|
|
options.classesToExclude = (string[])classesToExclude.ToArray(typeof(string));
|
2006-08-31 13:22:10 +04:00
|
|
|
return CompilerClassLoader.Compile(options);
|
2003-02-20 17:18:38 +03:00
|
|
|
}
|
|
|
|
catch(Exception x)
|
|
|
|
{
|
|
|
|
Console.Error.WriteLine(x);
|
|
|
|
return 1;
|
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
|
2003-01-08 16:35:05 +03:00
|
|
|
private static byte[] ReadFromZip(ZipFile zf, ZipEntry ze)
|
|
|
|
{
|
|
|
|
byte[] buf = new byte[ze.Size];
|
|
|
|
int pos = 0;
|
|
|
|
Stream s = zf.GetInputStream(ze);
|
|
|
|
while(pos < buf.Length)
|
|
|
|
{
|
|
|
|
pos += s.Read(buf, pos, buf.Length - pos);
|
|
|
|
}
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
2006-08-29 10:28:34 +04:00
|
|
|
private static void AddClassFile(string filename, byte[] buf, bool addResourceFallback)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
string name = ClassFile.GetClassName(buf, 0, buf.Length);
|
|
|
|
if(classes.ContainsKey(name))
|
|
|
|
{
|
|
|
|
StaticCompiler.IssueMessage(Message.DuplicateClassName, name);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
classes.Add(name, buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(ClassFormatError x)
|
|
|
|
{
|
|
|
|
if(addResourceFallback)
|
|
|
|
{
|
|
|
|
// not a class file, so we include it as a resource
|
|
|
|
// (IBM's db2os390/sqlj jars apparantly contain such files)
|
|
|
|
StaticCompiler.IssueMessage(Message.NotAClassFile, filename, x.Message);
|
|
|
|
AddResource(filename, buf);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
StaticCompiler.IssueMessage(Message.ClassFormatError, filename, x.Message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-02 12:46:13 +03:00
|
|
|
private static void ProcessZipFile(string file)
|
|
|
|
{
|
|
|
|
ZipFile zf = new ZipFile(file);
|
|
|
|
try
|
|
|
|
{
|
|
|
|
foreach(ZipEntry ze in zf)
|
|
|
|
{
|
2005-05-17 17:18:16 +04:00
|
|
|
if(ze.IsDirectory)
|
|
|
|
{
|
|
|
|
// skip
|
|
|
|
}
|
|
|
|
else if(ze.Name.ToLower().EndsWith(".class"))
|
2004-02-02 12:46:13 +03:00
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
AddClassFile(ze.Name, ReadFromZip(zf, ze), true);
|
2004-02-02 12:46:13 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// if it's not a class, we treat it as a resource and the manifest
|
|
|
|
// is examined to find the Main-Class
|
|
|
|
if(ze.Name == "META-INF/MANIFEST.MF" && manifestMainClass == null)
|
|
|
|
{
|
|
|
|
// read main class from manifest
|
|
|
|
// TODO find out if we can use other information from manifest
|
|
|
|
StreamReader rdr = new StreamReader(zf.GetInputStream(ze));
|
|
|
|
string line;
|
|
|
|
while((line = rdr.ReadLine()) != null)
|
|
|
|
{
|
|
|
|
if(line.StartsWith("Main-Class: "))
|
|
|
|
{
|
2004-11-04 15:50:28 +03:00
|
|
|
manifestMainClass = line.Substring(12).Replace('/', '.');
|
2004-02-02 12:46:13 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-21 09:15:51 +04:00
|
|
|
AddResource(ze.Name, ReadFromZip(zf, ze));
|
2004-02-02 12:46:13 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally
|
|
|
|
{
|
|
|
|
zf.Close();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-05-23 12:24:07 +04:00
|
|
|
private static void AddResource(string name, byte[] buf)
|
|
|
|
{
|
2006-08-21 09:15:51 +04:00
|
|
|
if(resources.ContainsKey(name))
|
2005-05-23 12:24:07 +04:00
|
|
|
{
|
2006-08-21 09:15:51 +04:00
|
|
|
StaticCompiler.IssueMessage(Message.DuplicateResourceName, name);
|
2005-05-23 12:24:07 +04:00
|
|
|
}
|
2006-08-21 09:15:51 +04:00
|
|
|
else
|
|
|
|
{
|
|
|
|
resources.Add(name, buf);
|
|
|
|
}
|
2005-05-23 12:24:07 +04:00
|
|
|
}
|
|
|
|
|
2004-02-02 12:46:13 +03:00
|
|
|
private static void ProcessFile(DirectoryInfo baseDir, string file)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2003-04-26 16:13:02 +04:00
|
|
|
switch(new FileInfo(file).Extension.ToLower())
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2003-04-26 16:13:02 +04:00
|
|
|
case ".class":
|
2005-08-29 11:26:05 +04:00
|
|
|
using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
2006-08-29 10:28:34 +04:00
|
|
|
byte[] buf = new byte[fs.Length];
|
|
|
|
fs.Read(buf, 0, buf.Length);
|
|
|
|
AddClassFile(file, buf, false);
|
2003-04-26 16:13:02 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case ".jar":
|
|
|
|
case ".zip":
|
|
|
|
try
|
|
|
|
{
|
2004-02-02 12:46:13 +03:00
|
|
|
ProcessZipFile(file);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
2005-10-01 15:16:11 +04:00
|
|
|
catch(ICSharpCode.SharpZipLib.SharpZipBaseException x)
|
2003-04-26 16:13:02 +04:00
|
|
|
{
|
2004-02-02 12:46:13 +03:00
|
|
|
Console.Error.WriteLine("Warning: error reading {0}: {1}", file, x.Message);
|
2003-04-26 16:13:02 +04:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2003-08-08 16:37:14 +04:00
|
|
|
{
|
|
|
|
if(baseDir == null)
|
|
|
|
{
|
2003-12-20 01:19:18 +03:00
|
|
|
Console.Error.WriteLine("Warning: unknown file type: {0}", file);
|
2003-08-08 16:37:14 +04:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// include as resource
|
2003-08-21 14:06:34 +04:00
|
|
|
try
|
2003-08-08 16:37:14 +04:00
|
|
|
{
|
2005-08-29 11:26:05 +04:00
|
|
|
using(FileStream fs = new FileStream(file, FileMode.Open, FileAccess.Read))
|
2003-08-21 14:06:34 +04:00
|
|
|
{
|
|
|
|
byte[] b = new byte[fs.Length];
|
|
|
|
fs.Read(b, 0, b.Length);
|
2004-12-12 17:36:25 +03:00
|
|
|
// extract the resource name by chopping off the base directory
|
2004-03-16 20:10:09 +03:00
|
|
|
string name = file.Substring(baseDir.FullName.Length);
|
2004-12-12 17:36:25 +03:00
|
|
|
if(name.Length > 0 && name[0] == Path.DirectorySeparatorChar)
|
|
|
|
{
|
|
|
|
name = name.Substring(1);
|
|
|
|
}
|
2003-08-21 14:06:34 +04:00
|
|
|
name = name.Replace('\\', '/');
|
2005-05-23 12:24:07 +04:00
|
|
|
AddResource(name, b);
|
2003-08-21 14:06:34 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(UnauthorizedAccessException)
|
|
|
|
{
|
2003-12-20 01:19:18 +03:00
|
|
|
Console.Error.WriteLine("Warning: error reading file {0}: Access Denied", file);
|
2003-08-08 16:37:14 +04:00
|
|
|
}
|
|
|
|
}
|
2003-04-26 16:13:02 +04:00
|
|
|
break;
|
2003-08-08 16:37:14 +04:00
|
|
|
}
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-02-02 12:46:13 +03:00
|
|
|
private static void Recurse(DirectoryInfo baseDir, DirectoryInfo dir, string spec)
|
2002-12-18 19:00:25 +03:00
|
|
|
{
|
|
|
|
foreach(FileInfo file in dir.GetFiles(spec))
|
|
|
|
{
|
2004-02-02 12:46:13 +03:00
|
|
|
ProcessFile(baseDir, file.FullName);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
foreach(DirectoryInfo sub in dir.GetDirectories())
|
|
|
|
{
|
2004-02-02 12:46:13 +03:00
|
|
|
Recurse(baseDir, sub, spec);
|
2002-12-18 19:00:25 +03:00
|
|
|
}
|
|
|
|
}
|
2003-08-21 14:06:34 +04:00
|
|
|
|
|
|
|
//This processes an exclusion file with a single regular expression per line
|
|
|
|
private static void ProcessExclusionFile(ArrayList classesToExclude, String filename)
|
|
|
|
{
|
|
|
|
try
|
|
|
|
{
|
|
|
|
using(StreamReader file = new StreamReader(filename))
|
|
|
|
{
|
|
|
|
String line;
|
|
|
|
while((line = file.ReadLine()) != null)
|
|
|
|
{
|
|
|
|
line = line.Trim();
|
|
|
|
if(!line.StartsWith("//") && line.Length != 0)
|
|
|
|
{
|
|
|
|
classesToExclude.Add(line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(FileNotFoundException)
|
|
|
|
{
|
2003-12-20 01:19:18 +03:00
|
|
|
Console.Error.WriteLine("Warning: could not find exclusion file '{0}'", filename);
|
2003-08-21 14:06:34 +04:00
|
|
|
}
|
|
|
|
}
|
2004-03-16 20:10:09 +03:00
|
|
|
|
|
|
|
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
|
|
|
{
|
|
|
|
// make sure all the referenced assemblies are visible (they are loaded with LoadFrom, so
|
|
|
|
// they end up in the LoadFrom context [unless they happen to be available in one of the probe paths])
|
2005-12-07 12:06:32 +03:00
|
|
|
foreach(Assembly a in AppDomain.CurrentDomain.ReflectionOnlyGetAssemblies())
|
2004-03-16 20:10:09 +03:00
|
|
|
{
|
2005-12-07 12:06:32 +03:00
|
|
|
if(args.Name.StartsWith(a.GetName().Name + ", "))
|
2004-03-16 20:10:09 +03:00
|
|
|
{
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
}
|
2007-01-06 10:11:25 +03:00
|
|
|
return Assembly.ReflectionOnlyLoad(args.Name);
|
2005-05-23 12:24:07 +04:00
|
|
|
}
|
|
|
|
}
|