Exemplo n.º 1
0
    public static bool IsOutParameter(ParameterInfo pi)
    {
#if IKVM
        return(pi.IsOut);
#else
        return(AttributeManager.HasAttribute <OutAttribute> (pi));
#endif
    }
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (!AttributeManager.HasAttribute(context, typeof(LogInRequired)))
        {
            return;
        }
        if (context.HttpContext.User.Identity.IsAuthenticated)
        {
            return;
        }

        context.Result = new RedirectResult("/login?ReturnUrl=" + Uri.EscapeDataString(context.HttpContext.Request.Path));
    }
Exemplo n.º 3
0
    public void GenerateFilter(Type type)
    {
        var is_abstract = AttributeManager.HasAttribute <AbstractAttribute> (type);
        var filter      = AttributeManager.GetCustomAttribute <CoreImageFilterAttribute> (type);
        var base_type   = AttributeManager.GetCustomAttribute <BaseTypeAttribute> (type);
        var type_name   = type.Name;
        var native_name = base_type.Name ?? type_name;
        var base_name   = base_type.BaseType.Name;

        // internal static CIFilter FromName (string filterName, IntPtr handle)
        filters.Add(type_name);

        // type declaration
        print("public{0} partial class {1} : {2} {{",
              is_abstract ? " abstract" : String.Empty,
              type_name, base_name);
        print("");
        indent++;

        // default constructor - if type is not abstract
        string v;

        if (!is_abstract)
        {
            v = GetVisibility(filter.DefaultCtorVisibility);
            if (v.Length > 0)
            {
                print_generated_code();
                print("{0}{1} () : base (\"{2}\")", v, type.Name, native_name);
                PrintEmptyBody();
            }
        }

        // IntPtr constructor - always present
        var intptrctor_visibility = filter.IntPtrCtorVisibility;

        if (intptrctor_visibility == MethodAttributes.PrivateScope)
        {
            // since it was not generated code we never fixed the .ctor(IntPtr) visibility for unified
            if (Generator.XamcoreVersion >= 3)
            {
                intptrctor_visibility = MethodAttributes.FamORAssem;
            }
            else
            {
                intptrctor_visibility = MethodAttributes.Public;
            }
        }
        print_generated_code();
        print("{0}{1} (IntPtr handle) : base (handle)", GetVisibility(intptrctor_visibility), type_name);
        PrintEmptyBody();

        // NSObjectFlag constructor - always present (needed to implement NSCoder for subclasses)
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("protected {0} (NSObjectFlag t) : base (t)", type_name);
        PrintEmptyBody();

        // NSCoder constructor - all filters conforms to NSCoding
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("[Export (\"initWithCoder:\")]");
        print("public {0} (NSCoder coder) : base (NSObjectFlag.Empty)", type_name);
        print("{");
        indent++;
        print("IntPtr h;");
        print("if (IsDirectBinding) {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("} else {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("}");
        print("InitializeHandle (h, \"initWithCoder:\");");
        indent--;
        print("}");
        print("");

        // string constructor
        // default is protected (for abstract) but backward compatibility (XAMCORE_2_0) requires some hacks
        v = GetVisibility(filter.StringCtorVisibility);
        if (is_abstract && (v.Length == 0))
        {
            v = "protected ";
        }
        if (v.Length > 0)
        {
            print_generated_code();
            print("{0} {1} (string name) : base (CreateFilter (name))", v, type_name);
            PrintEmptyBody();
        }

        // properties
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable())
            {
                continue;
            }

            print("");
            print_generated_code();
            var ptype = p.PropertyType.Name;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;
            }
            print("public {0} {1} {{", ptype, p.Name);
            indent++;

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            if (p.GetGetMethod() != null)
            {
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }

        indent--;
        print("}");

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
Exemplo n.º 4
0
    // caller already:
    //	- setup the header and namespace
    //	- call/emit PrintPlatformAttributes on the type
    void GenerateEnum(Type type)
    {
        if (AttributeManager.HasAttribute <FlagsAttribute> (type))
        {
            print("[Flags]");
        }

        var native = AttributeManager.GetCustomAttribute <NativeAttribute> (type);

        if (native != null)
        {
            if (String.IsNullOrEmpty(native.NativeName))
            {
                print("[Native]");
            }
            else
            {
                print("[Native (\"{0}\")]", native.NativeName);
            }
        }
        CopyObsolete(type);

        var unique_constants = new HashSet <string> ();
        var fields           = new Dictionary <FieldInfo, FieldAttribute> ();
        Tuple <FieldInfo, FieldAttribute> null_field     = null;
        Tuple <FieldInfo, FieldAttribute> default_symbol = null;
        var underlying_type = GetCSharpTypeName(TypeManager.GetUnderlyingEnumType(type));

        print("public enum {0} : {1} {{", type.Name, underlying_type);
        indent++;
        foreach (var f in type.GetFields())
        {
            // skip value__ field
            if (f.IsSpecialName)
            {
                continue;
            }
            PrintPlatformAttributes(f);
            CopyObsolete(f);
            print("{0} = {1},", f.Name, f.GetRawConstantValue());
            var fa = AttributeManager.GetCustomAttribute <FieldAttribute> (f);
            if (fa == null)
            {
                continue;
            }
            if (f.IsUnavailable())
            {
                continue;
            }
            if (fa.SymbolName == null)
            {
                null_field = new Tuple <FieldInfo, FieldAttribute> (f, fa);
            }
            else if (unique_constants.Contains(fa.SymbolName))
            {
                throw new BindingException(1046, true, $"The [Field] constant {fa.SymbolName} cannot only be used once inside enum {type.Name}.");
            }
            else
            {
                fields.Add(f, fa);
                unique_constants.Add(fa.SymbolName);
            }
            if (AttributeManager.GetCustomAttribute <DefaultEnumValueAttribute> (f) != null)
            {
                if (default_symbol != null)
                {
                    throw new BindingException(1045, true, $"Only a single [DefaultEnumValue] attribute can be used inside enum {type.Name}.");
                }
                default_symbol = new Tuple <FieldInfo, FieldAttribute> (f, fa);
            }
        }
        indent--;
        print("}");
        unique_constants.Clear();

        var library_name = type.Namespace;
        var error        = AttributeManager.GetCustomAttribute <ErrorDomainAttribute> (type);

        if ((fields.Count > 0) || (error != null))
        {
            print("");
            // the *Extensions has the same version requirement as the enum itself
            PrintPlatformAttributes(type);
            print("[CompilerGenerated]");
            print("static public partial class {0}Extensions {{", type.Name);
            indent++;

            var field     = fields.FirstOrDefault();
            var fieldAttr = field.Value;

            ComputeLibraryName(fieldAttr, type, field.Key?.Name, out library_name, out string library_path);
        }

        if (error != null)
        {
            // this attribute is important for our tests
            print("[Field (\"{0}\", \"{1}\")]", error.ErrorDomain, library_name);
            print("static NSString _domain;");
            print("");
            print("public static NSString GetDomain (this {0} self)", type.Name);
            print("{");
            indent++;
            print("if (_domain == null)");
            indent++;
            print("_domain = Dlfcn.GetStringConstant (Libraries.{0}.Handle, \"{1}\");", library_name, error.ErrorDomain);
            indent--;
            print("return _domain;");
            indent--;
            print("}");
        }

        if (fields.Count > 0)
        {
            print("static IntPtr[] values = new IntPtr [{0}];", fields.Count);
            print("");

            int n = 0;
            foreach (var kvp in fields)
            {
                var f  = kvp.Key;
                var fa = kvp.Value;
                // the attributes (availability and field) are important for our tests
                PrintPlatformAttributes(f);
                libraries.TryGetValue(library_name, out var libPath);
                var libname = fa.LibraryName?.Replace("+", string.Empty);
                // We need to check for special cases inside FieldAttributes
                // fa.LibraryName could contain a different framework i.e UITrackingRunLoopMode (UIKit) inside NSRunLoopMode enum (Foundation).
                // libPath could have a custom path i.e. CoreImage which in macOS is inside Quartz
                // library_name contains the Framework constant name the Field is inside of, used as fallback.
                bool useFieldAttrLibName = libname != null && !string.Equals(libname, library_name, StringComparison.OrdinalIgnoreCase);
                print("[Field (\"{0}\", \"{1}\")]", fa.SymbolName, useFieldAttrLibName ? libname : libPath ?? library_name);
                print("internal unsafe static IntPtr {0} {{", fa.SymbolName);
                indent++;
                print("get {");
                indent++;
                print("fixed (IntPtr *storage = &values [{0}])", n++);
                indent++;
                print("return Dlfcn.CachePointer (Libraries.{0}.Handle, \"{1}\", storage);", useFieldAttrLibName ? libname : library_name, fa.SymbolName);
                indent--;
                indent--;
                print("}");
                indent--;
                print("}");
                print("");
            }

            print("public static NSString GetConstant (this {0} self)", type.Name);
            print("{");
            indent++;
            print("IntPtr ptr = IntPtr.Zero;");
            print("switch (({0}) self) {{", underlying_type);
            var default_symbol_name = default_symbol?.Item2.SymbolName;
            // more than one enum member can share the same numeric value - ref: #46285
            foreach (var kvp in fields)
            {
                print("case {0}: // {1}.{2}", Convert.ToInt64(kvp.Key.GetRawConstantValue()), type.Name, kvp.Key.Name);
                var sn = kvp.Value.SymbolName;
                if (sn == default_symbol_name)
                {
                    print("default:");
                }
                indent++;
                print("ptr = {0};", sn);
                print("break;");
                indent--;
            }
            print("}");
            print("return (NSString) Runtime.GetNSObject (ptr);");
            indent--;
            print("}");

            print("");

            print("public static {0} GetValue (NSString constant)", type.Name);
            print("{");
            indent++;
            print("if (constant == null)");
            indent++;
            // if we do not have a enum value that maps to a null field then we throw
            if (null_field == null)
            {
                print("throw new ArgumentNullException (nameof (constant));");
            }
            else
            {
                print("return {0}.{1};", type.Name, null_field.Item1.Name);
            }
            indent--;
            foreach (var kvp in fields)
            {
                print("if (constant.IsEqualTo ({0}))", kvp.Value.SymbolName);
                indent++;
                print("return {0}.{1};", type.Name, kvp.Key.Name);
                indent--;
            }
            // if there's no default then we throw on unknown constants
            if (default_symbol == null)
            {
                print("throw new NotSupportedException (constant + \" has no associated enum value in \" + nameof ({0}) + \" on this platform.\");", type.Name);
            }
            else
            {
                print("return {0}.{1};", type.Name, default_symbol.Item1.Name);
            }
            indent--;
            print("}");
        }

        if ((fields.Count > 0) || (error != null))
        {
            indent--;
            print("}");
        }

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
Exemplo n.º 5
0
    static int Main2(string [] args)
    {
        bool          show_help = false;
        bool          zero_copy = false;
        string        basedir = null;
        string        tmpdir = null;
        string        ns = null;
        string        outfile = null;
        bool          delete_temp = true, debug = false;
        bool          verbose          = 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           references         = 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;

        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 => Generator.BindThirdPartyLibrary = false },
            { "r=", "Adds a reference", v => references.Add(v) },
            { "lib=", "Adds the directory to the search path for the compiler", v => libs.Add(StringUtils.Quote(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(StringUtils.Quote(v)) },
            { "s=", "Adds a source file required to build the API", v => core_sources.Add(StringUtils.Quote(v)) },
            { "v", "Sets verbose mode", v => verbose = true },
            { "x=", "Adds the specified file to the build, used after the core files are compiled", v => extra_sources.Add(StringUtils.Quote(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 => { } },
            { "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: 'MonoTouch,v1.0', '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, $"Could not parse the command line argument '--warnaserror': {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, $"Could not parse the command line argument '--nowarn': {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, "A target framework (--target-framework) must be specified.");
        }

        switch (target_framework.Value.Identifier.ToLowerInvariant())
        {
        case "monotouch":
            CurrentPlatform = PlatformName.iOS;
            Unified         = false;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/2.1/monotouch.dll");
            }
            Path.Combine(GetSDKRoot(), "bin/smcs");
            AddAnyMissingSystemReferencesFromSDK("lib/mono/2.1/", references);
            break;

        case "xamarin.ios":
            CurrentPlatform = PlatformName.iOS;
            Unified         = true;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.iOS/Xamarin.iOS.dll");
            }
            AddAnyMissingSystemReferencesFromSDK("lib/mono/Xamarin.iOS", references);
            break;

        case "xamarin.tvos":
            CurrentPlatform = PlatformName.TvOS;
            Unified         = true;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.TVOS/Xamarin.TVOS.dll");
            }
            AddAnyMissingSystemReferencesFromSDK("lib/mono/Xamarin.TVOS", references);
            break;

        case "xamarin.watchos":
            CurrentPlatform = PlatformName.WatchOS;
            Unified         = true;
            nostdlib        = true;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib/mono/Xamarin.WatchOS/Xamarin.WatchOS.dll");
            }
            AddAnyMissingSystemReferencesFromSDK("lib/mono/Xamarin.WatchOS", references);
            break;

        case "xammac":
            CurrentPlatform = PlatformName.MacOSX;
            Unified         = false;
            if (string.IsNullOrEmpty(baselibdll))
            {
                baselibdll = Path.Combine(GetSDKRoot(), "lib", "mono", "XamMac.dll");
            }
            AddAnyMissingSystemReferences("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5", references);
            break;

        case "xamarin.mac":
            CurrentPlatform   = PlatformName.MacOSX;
            Unified           = true;
            nostdlib          = true;
            skipSystemDrawing = target_framework == TargetFramework.Xamarin_Mac_4_5_Full;
            if (string.IsNullOrEmpty(baselibdll))
            {
                if (target_framework == TargetFramework.Xamarin_Mac_2_0_Mobile)
                {
                    baselibdll = Path.Combine(GetSDKRoot(), "lib", "reference", "mobile", "Xamarin.Mac.dll");
                    AddAnyMissingSystemReferencesFromSDK("lib/mono/Xamarin.Mac", references);
                }
                else
                {
                    baselibdll = Path.Combine(GetSDKRoot(), "lib", "reference", "full", "Xamarin.Mac.dll");
                    AddAnyMissingSystemReferencesFromSDK("lib/mono/4.5", references);
                }
            }
            break;

        default:
            throw ErrorHelper.CreateError(1043, "Internal error: unknown target framework '{0}'.", target_framework);
        }

        if (target_framework == TargetFramework.XamMac_1_0 && !references.Any((v) => Path.GetFileNameWithoutExtension(v) == "System.Drawing"))
        {
            // If we're targeting XM/Classic ensure we have a reference to System.Drawing.dll.
            references.Add("/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/System.Drawing.dll");
        }

        if (sources.Count > 0)
        {
            api_sources.Insert(0, StringUtils.Quote(sources [0]));
            for (int i = 1; i < sources.Count; i++)
            {
                core_sources.Insert(i - 1, StringUtils.Quote(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(StringUtils.Unquote(api_sources [0]));

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

        string refs = string.Empty;

        foreach (var r in references)
        {
            if (refs != string.Empty)
            {
                refs += " ";
            }
            refs += "-r:" + StringUtils.Quote(r);
        }
        string paths = (libs.Count > 0 ? "-lib:" + String.Join(" -lib:", libs.ToArray()) : "");

        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 StringBuilder();

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


            var si = new ProcessStartInfo(compiler, cargs.ToString())
            {
                UseShellExecute = false,
            };

            // HACK: We are calling btouch with forced 2.1 path but we need working mono for compiler
            si.EnvironmentVariables.Remove("MONO_PATH");

            if (verbose)
            {
                Console.WriteLine("{0} {1}", si.FileName, si.Arguments);
            }

            var p = Process.Start(si);
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                Console.WriteLine("{0}: API binding contains errors.", ToolName);
                return(1);
            }

            universe = new Universe(UniverseOptions.EnableFunctionPointers | UniverseOptions.ResolveMissingMembers | UniverseOptions.MetadataOnly);

            Assembly api;
            try {
                api = universe.LoadFile(tmpass);
            } catch (Exception e) {
                if (verbose)
                {
                    Console.WriteLine(e);
                }

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

            Assembly baselib;
            try {
                baselib = universe.LoadFile(baselibdll);
            } catch (Exception e) {
                if (verbose)
                {
                    Console.WriteLine(e);
                }

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

            Assembly corlib_assembly   = universe.LoadFile(LocateAssembly("mscorlib"));
            Assembly platform_assembly = baselib;
            Assembly system_assembly   = universe.LoadFile(LocateAssembly("System"));
            Assembly binding_assembly  = universe.LoadFile(GetAttributeLibraryPath());
            TypeManager.Initialize(api, corlib_assembly, platform_assembly, system_assembly, binding_assembly);

            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)
            {
                if (File.Exists(r))
                {
                    try {
                        universe.LoadFile(r);
                    } catch (Exception ex) {
                        ErrorHelper.Show(new BindingException(1104, false, "Could not load the referenced library '{0}': {1}.", 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(
                NamespacePlatformPrefix,
                ns == null ? firstApiDefinitionName : ns,
                skipSystemDrawing
                );

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

            if (!Unified && !Generator.BindThirdPartyLibrary)
            {
                foreach (var mi in baselib.GetType(nsManager.CoreObjCRuntime + ".Messaging").GetMethods())
                {
                    if (mi.Name.IndexOf("_objc_msgSend", StringComparison.Ordinal) != -1)
                    {
                        g.RegisterMethodName(mi.Name);
                    }
                }
            }

            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.Append("-unsafe ");
            }
            cargs.Append("-target:library ");
            cargs.Append("-out:").Append(StringUtils.Quote(outfile)).Append(' ');
            foreach (var def in defines)
            {
                cargs.Append("-define:").Append(def).Append(' ');
            }
            foreach (var gf in g.GeneratedFiles)
            {
                cargs.Append(gf).Append(' ');
            }
            foreach (var cs in core_sources)
            {
                cargs.Append(cs).Append(' ');
            }
            foreach (var es in extra_sources)
            {
                cargs.Append(es).Append(' ');
            }
            cargs.Append(refs).Append(' ');
            cargs.Append("-r:").Append(StringUtils.Quote(baselibdll)).Append(' ');
            foreach (var res in resources)
            {
                cargs.Append(res).Append(' ');
            }
            if (nostdlib)
            {
                cargs.Append("-nostdlib ");
                cargs.Append("-noconfig ");
            }
            if (!string.IsNullOrEmpty(Path.GetDirectoryName(baselibdll)))
            {
                cargs.Append("-lib:").Append(Path.GetDirectoryName(baselibdll)).Append(' ');
            }

            si = new ProcessStartInfo(compiler, cargs.ToString())
            {
                UseShellExecute = false,
            };

            // HACK: We are calling btouch with forced 2.1 path but we need working mono for compiler
            si.EnvironmentVariables.Remove("MONO_PATH");

            if (verbose)
            {
                Console.WriteLine("{0} {1}", si.FileName, si.Arguments);
            }

            p = Process.Start(si);
            p.WaitForExit();
            if (p.ExitCode != 0)
            {
                Console.WriteLine("{0}: API binding contains errors.", ToolName);
                return(1);
            }
        } finally {
            if (delete_temp)
            {
                Directory.Delete(tmpdir, true);
            }
        }
        return(0);
    }
    public void GenerateFilter(Type type)
    {
        var is_abstract = AttributeManager.HasAttribute <AbstractAttribute> (type);
        var filter      = AttributeManager.GetCustomAttribute <CoreImageFilterAttribute> (type);
        var base_type   = AttributeManager.GetCustomAttribute <BaseTypeAttribute> (type);
        var type_name   = type.Name;
        var native_name = base_type.Name ?? type_name;
        var base_name   = base_type.BaseType.Name;

        // internal static CIFilter FromName (string filterName, IntPtr handle)
        filters.Add(type_name);

        // filters are now exposed as protocols so we need to conform to them
        var interfaces = String.Empty;

        foreach (var i in type.GetInterfaces())
        {
            interfaces += $", I{i.Name}";
        }

        // type declaration
        print("public{0} partial class {1} : {2}{3} {{",
              is_abstract ? " abstract" : String.Empty,
              type_name, base_name, interfaces);
        print("");
        indent++;

        // default constructor - if type is not abstract
        string v;

        if (!is_abstract)
        {
            v = GetVisibility(filter.DefaultCtorVisibility);
            if (v.Length > 0)
            {
                print_generated_code();
                print("{0}{1} () : base (\"{2}\")", v, type.Name, native_name);
                PrintEmptyBody();
            }
        }

        // IntPtr constructor - always present
        var intptrctor_visibility = filter.IntPtrCtorVisibility;

        if (intptrctor_visibility == MethodAttributes.PrivateScope)
        {
            // since it was not generated code we never fixed the .ctor(IntPtr) visibility for unified
            if (XamcoreVersion >= 3)
            {
                intptrctor_visibility = MethodAttributes.FamORAssem;
            }
            else
            {
                intptrctor_visibility = MethodAttributes.Public;
            }
        }
        print_generated_code();
        print("{0}{1} (IntPtr handle) : base (handle)", GetVisibility(intptrctor_visibility), type_name);
        PrintEmptyBody();

        // NSObjectFlag constructor - always present (needed to implement NSCoder for subclasses)
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("protected {0} (NSObjectFlag t) : base (t)", type_name);
        PrintEmptyBody();

        // NSCoder constructor - all filters conforms to NSCoding
        print_generated_code();
        print("[EditorBrowsable (EditorBrowsableState.Advanced)]");
        print("[Export (\"initWithCoder:\")]");
        print("public {0} (NSCoder coder) : base (NSObjectFlag.Empty)", type_name);
        print("{");
        indent++;
        print("IntPtr h;");
        print("if (IsDirectBinding) {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSend_IntPtr (this.Handle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("} else {");
        indent++;
        print("h = global::{0}.Messaging.IntPtr_objc_msgSendSuper_IntPtr (this.SuperHandle, Selector.GetHandle (\"initWithCoder:\"), coder.Handle);", ns.CoreObjCRuntime);
        indent--;
        print("}");
        print("InitializeHandle (h, \"initWithCoder:\");");
        indent--;
        print("}");
        print("");

        // string constructor
        // default is protected (for abstract) but backward compatibility (XAMCORE_2_0) requires some hacks
        v = GetVisibility(filter.StringCtorVisibility);
        if (is_abstract && (v.Length == 0))
        {
            v = "protected ";
        }
        if (v.Length > 0)
        {
            print_generated_code();
            print("{0} {1} (string name) : base (CreateFilter (name))", v, type_name);
            PrintEmptyBody();
        }

        // properties
        GenerateProperties(type);

        // protocols
        GenerateProtocolProperties(type, new HashSet <string> ());

        indent--;
        print("}");

        // namespace closing (it's optional to use namespaces even if it's a bad practice, ref #35283)
        if (indent > 0)
        {
            indent--;
            print("}");
        }
    }
    void GenerateProperties(Type type)
    {
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable(this))
            {
                continue;
            }
            if (AttributeManager.HasAttribute <StaticAttribute> (p))
            {
                continue;
            }

            print("");
            PrintPropertyAttributes(p);
            print_generated_code();

            var ptype = p.PropertyType.Name;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;

            // adding `using ImageIO;` would lead to `error CS0104: 'CGImageProperties' is an ambiguous reference between 'CoreGraphics.CGImageProperties' and 'ImageIO.CGImageProperties'`
            case "CGImageMetadata":
                ptype = "ImageIO.CGImageMetadata";
                break;
            }
            print("public {0} {1} {{", ptype, p.Name);
            indent++;

            // an export will be present (only) if it's defined in a protocol
            var export = AttributeManager.GetCustomAttribute <ExportAttribute> (p);

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            // we can skip the name when it's identical to a protocol selector
            if (name == null)
            {
                if (export == null)
                {
                    throw new BindingException(1072, true, $"Missing [CoreImageFilterProperty] attribute on {0} property {1}", type.Name, p.Name);
                }

                var sel = export.Selector;
                if (sel.StartsWith("input", StringComparison.Ordinal))
                {
                    name = sel;
                }
                else
                {
                    name = "input" + Capitalize(sel);
                }
            }

            if (p.GetGetMethod() != null)
            {
                PrintFilterExport(p, export, setter: false);
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                PrintFilterExport(p, export, setter: true);
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }
    }
Exemplo n.º 8
0
    void GenerateProperties(Type type, Type originalType = null, bool fromProtocol = false)
    {
        foreach (var p in type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (p.IsUnavailable(this))
            {
                continue;
            }
            if (AttributeManager.HasAttribute <StaticAttribute> (p))
            {
                continue;
            }

            print("");

            // an export will be present (only) if it's defined in a protocol
            var export = AttributeManager.GetCustomAttribute <ExportAttribute> (p);

            // this is a bit special since CoreImage filter protocols are much newer than the our generated, key-based bindings
            // so we do not want to advertise the protocol versions since most properties would be incorrectly advertised
            PrintPropertyAttributes(p, originalType, skipTypeInjection: export != null);
            print_generated_code();

            var ptype    = p.PropertyType.Name;
            var nullable = false;
            // keep C# names as they are reserved keywords (e.g. Boolean also exists in OpenGL for Mac)
            switch (ptype)
            {
            case "Boolean":
                ptype = "bool";
                break;

            case "Int32":
                ptype = "int";
                break;

            case "Single":
                ptype = "float";
                break;

            case "String":
                ptype = "string";
                break;

            // adding `using ImageIO;` would lead to `error CS0104: 'CGImageProperties' is an ambiguous reference between 'CoreGraphics.CGImageProperties' and 'ImageIO.CGImageProperties'`
            case "CGImageMetadata":
                ptype = "ImageIO.CGImageMetadata";
                break;

            case "CIVector":
            case "CIColor":
            case "CIImage":
                // protocol-based bindings have annotations - but the older, key-based, versions did not
                if (!fromProtocol)
                {
                    nullable = true;
                }
                break;
            }
            if (AttributeManager.HasAttribute <NullAllowedAttribute> (p))
            {
                nullable = true;
            }
            print("public {0}{1} {2} {{", ptype, nullable ? "?" : "", p.Name);
            indent++;

            var name = AttributeManager.GetCustomAttribute <CoreImageFilterPropertyAttribute> (p)?.Name;
            // we can skip the name when it's identical to a protocol selector
            if (name == null)
            {
                if (export == null)
                {
                    throw new BindingException(1074, true, type.Name, p.Name);
                }

                var sel = export.Selector;
                if (sel.StartsWith("input", StringComparison.Ordinal))
                {
                    name = sel;
                }
                else
                {
                    name = "input" + Capitalize(sel);
                }
            }

            if (p.GetGetMethod() != null)
            {
                PrintFilterExport(p, export, setter: false);
                GenerateFilterGetter(ptype, name);
            }
            if (p.GetSetMethod() != null)
            {
                PrintFilterExport(p, export, setter: true);
                GenerateFilterSetter(ptype, name);
            }

            indent--;
            print("}");
        }
    }
Exemplo n.º 9
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          verbose          = 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           references         = 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 => verbose = false },
            { "v", "Sets verbose mode", v => verbose = true },
            { "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.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, verbose ? 1 : 0) != 0)
            {
                throw ErrorHelper.CreateError(2, compile_output.ToString().Replace("\n", "\n\t"));
            }


            universe = new Universe(UniverseOptions.EnableFunctionPointers | UniverseOptions.ResolveMissingMembers | UniverseOptions.MetadataOnly);
            if (IsDotNet)
            {
                // IKVM tries uses reflection to locate assemblies on disk, but .NET doesn't include reflection so that fails.
                // Instead intercept assembly resolution and look for assemblies where we know they are.
                var resolved_assemblies = new Dictionary <string, Assembly> ();
                universe.AssemblyResolve += (object sender, IKVM.Reflection.ResolveEventArgs rea) => {
                    var an = new AssemblyName(rea.Name);

                    // Check if we've already found this assembly
                    if (resolved_assemblies.TryGetValue(an.Name, out var rv))
                    {
                        return(rv);
                    }

                    // Check if the assembly has already been loaded into IKVM
                    var assemblies = universe.GetAssemblies();
                    foreach (var asm in assemblies)
                    {
                        if (asm.GetName().Name == an.Name)
                        {
                            resolved_assemblies [an.Name] = asm;
                            return(asm);
                        }
                    }

                    // Look in the references to find a matching one and get the path from there.
                    foreach (var r in references)
                    {
                        var fn = Path.GetFileNameWithoutExtension(r);
                        if (fn == an.Name)
                        {
                            rv = universe.LoadFile(r);
                            resolved_assemblies [an.Name] = rv;
                            return(rv);
                        }
                    }

                    throw ErrorHelper.CreateError(1081, rea.Name);
                };
            }

            Assembly api;
            try {
                api = universe.LoadFile(tmpass);
            } catch (Exception e) {
                if (verbose)
                {
                    Console.WriteLine(e);
                }

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

            Assembly baselib;
            try {
                baselib = universe.LoadFile(baselibdll);
            } catch (Exception e) {
                if (verbose)
                {
                    Console.WriteLine(e);
                }

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

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

            Assembly corlib_assembly = universe.LoadFile(LocateAssembly("mscorlib"));
            // Explicitly load our attribute library so that IKVM doesn't try (and fail) to find it.
            universe.LoadFile(GetAttributeLibraryPath());

            TypeManager.Initialize(this, api, corlib_assembly, 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.LoadFile(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, verbose ? 1 : 0) != 0)
            {
                throw ErrorHelper.CreateError(1000, generated_compile_output.ToString().Replace("\n", "\n\t"));
            }
        } finally {
            if (delete_temp)
            {
                Directory.Delete(tmpdir, true);
            }
        }
        return(0);
    }
 public static bool IsOutParameter(ParameterInfo pi)
 {
     return(AttributeManager.HasAttribute <OutAttribute> (pi));
 }