public static int Main2(params string [] args)
        {
            var action   = Action.None;
            var embedder = new Embedder();

            CurrentEmbedder = embedder;

            var os = new OptionSet {
                { "c|compile", "Compiles the generated output", v => embedder.CompileCode = true },
                { "e|extension", "Compiles the generated output as extension safe api", v => embedder.Extension = true },
                { "d|debug", "Build the native library with debug information.", v => embedder.Debug = true },
                { "gen=", $"Target generator (default {embedder.TargetLanguage})", v => embedder.SetTarget(v) },
                { "abi=", "A comma-separated list of ABIs to compile. If not specified, all ABIs applicable to the selected platform will be built. Valid values (also depends on platform): i386, x86_64, armv7, armv7s, armv7k, arm64.", (v) =>
                  {
                      embedder.ABIs.AddRange(v.Split(',').Select((a) => a.ToLowerInvariant()));
                  } },
                { "o|out|outdir=", "Output directory", v => embedder.OutputDirectory = v },
                { "p|platform=", $"Target platform (iOS, macOS [default], macos-[modern|full|system], watchOS, tvOS)", v => embedder.SetPlatform(v) },
                { "vs=", $"Visual Studio version for compilation (unsupported)", v => { throw new EmbeddinatorException(2, $"Option `--vs` is not supported"); } },
                { "h|?|help", "Displays the help", v => action = Action.Help },
                { "v|verbose", "generates diagnostic verbose output", v => ErrorHelper.Verbosity++ },
                { "version", "Display the version information.", v => action = Action.Version },
                { "target=", "The compilation target (staticlibrary, sharedlibrary, framework).", embedder.SetCompilationTarget },
                { "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) {
                          ErrorHelper.Error(26, ex, "Could not parse the command line argument '{0}': {1}", "--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) {
                          ErrorHelper.Error(26, ex, "Could not parse the command line argument '{0}': {1}", "--nowarn", ex.Message);
                      }
                  } },
            };

            var assemblies = os.Parse(args);

            if (action == Action.None && assemblies.Count > 0)
            {
                action = Action.Generate;
            }

            switch (action)
            {
            case Action.None:
            case Action.Help:
                Console.WriteLine($"Embeddinator-4000 {Info.Version} ({Info.Branch}: {Info.Hash})");
                Console.WriteLine("Generates target language bindings for interop with managed code.");
                Console.WriteLine("");
                Console.WriteLine($"Usage: objcgen [options]+ ManagedAssembly1.dll [ManagedAssembly2.dll ...]");
                Console.WriteLine();
                os.WriteOptionDescriptions(Console.Out);
                return(0);

            case Action.Version:
                Console.WriteLine($"Embeddinator-4000 v0.1 ({Info.Branch}: {Info.Hash})");
                return(0);

            case Action.Generate:
                try {
                    var result = embedder.Generate(assemblies);
                    if (embedder.CompileCode && (result == 0))
                    {
                        result = embedder.Compile();
                    }
                    Console.WriteLine("Done");
                    return(result);
                } catch (NotImplementedException e) {
                    throw new EmbeddinatorException(9, true, e, $"The feature `{e.Message}` is not currently supported by the tool");
                }

            default:
                throw ErrorHelper.CreateError(99, "Internal error: invalid action {0}. Please file a bug report with a test case (https://github.com/mono/Embeddinator-4000/issues)", action);
            }
        }
Exemple #2
0
        public override void Process(IEnumerable <Assembly> input)
        {
            foreach (var a in input)
            {
                var pa = new ProcessedAssembly(a);
                // ignoring/warning one is not an option as they could be different (e.g. different builds/versions)
                if (!AddIfUnique(pa))
                {
                    throw ErrorHelper.CreateError(12, $"The assembly name `{pa.Name}` is not unique");
                }

                foreach (var t in GetTypes(a))
                {
                    if (t.IsEnum)
                    {
                        enums.Add(new ProcessedType(t));
                        continue;
                    }

                    if (t.IsInterface)
                    {
                        protocols.Add(new ProcessedType(t));
                    }
                    else
                    {
                        types.Add(new ProcessedType(t));
                    }

                    extension_type = t.HasCustomAttribute("System.Runtime.CompilerServices", "ExtensionAttribute");

                    implement_system_icomparable   = t.Implements("System", "IComparable");
                    implement_system_icomparable_t = t.Implements("System", "IComparable`1");

                    var constructors          = GetConstructors(t).OrderBy((arg) => arg.ParameterCount).ToList();
                    var processedConstructors = PostProcessConstructors(constructors).ToList();
                    if (processedConstructors.Count > 0)
                    {
                        ctors.Add(t, processedConstructors);
                    }

                    var typeEquals       = equals.Where(x => x.Key == t).Select(x => x.Value);
                    var meths            = GetMethods(t).OrderBy((arg) => arg.Name).ToList();
                    var processedMethods = PostProcessMethods(meths, typeEquals).ToList();
                    if (processedMethods.Count > 0)
                    {
                        methods.Add(t, processedMethods);
                    }

                    var props          = new List <PropertyInfo> ();
                    var subscriptProps = new List <PropertyInfo> ();
                    foreach (var pi in GetProperties(t))
                    {
                        var getter = pi.GetGetMethod();
                        var setter = pi.GetSetMethod();
                        // setter only property are valid in .NET and we need to generate a method in ObjC (there's no writeonly properties)
                        if (getter == null)
                        {
                            continue;
                        }

                        // indexers are implemented as methods and object subscripting
                        if ((getter.ParameterCount > 0) || ((setter != null) && setter.ParameterCount > 1))
                        {
                            subscriptProps.Add(pi);
                            continue;
                        }

                        // we can do better than methods for the more common cases (readonly and readwrite)
                        processedMethods.RemoveAll(x => x.Method == getter);
                        processedMethods.RemoveAll(x => x.Method == setter);
                        props.Add(pi);
                    }
                    props = props.OrderBy((arg) => arg.Name).ToList();
                    var processedProperties = PostProcessProperties(props).ToList();
                    if (processedProperties.Count > 0)
                    {
                        properties.Add(t, processedProperties);
                    }

                    if (subscriptProps.Count > 0)
                    {
                        if (subscriptProps.Count > 1)
                        {
                            delayed.Add(ErrorHelper.CreateWarning(1041, $"Indexed properties on {t.Name} is not generated because multiple indexed properties not supported."));
                        }
                        else
                        {
                            subscriptProperties.Add(t, PostProcessSubscriptProperties(subscriptProps).ToList());
                        }
                    }

                    // fields will need to be wrapped within properties
                    var f = GetFields(t).OrderBy((arg) => arg.Name).ToList();
                    var processedFields = PostProcessFields(f).ToList();
                    if (processedFields.Count > 0)
                    {
                        fields.Add(t, processedFields);
                    }
                }
            }
            types = types.OrderBy((arg) => arg.Type.FullName).OrderBy((arg) => types.Contains(arg.Type.BaseType)).ToList();
            Console.WriteLine($"\t{types.Count} types found");

            ErrorHelper.Show(delayed);
        }