support for compiling Mono.Cecil without any references to System.dll
[mono.git] / mcs / class / Mono.Cecil / Mono.Cecil / BaseAssemblyResolver.cs
index 7b98b0958bdf0e46736a92b2401ab69cfd9abd58..04f2e20aebca53c4d58f8ad37cc473b2291c6a4b 100644 (file)
@@ -37,6 +37,7 @@ namespace Mono.Cecil {
        public abstract class BaseAssemblyResolver : IAssemblyResolver {
 
                ArrayList m_directories;
+               string[] m_monoGacPaths;
 
                public void AddSearchDirectory (string directory)
                {
@@ -80,7 +81,7 @@ namespace Mono.Cecil {
                                        return assembly;
                        }
 
-#if !CF_1_0 && !CF_2_0
+#if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
                        if (name.Name == "mscorlib") {
                                assembly = GetCorlib (name);
                                if (assembly != null)
@@ -119,7 +120,7 @@ namespace Mono.Cecil {
                        return version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0;
                }
 
-#if !CF_1_0 && !CF_2_0
+#if !CF_1_0 && !CF_2_0 && !NO_SYSTEM_DLL
                static AssemblyDefinition GetCorlib (AssemblyNameReference reference)
                {
                        SR.AssemblyName corlib = typeof (object).Assembly.GetName ();
@@ -131,27 +132,39 @@ namespace Mono.Cecil {
                                        typeof (object).Module.FullyQualifiedName).FullName
                                ).FullName;
 
+                       string runtime_path = null;
                        if (OnMono ()) {
                                if (reference.Version.Major == 1)
-                                       path = Path.Combine (path, "1.0");
+                                       runtime_path = "1.0";
                                else if (reference.Version.Major == 2) {
                                        if (reference.Version.Minor == 1)
-                                               path = Path.Combine (path, "2.1");
+                                               runtime_path = "2.1";
                                        else
-                                               path = Path.Combine (path, "2.0");
-                               } else
-                                       throw new NotSupportedException ("Version not supported: " + reference.Version);
+                                               runtime_path = "2.0";
+                               } else if (reference.Version.Major == 4)
+                                       runtime_path = "4.0";
                        } else {
-                               if (reference.Version.ToString () == "1.0.3300.0")
-                                       path = Path.Combine (path, "v1.0.3705");
-                               else if (reference.Version.ToString () == "1.0.5000.0")
-                                       path = Path.Combine (path, "v1.1.4322");
-                               else if (reference.Version.ToString () == "2.0.0.0")
-                                       path = Path.Combine (path, "v2.0.50727");
-                               else
-                                       throw new NotSupportedException ("Version not supported: " + reference.Version);
+                               switch (reference.Version.ToString ()) {
+                               case "1.0.3300.0":
+                                       runtime_path = "v1.0.3705";
+                                       break;
+                               case "1.0.5000.0":
+                                       runtime_path = "v1.1.4322";
+                                       break;
+                               case "2.0.0.0":
+                                       runtime_path = "v2.0.50727";
+                                       break;
+                               case "4.0.0.0":
+                                       runtime_path = "v4.0.21006";
+                                       break;
+                               }
                        }
 
+                       if (runtime_path == null)
+                               throw new NotSupportedException ("Version not supported: " + reference.Version);
+
+                       path = Path.Combine (path, runtime_path);
+
                        if (File.Exists (Path.Combine (path, "mscorlib.dll")))
                                return AssemblyFactory.GetAssembly (Path.Combine (path, "mscorlib.dll"));
 
@@ -163,17 +176,50 @@ namespace Mono.Cecil {
                        return typeof (object).Assembly.GetType ("System.MonoType", false) != null;
                }
 
-               static AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
+               string[] MonoGacPaths {
+                       get {
+                               if (m_monoGacPaths == null)
+                                       m_monoGacPaths = GetDefaultMonoGacPaths ();
+                               return m_monoGacPaths;  
+                       }
+               }
+
+               static string[] GetDefaultMonoGacPaths ()
+               {
+                       ArrayList paths = new ArrayList ();
+                       string s = GetCurrentGacPath ();
+                       if (s != null)
+                               paths.Add (s);
+                       string gacPathsEnv = Environment.GetEnvironmentVariable ("MONO_GAC_PREFIX");
+                       if (gacPathsEnv != null && gacPathsEnv.Length > 0) {
+                               string[] gacPrefixes = gacPathsEnv.Split (Path.PathSeparator);
+                               foreach (string gacPrefix in gacPrefixes) {
+                                       if (gacPrefix != null && gacPrefix.Length > 0) {
+                                               string gac = Path.Combine (Path.Combine (Path.Combine (gacPrefix, "lib"), "mono"), "gac");
+                                               if (Directory.Exists (gac) && !paths.Contains (gac))
+                                                       paths.Add (gac);
+                                       }
+                               }
+                       }
+                       return (string[]) paths.ToArray (typeof (String));
+               }
+
+               AssemblyDefinition GetAssemblyInGac (AssemblyNameReference reference)
                {
                        if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
                                return null;
 
-                       string currentGac = GetCurrentGacPath ();
                        if (OnMono ()) {
-                               string s = GetAssemblyFile (reference, currentGac);
-                               if (File.Exists (s))
-                                       return AssemblyFactory.GetAssembly (s);
+                               foreach (string gacpath in MonoGacPaths) {
+                                       string s = GetAssemblyFile (reference, gacpath);
+                                       if (File.Exists (s))
+                                               return AssemblyFactory.GetAssembly (s);
+                               }
                        } else {
+                               string currentGac = GetCurrentGacPath ();
+                               if (currentGac == null)
+                                       return null;
+
                                string [] gacs = new string [] {"GAC_MSIL", "GAC_32", "GAC"};
                                for (int i = 0; i < gacs.Length; i++) {
                                        string gac = Path.Combine (Directory.GetParent (currentGac).FullName, gacs [i]);
@@ -202,10 +248,14 @@ namespace Mono.Cecil {
 
                static string GetCurrentGacPath ()
                {
+                       string file = typeof (Uri).Module.FullyQualifiedName;
+                       if (!File.Exists (file))
+                               return null;
+
                        return Directory.GetParent (
                                Directory.GetParent (
                                        Path.GetDirectoryName (
-                                               typeof (Uri).Module.FullyQualifiedName)
+                                               file)
                                        ).FullName
                                ).FullName;
                }