diff --git a/ikvmc.8.csproj b/ikvmc.8.csproj
index 06b643f0..a00c8623 100644
--- a/ikvmc.8.csproj
+++ b/ikvmc.8.csproj
@@ -71,6 +71,7 @@
Code
+
Code
diff --git a/ikvmc/AssemblyResolver.cs b/ikvmc/AssemblyResolver.cs
new file mode 100644
index 00000000..85556d45
--- /dev/null
+++ b/ikvmc/AssemblyResolver.cs
@@ -0,0 +1,294 @@
+/*
+ Copyright (C) 2010 Jeroen Frijters
+
+ 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.Generic;
+using System.Text;
+using System.IO;
+using IKVM.Reflection;
+
+namespace IKVM.Internal
+{
+ sealed class AssemblyResolver
+ {
+ private readonly List libpath = new List();
+ private Universe universe;
+
+ internal int Init(Universe universe, bool nostdlib, IList references, IList userLibPaths)
+ {
+ this.universe = universe;
+ // like the C# compiler, the references are loaded from:
+ // current directory, CLR directory, -lib: option, %LIB% environment
+ // (note that, unlike the C# compiler, we don't add the CLR directory if -nostdlib has been specified)
+ libpath.Add(Environment.CurrentDirectory);
+ if (!nostdlib)
+ {
+ libpath.Add(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory());
+ }
+ foreach (string str in userLibPaths)
+ {
+ AddLibraryPaths(str, "-lib option");
+ }
+ AddLibraryPaths(Environment.GetEnvironmentVariable("LIB") ?? "", "LIB environment");
+ int rc = 0;
+ if (nostdlib)
+ {
+ rc = LoadMscorlib(references);
+ }
+ if (rc == 0)
+ {
+ universe.AssemblyResolve += new IKVM.Reflection.ResolveEventHandler(universe_AssemblyResolve);
+ }
+ return rc;
+ }
+
+ internal Assembly LoadWithPartialName(string name)
+ {
+ foreach (string path in FindAssemblyPath(name + ".dll"))
+ {
+ return universe.LoadFile(path);
+ }
+ return null;
+ }
+
+ internal int ResolveReference(Dictionary cache, ref Assembly[] references, string reference)
+ {
+ string[] files = new string[0];
+ try
+ {
+ string path = Path.GetDirectoryName(reference);
+ files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(reference));
+ }
+ catch (ArgumentException)
+ {
+ }
+ catch (IOException)
+ {
+ }
+ if (files.Length == 0)
+ {
+ Assembly asm = null;
+ cache.TryGetValue(reference, out asm);
+ try
+ {
+ if (asm == null)
+ {
+ foreach (string found in FindAssemblyPath(reference))
+ {
+ asm = StaticCompiler.LoadFile(found);
+ cache.Add(reference, asm);
+ break;
+ }
+ }
+ }
+ catch (FileLoadException)
+ {
+ }
+ if (asm == null)
+ {
+ Console.Error.WriteLine("Error: reference not found: {0}", reference);
+ return 1;
+ }
+ ArrayAppend(ref references, asm);
+ }
+ else
+ {
+ foreach (string file in files)
+ {
+ try
+ {
+ Assembly asm;
+ if (!cache.TryGetValue(file, out asm))
+ {
+ asm = StaticCompiler.LoadFile(file);
+ }
+ ArrayAppend(ref references, asm);
+ }
+ catch (FileLoadException)
+ {
+ Console.Error.WriteLine("Error: reference not found: {0}", file);
+ return 1;
+ }
+ }
+ }
+ return 0;
+ }
+
+ private static void ArrayAppend(ref T[] array, T element)
+ {
+ if (array == null)
+ {
+ array = new T[] { element };
+ }
+ else
+ {
+ T[] temp = new T[array.Length + 1];
+ Array.Copy(array, 0, temp, 0, array.Length);
+ temp[temp.Length - 1] = element;
+ array = temp;
+ }
+ }
+
+ private Assembly universe_AssemblyResolve(object sender, IKVM.Reflection.ResolveEventArgs args)
+ {
+ // to support Universe.GetType("System.Object, mscorlib"), we have to support partial names
+ // (the map.xml file contains such type names)
+ bool partialName = !args.Name.Contains(",");
+ AssemblyName name = new AssemblyName(args.Name);
+ foreach (string file in FindAssemblyPath(name.Name + ".dll"))
+ {
+ Assembly asm = StaticCompiler.LoadFile(file);
+ if (Matches(asm.GetName(), name) || partialName)
+ {
+ return asm;
+ }
+ }
+ if (args.RequestingAssembly != null)
+ {
+ string path = Path.Combine(Path.GetDirectoryName(args.RequestingAssembly.Location), name.Name + ".dll");
+ if (File.Exists(path) && Matches(AssemblyName.GetAssemblyName(path), name))
+ {
+ return StaticCompiler.LoadFile(path);
+ }
+ }
+ Console.Error.WriteLine("Error: unable to find assembly '{0}'", args.Name);
+ if (args.RequestingAssembly != null)
+ {
+ Console.Error.WriteLine(" (a dependency of '{0}')", args.RequestingAssembly.FullName);
+ }
+ Environment.Exit(1);
+ return null;
+ }
+
+ private static bool Matches(AssemblyName assemblyDef, AssemblyName assemblyRef)
+ {
+ if (assemblyDef.Name != assemblyRef.Name)
+ {
+ return false;
+ }
+ bool strongNamed = IsStrongNamed(assemblyDef);
+ if (strongNamed != IsStrongNamed(assemblyRef))
+ {
+ return false;
+ }
+ if (strongNamed)
+ {
+ return IsEqual(assemblyDef.GetPublicKeyToken(), assemblyRef.GetPublicKeyToken()) && assemblyDef.Version >= assemblyRef.Version;
+ }
+ return true;
+ }
+
+ private static bool IsStrongNamed(AssemblyName name)
+ {
+ byte[] key = name.GetPublicKeyToken();
+ return key != null && key.Length != 0;
+ }
+
+ private static bool IsEqual(byte[] b1, byte[] b2)
+ {
+ if (b1.Length != b2.Length)
+ {
+ return false;
+ }
+ for (int i = 0; i < b1.Length; i++)
+ {
+ if (b1[i] != b2[i])
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void AddLibraryPaths(string str, string msg)
+ {
+ foreach (string dir in str.Split(Path.PathSeparator))
+ {
+ if (Directory.Exists(dir))
+ {
+ libpath.Add(dir);
+ }
+ else if (dir != "")
+ {
+ Console.Error.WriteLine("Warning: directory '{0}' specified in {1} is not valid", dir, msg);
+ }
+ }
+ }
+
+ private int LoadMscorlib(IList references)
+ {
+ Universe dummy = new Universe();
+ foreach (string r in references)
+ {
+ try
+ {
+ Assembly asm = dummy.LoadFile(r);
+ if (asm.GetType("System.Object") != null)
+ {
+ StaticCompiler.Universe.LoadMscorlib(r);
+ return 0;
+ }
+ }
+ catch
+ {
+ }
+ }
+ foreach (string mscorlib in FindAssemblyPath("mscorlib.dll"))
+ {
+ StaticCompiler.Universe.LoadMscorlib(mscorlib);
+ return 0;
+ }
+ Console.Error.WriteLine("Error: unable to find mscorlib.dll");
+ return 1;
+ }
+
+ private IEnumerable FindAssemblyPath(string file)
+ {
+ if (Path.IsPathRooted(file))
+ {
+ if (File.Exists(file))
+ {
+ yield return file;
+ }
+ }
+ else
+ {
+ foreach (string dir in libpath)
+ {
+ string path = Path.Combine(dir, file);
+ if (File.Exists(path))
+ {
+ yield return path;
+ }
+ // for legacy compat, we try again after appending .dll
+ path = Path.Combine(dir, file + ".dll");
+ if (File.Exists(path))
+ {
+ Console.WriteLine("Warning: Found assembly '{0}' using legacy search rule. Please append '.dll' to the reference.", file);
+ yield return path;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/ikvmc/Compiler.cs b/ikvmc/Compiler.cs
index 52f0ba46..2d35fad6 100644
--- a/ikvmc/Compiler.cs
+++ b/ikvmc/Compiler.cs
@@ -44,6 +44,9 @@ class IkvmcCompiler
private List classesToExclude = new List();
private static bool time;
private static string runtimeAssembly;
+ private static bool nostdlib;
+ private static readonly List libpaths = new List();
+ private static readonly AssemblyResolver loader = new AssemblyResolver();
private static List GetArgs(string[] args)
{
@@ -76,7 +79,6 @@ class IkvmcCompiler
static int Main(string[] args)
{
DateTime start = DateTime.Now;
- StaticCompiler.Universe.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
System.Threading.Thread.CurrentThread.Name = "compiler";
Tracer.EnableTraceConsoleListener();
Tracer.EnableTraceForDebug();
@@ -88,7 +90,12 @@ class IkvmcCompiler
}
IkvmcCompiler comp = new IkvmcCompiler();
List targets = new List();
- int rc = comp.ParseCommandLine(argList.GetEnumerator(), targets);
+ CompilerOptions toplevel = new CompilerOptions();
+ int rc = comp.ParseCommandLine(argList.GetEnumerator(), targets, toplevel);
+ if (rc == 0)
+ {
+ loader.Init(StaticCompiler.Universe, nostdlib, toplevel.unresolvedReferences, libpaths);
+ }
if (rc == 0)
{
rc = ResolveReferences(targets);
@@ -207,11 +214,12 @@ class IkvmcCompiler
Console.Error.WriteLine(" class loader");
Console.Error.WriteLine(" -baseaddress: Base address for the library to be built");
Console.Error.WriteLine(" -nopeercrossreference Do not automatically cross reference all peers");
+ Console.Error.WriteLine(" -nostdlib Do not reference standard libraries");
+ Console.Error.WriteLine(" -lib: Additional directories to search for references");
}
- int ParseCommandLine(IEnumerator arglist, List targets)
+ int ParseCommandLine(IEnumerator arglist, List targets, CompilerOptions options)
{
- CompilerOptions options = new CompilerOptions();
options.target = PEFileKinds.ConsoleApplication;
options.guessFileKind = true;
options.version = new Version(0, 0, 0, 0);
@@ -613,6 +621,16 @@ class IkvmcCompiler
{
options.crossReferenceAllPeers = false;
}
+ else if(s=="-nostdlib")
+ {
+ // this is a global option
+ nostdlib = true;
+ }
+ else if(s.StartsWith("-lib:"))
+ {
+ // this is a global option
+ libpaths.Add(s.Substring(5));
+ }
else
{
Console.Error.WriteLine("Warning: unrecognized option: {0}", s);
@@ -778,7 +796,7 @@ class IkvmcCompiler
goto next_reference;
}
}
- int rc = ResolveReferences(cache, ref target.references, reference);
+ int rc = loader.ResolveReference(cache, ref target.references, reference);
if (rc != 0)
{
return rc;
@@ -790,72 +808,6 @@ class IkvmcCompiler
return 0;
}
- private static int ResolveReferences(Dictionary cache, ref Assembly[] references, string r)
- {
- string[] files = new string[0];
- try
- {
- string path = Path.GetDirectoryName(r);
- files = Directory.GetFiles(path == "" ? "." : path, Path.GetFileName(r));
- }
- catch (ArgumentException)
- {
- }
- catch (IOException)
- {
- }
- if (files.Length == 0)
- {
- Assembly asm = null;
- cache.TryGetValue(r, out asm);
- try
- {
- if (asm == null)
- {
-#pragma warning disable 618
- // Assembly.LoadWithPartialName is obsolete
- System.Reflection.Assembly found = System.Reflection.Assembly.LoadWithPartialName(r);
-#pragma warning restore
- if (found != null)
- {
- asm = StaticCompiler.LoadFile(found.Location);
- cache.Add(r, asm);
- }
- }
- }
- catch (FileLoadException)
- {
- }
- if (asm == null)
- {
- Console.Error.WriteLine("Error: reference not found: {0}", r);
- return 1;
- }
- ArrayAppend(ref references, asm);
- }
- else
- {
- foreach (string file in files)
- {
- try
- {
- Assembly asm;
- if (!cache.TryGetValue(file, out asm))
- {
- asm = StaticCompiler.LoadFile(file);
- }
- ArrayAppend(ref references, asm);
- }
- catch (FileLoadException)
- {
- Console.Error.WriteLine("Error: reference not found: {0}", file);
- return 1;
- }
- }
- }
- return 0;
- }
-
private static void ArrayAppend(ref T[] array, T element)
{
if (array == null)
@@ -1092,77 +1044,4 @@ class IkvmcCompiler
Console.Error.WriteLine("Warning: could not find exclusion file '{0}'", filename);
}
}
-
- // this method checks if the assembly was loaded from a CLR probe location
- // (in that case we can also resolve its dependencies via the CLR)
- private static bool IsLoadedFromCurrentClrProbeLocation(Assembly asm)
- {
- try
- {
- // we have to use StringComparison.OrdinalIgnoreCase, because it the CLR sometimes appends ".dll"
- // and other times ".DLL" (when the assembly is loaded from DEVPATH)
- return System.Reflection.Assembly.ReflectionOnlyLoad(asm.FullName).Location.Equals(asm.Location, StringComparison.OrdinalIgnoreCase);
- }
- catch
- {
- return false;
- }
- }
-
- private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
- {
- if (args.RequestingAssembly == null || IsLoadedFromCurrentClrProbeLocation(args.RequestingAssembly))
- {
- System.Reflection.Assembly asm = null;
- try
- {
- asm = System.Reflection.Assembly.ReflectionOnlyLoad(args.Name);
- }
- catch
- {
- }
- if (asm != null)
- {
- return StaticCompiler.LoadFile(asm.Location);
- }
- }
- else
- {
- // apply unification and policy
- try
- {
- string name = System.Reflection.Assembly.ReflectionOnlyLoad(args.Name).FullName;
- if (name != args.Name)
- {
- return StaticCompiler.Load(name);
- }
- }
- catch
- {
- }
- // HACK support loading additional assemblies from a multi assembly group from the same location as the main assembly
- Type main = args.RequestingAssembly.GetType("__");
- if (main != null)
- {
- try
- {
- string path = Path.Combine(Path.GetDirectoryName(main.Assembly.Location), new AssemblyName(args.Name).Name + ".dll");
- if (AssemblyName.GetAssemblyName(path).FullName == args.Name)
- {
- return StaticCompiler.LoadFile(path);
- }
- }
- catch
- {
- }
- }
- }
- Console.Error.WriteLine("Error: unable to find assembly '{0}'", args.Name);
- if (args.RequestingAssembly != null)
- {
- Console.Error.WriteLine(" (a dependency of '{0}')", args.RequestingAssembly.FullName);
- }
- Environment.Exit(1);
- return null;
- }
}
diff --git a/ikvmc/ikvmc.build b/ikvmc/ikvmc.build
index 9470185a..78455869 100644
--- a/ikvmc/ikvmc.build
+++ b/ikvmc/ikvmc.build
@@ -13,6 +13,7 @@
+
diff --git a/ikvmstub/ikvmstub.8.csproj b/ikvmstub/ikvmstub.8.csproj
index 5b8be175..74ac0956 100644
--- a/ikvmstub/ikvmstub.8.csproj
+++ b/ikvmstub/ikvmstub.8.csproj
@@ -73,6 +73,7 @@
Code
+
Code
diff --git a/ikvmstub/ikvmstub.build b/ikvmstub/ikvmstub.build
index eb1f5b1e..387837a7 100644
--- a/ikvmstub/ikvmstub.build
+++ b/ikvmstub/ikvmstub.build
@@ -8,6 +8,7 @@
+
diff --git a/ikvmstub/ikvmstub.cs b/ikvmstub/ikvmstub.cs
index b6de9510..6b5236e9 100644
--- a/ikvmstub/ikvmstub.cs
+++ b/ikvmstub/ikvmstub.cs
@@ -29,8 +29,6 @@ using IKVM.Attributes;
using IKVM.Internal;
using IKVM.Reflection;
using Type = IKVM.Reflection.Type;
-using ResolveEventArgs = IKVM.Reflection.ResolveEventArgs;
-using ResolveEventHandler = IKVM.Reflection.ResolveEventHandler;
static class NetExp
{
@@ -48,6 +46,9 @@ static class NetExp
string assemblyNameOrPath = null;
bool continueOnError = false;
bool autoLoadSharedClassLoaderAssemblies = false;
+ List references = new List();
+ List libpaths = new List();
+ bool nostdlib = false;
foreach(string s in args)
{
if(s.StartsWith("-") || assemblyNameOrPath != null)
@@ -66,17 +67,15 @@ static class NetExp
}
else if(s.StartsWith("-r:") || s.StartsWith("-reference:"))
{
- string path = s.Substring(s.IndexOf(':') + 1);
- try
- {
- StaticCompiler.Universe.LoadFile(path);
- }
- catch (Exception x)
- {
- Console.Error.WriteLine("Error: unable to load reference {0}", path);
- Console.Error.WriteLine(" ({0})", x.Message);
- return 1;
- }
+ references.Add(s.Substring(s.IndexOf(':') + 1));
+ }
+ else if(s == "-nostdlib")
+ {
+ nostdlib = true;
+ }
+ else if(s.StartsWith("-lib:"))
+ {
+ libpaths.Add(s.Substring(5));
}
else
{
@@ -94,9 +93,21 @@ static class NetExp
{
Console.Error.WriteLine(GetVersionAndCopyrightInfo());
Console.Error.WriteLine();
- Console.Error.WriteLine("usage: ikvmstub [-serialver] [-skiperror] ");
+ Console.Error.WriteLine("usage: ikvmstub [-serialver] [-skiperror] [-reference:] [-lib:] ");
return 1;
}
+ AssemblyResolver resolver = new AssemblyResolver();
+ resolver.Init(StaticCompiler.Universe, nostdlib, references, libpaths);
+ Dictionary cache = new Dictionary();
+ foreach (string reference in references)
+ {
+ Assembly[] dummy = null;
+ int rc1 = resolver.ResolveReference(cache, ref dummy, reference);
+ if (rc1 != 0)
+ {
+ return rc1;
+ }
+ }
Assembly assembly = null;
try
{
@@ -109,19 +120,11 @@ static class NetExp
}
if(file != null && file.Exists)
{
- StaticCompiler.Universe.AssemblyResolve += new ResolveEventHandler(Universe_AssemblyResolve);
assembly = StaticCompiler.LoadFile(assemblyNameOrPath);
}
else
{
-#pragma warning disable 618
- // Assembly.LoadWithPartialName is obsolete
- System.Reflection.Assembly asm = System.Reflection.Assembly.LoadWithPartialName(assemblyNameOrPath);
-#pragma warning restore
- if (asm != null)
- {
- assembly = StaticCompiler.Universe.LoadFile(asm.Location);
- }
+ assembly = resolver.LoadWithPartialName(assemblyNameOrPath);
}
int rc = 0;
if(assembly == null)
@@ -244,29 +247,6 @@ static class NetExp
}
}
- private static Assembly Universe_AssemblyResolve(object sender, ResolveEventArgs args)
- {
- string path = args.Name;
- int index = path.IndexOf(',');
- if (index > 0)
- {
- path = path.Substring(0, index);
- }
- path = file.DirectoryName + Path.DirectorySeparatorChar + path + ".dll";
- if (File.Exists(path))
- {
- return StaticCompiler.LoadFile(path);
- }
- try
- {
- return StaticCompiler.LoadFile(System.Reflection.Assembly.Load(args.Name).Location);
- }
- catch
- {
- }
- return null;
- }
-
private static void WriteClass(TypeWrapper tw)
{
string name = tw.Name.Replace('.', '/');
diff --git a/openjdk/openjdk.build b/openjdk/openjdk.build
index 9b03f944..3823f7e6 100644
--- a/openjdk/openjdk.build
+++ b/openjdk/openjdk.build
@@ -47,7 +47,7 @@
-
+
@@ -74,7 +74,7 @@
-
+
@@ -165,6 +165,7 @@
+
@@ -183,7 +184,6 @@
-