Esempio n. 1
0
        public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
        {
            Assembly core = base.Resolve(context, assemblyName);

            if (core != null)
            {
                return(core);
            }

            ReadOnlySpan <byte> pktFromAssemblyName = assemblyName.GetPublicKeyToken();

            foreach (Assembly assembly in context.GetAssemblies())
            {
                AssemblyName assemblyNameFromContext = assembly.GetName();
                if (assemblyName.Name.Equals(assemblyNameFromContext.Name, StringComparison.OrdinalIgnoreCase) &&
                    NormalizeVersion(assemblyName.Version).Equals(assemblyNameFromContext.Version) &&
                    pktFromAssemblyName.SequenceEqual(assemblyNameFromContext.GetPublicKeyToken()) &&
                    NormalizeCultureName(assemblyName.CultureName).Equals(NormalizeCultureName(assemblyNameFromContext.CultureName)))
                {
                    return(assembly);
                }
            }

            return(null);
        }
Esempio n. 2
0
        public static void GetAssemblies()
        {
            using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
            {
                Assembly[] loadedAssemblies = lc.GetAssemblies().ToArray();
                Assert.Equal(1, loadedAssemblies.Length);

                // EmptyCoreMetadataAssemblyResolver already loaded s_SimpleNameOnlyImage
                Assembly a1 = lc.LoadFromByteArray(TestData.s_SimpleAssemblyImage);
                Assembly a2 = lc.LoadFromByteArray(TestData.s_SimpleNameOnlyImage);
                loadedAssemblies = lc.GetAssemblies().ToArray();
                Assert.Equal(2, loadedAssemblies.Length);
                Assert.Contains <Assembly>(a1, loadedAssemblies);
                Assert.Contains <Assembly>(a2, loadedAssemblies);
            }
        }
Esempio n. 3
0
    public override Assembly?Resolve(MetadataLoadContext context, AssemblyName assemblyName)
    {
        string?name = assemblyName.Name;

        if (name != null)
        {
            foreach (var asm in context.GetAssemblies())
            {
                if (asm.GetName().Name == name)
                {
                    return(asm);
                }
            }

            string dllName = name + ".dll";
            foreach (var libraryPath in libraryPaths)
            {
                string path = Path.Combine(libraryPath, dllName);
                if (File.Exists(path))
                {
                    return(context.LoadFromAssemblyPath(path));
                }
            }
            foreach (var reference in references)
            {
                if (Path.GetFileName(reference).Equals(dllName, StringComparison.OrdinalIgnoreCase))
                {
                    return(context.LoadFromAssemblyPath(reference));
                }
            }
        }
        return(null);
    }
Esempio n. 4
0
    private List <Assembly> LoadReferencedAssembliesMetadata()
    {
        var explorationContext = new MetadataLoadContext(_resolver);

        var knownAssemblies = explorationContext.GetAssemblies().Union(new[] { ImplementingAssembly }).ToList();
        var recursions      = 0;

        List <string> newAssemblyNames;

        do
        {
            recursions++;

            var knownNames      = knownAssemblies.Select(a => a.GetName().FullName).Distinct().ToList();
            var referencedNames = knownAssemblies.SelectMany(
                a => a.GetReferencedAssemblies().Where(n => n.FullName.StartsWith("Trakx")))
                                  .Select(a => a.FullName);
            newAssemblyNames = referencedNames.Except(knownNames).ToList();
            foreach (var name in newAssemblyNames)
            {
                try
                {
                    knownAssemblies.Add(explorationContext.LoadFromAssemblyName(name));
                }
                catch (Exception e) { _output.WriteLine("Failed to load assembly {0} with exception {1}", name, e); }
            }
        } while (newAssemblyNames.Any() && recursions <= _maxRecursions);

        return(knownAssemblies);
    }
Esempio n. 5
0
 public static void GetAssemblies_EmptyMetadataLoadContext()
 {
     using (MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver()))
     {
         Assembly[] loadedAssemblies = lc.GetAssemblies().ToArray();
         Assert.Equal(1, loadedAssemblies.Length);
     }
 }
        public static void DuplicateSignedAssembliesSameMvid()
        {
            using (TempDirectory dir = new TempDirectory())
                using (TempDirectory dir2 = new TempDirectory())
                    using (TempFile core = new TempFile(Path.Combine(dir.Path, TestData.s_PhonyCoreAssemblySimpleName), TestData.s_PhonyCoreAssemblyImage))
                        using (TempFile tf1 = new TempFile(Path.Combine(dir.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned100Image))
                            using (TempFile tf2 = new TempFile(Path.Combine(dir2.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned100Image))
                            {
                                var resolver = new PathAssemblyResolver(new string[] { core.Path, tf1.Path, tf2.Path });

                                using (var lc = new MetadataLoadContext(resolver, TestData.s_PhonyCoreAssemblyFullName))
                                {
                                    Assert.Equal(1, lc.GetAssemblies().Count());

                                    Assembly a1 = lc.LoadFromAssemblyName(TestData.s_SimpleVersionedShortName);
                                    Assembly a2 = lc.LoadFromAssemblyName(TestData.s_SimpleSignedVersioned100FullName);
                                    Assert.Same(a1, a2);
                                    Assert.Equal(2, lc.GetAssemblies().Count());
                                }
                            }
        }
Esempio n. 7
0
        public static void MetadataLoadContextApisAfterDispose()
        {
            MetadataLoadContext lc = new MetadataLoadContext(new EmptyCoreMetadataAssemblyResolver());

            lc.Dispose();

            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyName(new AssemblyName("Foo")));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyName("Foo"));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromAssemblyPath("Foo"));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromByteArray(TestData.s_SimpleAssemblyImage));
            Assert.Throws <ObjectDisposedException>(() => lc.LoadFromStream(new MemoryStream(TestData.s_SimpleAssemblyImage)));
            Assert.Throws <ObjectDisposedException>(() => lc.CoreAssembly);
            Assert.Throws <ObjectDisposedException>(() => lc.GetAssemblies());
        }
        public static void DuplicateSignedAndUnsignedAssemblies()
        {
            using (TempDirectory dir = new TempDirectory())
                using (TempDirectory dir2 = new TempDirectory())
                    using (TempFile core = new TempFile(Path.Combine(dir.Path, TestData.s_PhonyCoreAssemblySimpleName), TestData.s_PhonyCoreAssemblyImage))
                        using (TempFile tf1 = new TempFile(Path.Combine(dir.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned100Image))
                            using (TempFile tf2 = new TempFile(Path.Combine(dir2.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleUnsignedVersioned100Image))
                            {
                                var resolver = new PathAssemblyResolver(new string[] { core.Path, tf1.Path, tf2.Path });

                                using (var lc = new MetadataLoadContext(resolver, TestData.s_PhonyCoreAssemblyFullName))
                                {
                                    Assert.Equal(1, lc.GetAssemblies().Count());

                                    // These are treated as different since one contains a PublicKeyToken and one does not.
                                    Assembly a1 = lc.LoadFromAssemblyName(TestData.s_SimpleUnsignedVersioned100FullName);
                                    Assembly a2 = lc.LoadFromAssemblyName(TestData.s_SimpleSignedVersioned100FullName);
                                    Assert.NotSame(a1, a2);

                                    Assert.Equal(3, lc.GetAssemblies().Count());
                                }
                            }
        }
Esempio n. 9
0
        public Type FindType(Type type)
        {
            var assemblyName = type.Assembly.GetName();
            var assemblies   = _metadataLoadContext.GetAssemblies();
            var assembly     = assemblies.FirstOrDefault(x => string.Equals(x.FullName, assemblyName.FullName));

            if (assembly == null)
            {
                assembly = _metadataLoadContext.LoadFromAssemblyName(assemblyName);
            }

            var result = assembly.GetType(type.FullName);

            return(result);
        }
        public static void DuplicateSignedAssembliesDifferentVersions()
        {
            using (TempDirectory dir = new TempDirectory())
                using (TempDirectory dir2 = new TempDirectory())
                    using (TempFile core = new TempFile(Path.Combine(dir.Path, TestData.s_PhonyCoreAssemblySimpleName), TestData.s_PhonyCoreAssemblyImage))
                        using (TempFile tf1 = new TempFile(Path.Combine(dir.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned100Image))
                            using (TempFile tf2 = new TempFile(Path.Combine(dir2.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned200Image))
                            {
                                var resolver = new PathAssemblyResolver(new string[] { core.Path, tf1.Path, tf2.Path });

                                using (var lc = new MetadataLoadContext(resolver, TestData.s_PhonyCoreAssemblyFullName))
                                {
                                    Assert.Equal(1, lc.GetAssemblies().Count());

                                    // Using simple name will find first assembly that matches.
                                    Assembly a1 = lc.LoadFromAssemblyName(TestData.s_SimpleVersionedShortName);
                                    Assembly a2 = lc.LoadFromAssemblyName(TestData.s_SimpleSignedVersioned100FullName);
                                    Assembly a3 = lc.LoadFromAssemblyName(TestData.s_SimpleSignedVersioned200FullName);
                                    Assert.True(object.ReferenceEquals(a1, a2) || object.ReferenceEquals(a1, a3));

                                    Assert.Equal(3, lc.GetAssemblies().Count());
                                }
                            }
        }
Esempio n. 11
0
        public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
        {
            var matchedAssembly = context.GetAssemblies()
                                  .FirstOrDefault(a => a.GetName().Name == assemblyName.Name);

            if (matchedAssembly != null)
            {
                return(matchedAssembly);
            }

            var path = Path.Combine(this.directory, assemblyName.Name + ".dll");

            if (File.Exists(path))
            {
                return(context.LoadFromAssemblyPath(path));
            }

            throw new FileLoadException($"Could not resolve {assemblyName}");
        }
Esempio n. 12
0
        public static void GetAssemblies_SnapshotIsAtomic()
        {
            Assembly a1 = null;

            var resolver = new FuncMetadataAssemblyResolver(
                delegate(MetadataLoadContext context, AssemblyName refName)
            {
                if (a1 == null)
                {
                    // Initial request to load core assembly
                    return(a1 = context.LoadFromByteArray(TestData.s_SimpleAssemblyImage));
                }
                return(null);
            });

            using (MetadataLoadContext lc = new MetadataLoadContext(resolver))
            {
                IEnumerable <Assembly> loadedAssembliesSnapshot = lc.GetAssemblies();
                Assembly   a2 = lc.LoadFromByteArray(TestData.s_SimpleNameOnlyImage);
                Assembly[] loadedAssemblies = loadedAssembliesSnapshot.ToArray();
                Assert.Equal(1, loadedAssemblies.Length);
                Assert.Equal(a1, loadedAssemblies[0]);
            }
        }
        public static void ResolveToAssemblyNameCombinations()
        {
            using (TempDirectory dir = new TempDirectory())
                using (TempFile core = new TempFile(Path.Combine(dir.Path, TestData.s_PhonyCoreAssemblySimpleName), TestData.s_PhonyCoreAssemblyImage))
                    using (TempFile tf1 = new TempFile(Path.Combine(dir.Path, TestData.s_SimpleVersionedShortName), TestData.s_SimpleSignedVersioned100Image))
                    {
                        var resolver = new PathAssemblyResolver(new string[] { core.Path, tf1.Path });

                        using (MetadataLoadContext lc = new MetadataLoadContext(resolver, TestData.s_PhonyCoreAssemblySimpleName))
                        {
                            Assert.Equal(1, lc.GetAssemblies().Count());

                            Assembly assembly = lc.LoadFromAssemblyName(TestData.s_SimpleVersionedShortName);
                            Assert.NotNull(assembly);

                            // Name

                            {
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(TestData.s_SimpleVersionedShortName.ToUpper());
                                Assert.NotNull(assemblyAgain);
                            }

                            AssemblyName assemblyName = new AssemblyName(TestData.s_SimpleVersionedShortName);

                            // Version

                            {
                                assemblyName.Version = new Version(999, 998);
                                lc.LoadFromAssemblyName(assemblyName);
                                Assert.Equal(2, lc.GetAssemblies().Count());
                            }

                            {
                                assemblyName.Version = null;
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.Version = new Version(0, 0, 0, 0);
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.Version = assembly.GetName().Version;
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            // CultureName; match not required

                            {
                                assemblyName.CultureName = "en";
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.CultureName = "";
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.CultureName = null;
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            assemblyName.CultureName = assembly.GetName().CultureName;

                            // PublicKeyToken

                            assemblyName.SetPublicKeyToken(new byte[] { 1 });
                            Assert.Throws <FileNotFoundException>(() => lc.LoadFromAssemblyName(assemblyName));

                            {
                                assemblyName.SetPublicKeyToken(null);
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.SetPublicKeyToken(Array.Empty <byte>());
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            {
                                assemblyName.SetPublicKeyToken(assembly.GetName().GetPublicKeyToken());
                                Assembly assemblyAgain = lc.LoadFromAssemblyName(assemblyName);
                                Assert.Same(assembly, assemblyAgain);
                            }

                            // None of the above should have affected the number of loaded assemblies.
                            Assert.Equal(2, lc.GetAssemblies().Count());
                        }
                    }
        }
Esempio n. 14
0
    int Main3(string [] args)
    {
        bool          show_help = false;
        bool          zero_copy = false;
        string        basedir = null;
        string        tmpdir = null;
        string        ns = null;
        bool          delete_temp = true, debug = false;
        bool          unsafef          = true;
        bool          external         = false;
        bool          public_mode      = true;
        bool          nostdlib         = false;
        bool?         inline_selectors = null;
        List <string> sources;
        var           resources          = new List <string> ();
        var           linkwith           = new List <string> ();
        var           api_sources        = new List <string> ();
        var           core_sources       = new List <string> ();
        var           extra_sources      = new List <string> ();
        var           defines            = new List <string> ();
        string        generate_file_list = null;
        bool          process_enums      = false;
        string        compiler           = "/Library/Frameworks/Mono.framework/Versions/Current/bin/csc";

        ErrorHelper.ClearWarningLevels();

        var os = new OptionSet()
        {
            { "h|?|help", "Displays the help", v => show_help = true },
            { "a", "Include alpha bindings (Obsolete).", v => {}, true },
            { "outdir=", "Sets the output directory for the temporary binding files", v => { basedir = v; } },
            { "o|out=", "Sets the name of the output library", v => outfile = v },
            { "tmpdir=", "Sets the working directory for temp files", v => { tmpdir = v; delete_temp = false; } },
            { "debug", "Generates a debugging build of the binding", v => debug = true },
            { "sourceonly=", "Only generates the source", v => generate_file_list = v },
            { "ns=", "Sets the namespace for storing helper classes", v => ns = v },
            { "unsafe", "Sets the unsafe flag for the build", v => unsafef = true },
            { "core", "Use this to build product assemblies", v => BindThirdPartyLibrary = false },
            { "r|reference=", "Adds a reference", v => references.Add(v) },
            { "lib=", "Adds the directory to the search path for the compiler", v => libs.Add(v) },
            { "compiler=", "Sets the compiler to use (Obsolete) ", v => compiler = v, true },
            { "sdk=", "Sets the .NET SDK to use (Obsolete)", v => {}, true },
            { "new-style", "Build for Unified (Obsolete).", v => { Console.WriteLine("The --new-style option is obsolete and ignored."); }, true },
            { "d=", "Defines a symbol", v => defines.Add(v) },
            { "api=", "Adds a API definition source file", v => api_sources.Add(v) },
            { "s=", "Adds a source file required to build the API", v => core_sources.Add(v) },
            { "q", "Quiet", v => ErrorHelper.Verbosity-- },
            { "v", "Sets verbose mode", v => ErrorHelper.Verbosity++ },
            { "x=", "Adds the specified file to the build, used after the core files are compiled", v => extra_sources.Add(v) },
            { "e", "Generates smaller classes that can not be subclassed (previously called 'external mode')", v => external = true },
            { "p", "Sets private mode", v => public_mode = false },
            { "baselib=", "Sets the base library", v => baselibdll = v },
            { "attributelib=", "Sets the attribute library", v => attributedll = v },
            { "use-zero-copy", v => zero_copy = true },
            { "nostdlib", "Does not reference mscorlib.dll library", l => nostdlib = true },
            { "no-mono-path", "Launches compiler with empty MONO_PATH", l => { }, true },
            { "native-exception-marshalling", "Enable the marshalling support for Objective-C exceptions", (v) => { /* no-op */ } },
            { "inline-selectors:", "If Selector.GetHandle is inlined and does not need to be cached (enabled by default in Xamarin.iOS, disabled in Xamarin.Mac)",
              v => inline_selectors = string.Equals("true", v, StringComparison.OrdinalIgnoreCase) || string.IsNullOrEmpty(v) },
            { "process-enums", "Process enums as bindings, not external, types.", v => process_enums = true },
            { "link-with=,", "Link with a native library {0:FILE} to the binding, embedded as a resource named {1:ID}",
              (path, id) => {
                  if (path == null || path.Length == 0)
                  {
                      throw new Exception("-link-with=FILE,ID requires a filename.");
                  }

                  if (id == null || id.Length == 0)
                  {
                      id = Path.GetFileName(path);
                  }

                  if (linkwith.Contains(id))
                  {
                      throw new Exception("-link-with=FILE,ID cannot assign the same resource id to multiple libraries.");
                  }

                  resources.Add(string.Format("-res:{0},{1}", path, id));
                  linkwith.Add(id);
              } },
            { "unified-full-profile", "Launches compiler pointing to XM Full Profile", l => { /* no-op*/ }, true },
            { "unified-mobile-profile", "Launches compiler pointing to XM Mobile Profile", l => { /* no-op*/ }, true },
            { "target-framework=", "Specify target framework to use. Always required, and the currently supported values are: 'Xamarin.iOS,v1.0', 'Xamarin.TVOS,v1.0', 'Xamarin.WatchOS,v1.0', 'XamMac,v1.0', 'Xamarin.Mac,Version=v2.0,Profile=Mobile', 'Xamarin.Mac,Version=v4.5,Profile=Full' and 'Xamarin.Mac,Version=v4.5,Profile=System')", v => SetTargetFramework(v) },
            { "warnaserror:", "An optional comma-separated list of warning codes that should be reported as errors (if no warnings are specified all warnings are reported as errors).", v => {
                  try {
                      if (!string.IsNullOrEmpty(v))
                      {
                          foreach (var code in v.Split(new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Error, int.Parse(code));
                          }
                      }
                      else
                      {
                          ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Error);
                      }
                  } catch (Exception ex) {
                      throw ErrorHelper.CreateError(26, ex.Message);
                  }
              } },
            { "nowarn:", "An optional comma-separated list of warning codes to ignore (if no warnings are specified all warnings are ignored).", v => {
                  try {
                      if (!string.IsNullOrEmpty(v))
                      {
                          foreach (var code in v.Split(new char [] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                          {
                              ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Disable, int.Parse(code));
                          }
                      }
                      else
                      {
                          ErrorHelper.SetWarningLevel(ErrorHelper.WarningLevel.Disable);
                      }
                  } catch (Exception ex) {
                      throw ErrorHelper.CreateError(26, ex.Message);
                  }
              } },
            new Mono.Options.ResponseFileSource(),
        };

        try {
            sources = os.Parse(args);
        } catch (Exception e) {
            Console.Error.WriteLine("{0}: {1}", ToolName, e.Message);
            Console.Error.WriteLine("see {0} --help for more information", ToolName);
            return(1);
        }

        if (show_help)
        {
            ShowHelp(os);
            return(0);
        }

        if (!target_framework.HasValue)
        {
            throw ErrorHelper.CreateError(86);
        }

        switch (target_framework.Value.Platform)
        {
        case ApplePlatform.iOS:
            CurrentPlatform = PlatformName.iOS;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.iOS/Xamarin.iOS.dll");
            }
            if (!IsDotNet)
            {
                references.Add("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/Xamarin.iOS", references);
            }
            break;

        case ApplePlatform.TVOS:
            CurrentPlatform = PlatformName.TvOS;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll");
            }
            if (!IsDotNet)
            {
                references.Add("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/Xamarin.TVOS", references);
            }
            break;

        case ApplePlatform.WatchOS:
            CurrentPlatform = PlatformName.WatchOS;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.WatchOS/Xamarin.WatchOS.dll");
            }
            if (!IsDotNet)
            {
                references.Add("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/Xamarin.WatchOS", references);
            }
            break;

        case ApplePlatform.MacCatalyst:
            CurrentPlatform = PlatformName.MacCatalyst;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.MacCatalyst/Xamarin.MacCatalyst.dll");
            }
            if (!IsDotNet)
            {
                // references.Add ("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/Xamarin.MacCatalyst", references);
            }
            break;

        case ApplePlatform.MacOSX:
            CurrentPlatform = PlatformName.MacOSX;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                if (target_framework == TargetFramework.Xamarin_Mac_2_0_Mobile)
                {
                    baselibdll = Path.Combine(GetSDKRoot(), "lib", "reference", "mobile", "Xamarin.Mac.dll");
                }
                else if (target_framework == TargetFramework.Xamarin_Mac_4_5_Full || target_framework == TargetFramework.Xamarin_Mac_4_5_System)
                {
                    baselibdll = Path.Combine(GetSDKRoot(), "lib", "reference", "full", "Xamarin.Mac.dll");
                }
                else
                {
                    throw ErrorHelper.CreateError(1053, target_framework);
                }
            }
            if (target_framework == TargetFramework.Xamarin_Mac_2_0_Mobile)
            {
                skipSystemDrawing = true;
                references.Add("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/Xamarin.Mac", references);
            }
            else if (target_framework == TargetFramework.Xamarin_Mac_4_5_Full)
            {
                skipSystemDrawing = true;
                references.Add("Facades/System.Drawing.Common");
                ReferenceFixer.FixSDKReferences(GetSDKRoot(), "lib/mono/4.5", references);
            }
            else if (target_framework == TargetFramework.Xamarin_Mac_4_5_System)
            {
                skipSystemDrawing = false;
                ReferenceFixer.FixSDKReferences("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5", references, forceSystemDrawing: true);
            }
            else if (target_framework == TargetFramework.DotNet_5_0_macOS)
            {
                skipSystemDrawing = false;
            }
            else
            {
                throw ErrorHelper.CreateError(1053, target_framework);
            }

            break;

        default:
            throw ErrorHelper.CreateError(1053, target_framework);
        }

        if (sources.Count > 0)
        {
            api_sources.Insert(0, sources [0]);
            for (int i = 1; i < sources.Count; i++)
            {
                core_sources.Insert(i - 1, sources [i]);
            }
        }

        if (api_sources.Count == 0)
        {
            Console.WriteLine("Error: no api file provided");
            ShowHelp(os);
            return(1);
        }

        if (tmpdir == null)
        {
            tmpdir = GetWorkDir();
        }

        string firstApiDefinitionName = Path.GetFileNameWithoutExtension(api_sources [0]);

        firstApiDefinitionName = firstApiDefinitionName.Replace('-', '_');          // This is not exhaustive, but common.
        if (outfile == null)
        {
            outfile = firstApiDefinitionName + ".dll";
        }

        var refs  = references.Select((v) => "-r:" + v);
        var paths = libs.Select((v) => "-lib:" + v);

        try {
            var tmpass = Path.Combine(tmpdir, "temp.dll");

            // -nowarn:436 is to avoid conflicts in definitions between core.dll and the sources
            // Keep source files at the end of the command line - csc will create TWO assemblies if any sources preceed the -out parameter
            var cargs = new List <string> ();

            cargs.Add("-debug");
            cargs.Add("-unsafe");
            cargs.Add("-target:library");
            cargs.Add("-nowarn:436");
            cargs.Add("-out:" + tmpass);
            cargs.Add("-r:" + GetAttributeLibraryPath());
            cargs.AddRange(refs);
            if (unsafef)
            {
                cargs.Add("-unsafe");
            }
            cargs.Add("-r:" + baselibdll);
            foreach (var def in defines)
            {
                cargs.Add("-define:" + def);
            }
            cargs.AddRange(paths);
            if (nostdlib)
            {
                cargs.Add("-nostdlib");
                cargs.Add("-noconfig");
            }
            cargs.AddRange(api_sources);
            cargs.AddRange(core_sources);
            if (!string.IsNullOrEmpty(Path.GetDirectoryName(baselibdll)))
            {
                cargs.Add("-lib:" + Path.GetDirectoryName(baselibdll));
            }

            if (Driver.RunCommand(compiler, cargs, null, out var compile_output, true, Driver.Verbosity) != 0)
            {
                throw ErrorHelper.CreateError(2, $"{compiler} {StringUtils.FormatArguments (cargs)}\n{compile_output}".Replace("\n", "\n\t"));
            }

            universe = new MetadataLoadContext(
                new SearchPathsAssemblyResolver(
                    GetLibraryDirectories().ToArray(),
                    references.ToArray()),
                "mscorlib"
                );

            Assembly api;
            try {
                api = universe.LoadFromAssemblyPath(tmpass);
            } catch (Exception e) {
                if (Driver.Verbosity > 0)
                {
                    Console.WriteLine(e);
                }

                Console.Error.WriteLine("Error loading API definition from {0}", tmpass);
                return(1);
            }

            Assembly baselib;
            try {
                baselib = universe.LoadFromAssemblyPath(baselibdll);
            } catch (Exception e) {
                if (Driver.Verbosity > 0)
                {
                    Console.WriteLine(e);
                }

                Console.Error.WriteLine("Error loading base library {0}", baselibdll);
                return(1);
            }

            AttributeManager = new AttributeManager(this);
            Frameworks       = new Frameworks(CurrentPlatform);

            // Explicitly load our attribute library so that IKVM doesn't try (and fail) to find it.
            universe.LoadFromAssemblyPath(GetAttributeLibraryPath());

            TypeManager.Initialize(this, api, universe.CoreAssembly, baselib);

            foreach (var linkWith in AttributeManager.GetCustomAttributes <LinkWithAttribute> (api))
            {
                if (!linkwith.Contains(linkWith.LibraryName))
                {
                    Console.Error.WriteLine("Missing native library {0}, please use `--link-with' to specify the path to this library.", linkWith.LibraryName);
                    return(1);
                }
            }

            foreach (var r in references)
            {
                // IKVM has a bug where it doesn't correctly compare assemblies, which means it
                // can end up loading the same assembly (in particular any System.Runtime whose
                // version > 4.0, but likely others as well) more than once. This is bad, because
                // we compare types based on reference equality, which breaks down when there are
                // multiple instances of the same type.
                //
                // So just don't ask IKVM to load assemblies that have already been loaded.
                var fn         = Path.GetFileNameWithoutExtension(r);
                var assemblies = universe.GetAssemblies();
                if (assemblies.Any((v) => v.GetName().Name == fn))
                {
                    continue;
                }

                if (File.Exists(r))
                {
                    try {
                        universe.LoadFromAssemblyPath(r);
                    } catch (Exception ex) {
                        ErrorHelper.Warning(1104, r, ex.Message);
                    }
                }
            }

            var types = new List <Type> ();
            var strong_dictionaries = new List <Type> ();
            foreach (var t in api.GetTypes())
            {
                if ((process_enums && t.IsEnum) ||
                    AttributeManager.HasAttribute <BaseTypeAttribute> (t) ||
                    AttributeManager.HasAttribute <ProtocolAttribute> (t) ||
                    AttributeManager.HasAttribute <StaticAttribute> (t) ||
                    AttributeManager.HasAttribute <PartialAttribute> (t))
                {
                    types.Add(t);
                }
                if (AttributeManager.HasAttribute <StrongDictionaryAttribute> (t))
                {
                    strong_dictionaries.Add(t);
                }
            }

            var nsManager = new NamespaceManager(
                this,
                ns == null ? firstApiDefinitionName : ns,
                skipSystemDrawing
                );

            var g = new Generator(this, nsManager, public_mode, external, debug, types.ToArray(), strong_dictionaries.ToArray())
            {
                BaseDir         = basedir != null ? basedir : tmpdir,
                ZeroCopyStrings = zero_copy,
                InlineSelectors = inline_selectors ?? (CurrentPlatform != PlatformName.MacOSX),
            };

            g.Go();

            if (generate_file_list != null)
            {
                using (var f = File.CreateText(generate_file_list)){
                    foreach (var x in g.GeneratedFiles.OrderBy((v) => v))
                    {
                        f.WriteLine(x);
                    }
                }
                return(0);
            }

            cargs.Clear();
            if (unsafef)
            {
                cargs.Add("-unsafe");
            }
            cargs.Add("-target:library");
            cargs.Add("-out:" + outfile);
            foreach (var def in defines)
            {
                cargs.Add("-define:" + def);
            }
            cargs.AddRange(g.GeneratedFiles);
            cargs.AddRange(core_sources);
            cargs.AddRange(extra_sources);
            cargs.AddRange(refs);
            cargs.Add("-r:" + baselibdll);
            cargs.AddRange(resources);
            if (nostdlib)
            {
                cargs.Add("-nostdlib");
                cargs.Add("-noconfig");
            }
            if (!string.IsNullOrEmpty(Path.GetDirectoryName(baselibdll)))
            {
                cargs.Add("-lib:" + Path.GetDirectoryName(baselibdll));
            }

            if (Driver.RunCommand(compiler, cargs, null, out var generated_compile_output, true, Driver.Verbosity) != 0)
            {
                throw ErrorHelper.CreateError(1000, $"{compiler} {StringUtils.FormatArguments (cargs)}\n{generated_compile_output}".Replace("\n", "\n\t"));
            }
        } finally {
            if (delete_temp)
            {
                Directory.Delete(tmpdir, true);
            }
        }
        return(0);
    }