public static InterfaceReflector FromCSharpSource(List <string> sourceFiles, List <string> referenceSourceFiles, List <string> referenceDllFiles, bool referenceBindGem)
        {
            var ir = new InterfaceReflector();

            ir.CompileCSharpSource(sourceFiles, referenceSourceFiles, referenceDllFiles, referenceBindGem);
            return(ir);
        }
        public static InterfaceReflector FromAssembly(string assembly, List <string> referenceAssemblies)
        {
            var ir = new InterfaceReflector();

            ir.LoadFromAssembly(assembly, referenceAssemblies);
            return(ir);
        }
Пример #3
0
        public static void WrappedMain(string[] args)
        {
            bool referenceBindGem = false;
            var  opts             = new OptionSet()
            {
                { "r|ref=", "Reference metadata from specified built file", v => ReferenceDLLFiles.Add(v) },
                { "R|srcref=", "Reference source file, but don't generate code for them", v => ReferenceSourceFiles.Add(Path.GetFullPath(v)) },
                { "include=", "Reference source file, but don't generate code for them", v => ReferenceSourceFiles.Add(Path.GetFullPath(v)) },
                { "o|out=", "Output base file, without extensions", v => OutFile = v },
                { "cppInclude=", "Cpp #include statement to generate in the header", v => CppIncludes.Add(v) },
                { "cppSrcInclude=", "Cpp #include statement to generate in the source", v => CppSrcIncludes.Add(v) },
                { "j|pure-js", "Generate pure JS bindings for components and structs only", v => PureJS = (v != null) },
                { "v|verbose", "Verbose output, including compilation errors", v => Verbose = true },
                { "internal", "Reference BindGem.exe for bindings attributes", v => referenceBindGem = true },
                { "d|devel", "Enable development build", v => Development = true },
                { "dots", "Enable DOTS mode", v => DOTS = true },
                { "define_guard=", "Define guard to use", v => DefineGuard = v },
            };

            try {
                SourceFiles = opts.Parse(args);
            }
            catch (OptionException e) {
                Console.Write("bindgen: ");
                Console.WriteLine(e.Message);
                opts.WriteOptionDescriptions(Console.Out);
                return;
            }

            if (OutFile == null)
            {
                opts.WriteOptionDescriptions(Console.Out);
                FatalError($"output must be specified with -o");
            }

            if (DOTS && PureJS)
            {
                opts.WriteOptionDescriptions(Console.Out);
                FatalError("Can't specify both DOTS mode and PureJS mode");
            }

            if (DefineGuard == null)
            {
                DefineGuard = $"BINDGEM_BIND_{BindGem.BaseOutputName}_IMPL";
            }

            // C# compiler fails on Windows on paths that are delimited with forward slashes, so normalize all inputs with forward
            // slashes to use backslashes instead.
            if (Path.DirectorySeparatorChar == '\\')
            {
                for (int i = 0; i < ReferenceDLLFiles.Count; ++i)
                {
                    ReferenceDLLFiles[i] = ReferenceDLLFiles[i].Replace('/', Path.DirectorySeparatorChar);
                }
                for (int i = 0; i < ReferenceSourceFiles.Count; ++i)
                {
                    ReferenceSourceFiles[i] = ReferenceSourceFiles[i].Replace('/', Path.DirectorySeparatorChar);
                }
                OutFile = OutFile.Replace('/', Path.DirectorySeparatorChar);
                for (int i = 0; i < CppIncludes.Count; ++i)
                {
                    CppIncludes[i] = CppIncludes[i].Replace('/', Path.DirectorySeparatorChar);
                }
                for (int i = 0; i < SourceFiles.Count; ++i)
                {
                    SourceFiles[i] = SourceFiles[i].Replace('/', Path.DirectorySeparatorChar);
                }
            }

            // Collapse duplicate input entries
            ReferenceSourceFiles = ReferenceSourceFiles.Distinct().ToList();
            CppIncludes          = CppIncludes.Distinct().ToList();
            CppSrcIncludes       = CppSrcIncludes.Distinct().ToList();

            InterfaceReflector reflector;

            if (DOTS)
            {
                if (SourceFiles.Count != 1 || ReferenceSourceFiles.Count != 0 || referenceBindGem)
                {
                    FatalError($"DOTS mode requires exactly one assembly as input source, and no -R srcrefs (only -r assembly refs allowed).  --internal is also not allowed.");
                }

                reflector = InterfaceReflector.FromAssembly(SourceFiles[0], ReferenceDLLFiles);
            }
            else
            {
                reflector = InterfaceReflector.FromCSharpSource(SourceFiles, ReferenceSourceFiles, ReferenceDLLFiles, referenceBindGem);
            }

            // Validate that the types we loaded are something we can support
            foreach (var s in reflector.Structs)
            {
                TypeUtils.ValidateAllowedObjectType(s);
            }
            foreach (var s in reflector.Interfaces)
            {
                TypeUtils.ValidateAllowedObjectType(s);
            }
            foreach (var s in reflector.Classes)
            {
                TypeUtils.ValidateAllowedObjectType(s);
            }

            foreach (var s in reflector.Structs)
            {
                TypeUtils.PreprocessTypeFields(s, 32);
                TypeUtils.PreprocessTypeFields(s, 64);
            }

            var languagesToGenerate = (SourceLanguage[])Enum.GetValues(typeof(SourceLanguage));

            if (DOTS)
            {
                languagesToGenerate = new[] {
                    SourceLanguage.CPlusPlus,
                    SourceLanguage.CPlusPlusHeader
                };
            }
            else if (PureJS)
            {
                languagesToGenerate = new[] {
                    SourceLanguage.JavaScript,
                    SourceLanguage.TypeScriptDefinition,
                    SourceLanguage.JSDoc,
                    SourceLanguage.CSharp
                };
            }

            var generators = new List <ILanguageHandler>();

            if (DOTS)
            {
                generators.Add(new CppBindingsGenerator());
            }
            else
            {
                generators.Add(new EmscriptenGenerator());
                if (!PureJS)
                {
                    generators.Add(new CppBindingsGenerator());
                }
                generators.Add(new TypeScriptDefinitionGenerator());
                generators.Add(new JSDocGenerator());
                generators.Add(new CGenerator());
                generators.Add(new CsBindingsGenerator());
            }

            foreach (var generator in generators)
            {
                reflector.ExportedEnums.ForEach(t => generator.HandleEnumType(t));
                reflector.ExportedStructs.Where(t => !t.IsComponentType()).ToList().ForEach(t => generator.HandleStructType(t));
                reflector.ExportedStructs.Where(t => t.IsComponentType()).ToList().ForEach(t => generator.HandleComponentType(t));
                reflector.ExportedDelegates.ForEach(t => generator.HandleCallbackType(t));
                reflector.ExportedInterfaces.Where(t => t.HasAttribute("NonSharedPtr") || t.HasAttribute("SharedPtr") || t.HasAttribute("Service")).ToList().ForEach(t => generator.HandleInterfaceType(t));
                reflector.ExportedClasses.Where(t => t.IsSystemType() || t.IsSystemFenceType()).ToList().ForEach(t => generator.HandleSystemType(t));
            }

            foreach (var sourceLang in languagesToGenerate)
            {
                var lh = new List <ILanguageHandler>(generators);
                lh.Sort(Comparer <ILanguageHandler> .Create((l1, l2) =>
                                                            l2.GeneratedSourceWeight(sourceLang).CompareTo(l1.GeneratedSourceWeight(sourceLang))));
                var src = new StringBuilder();
                foreach (var gen in lh)
                {
                    var langSrc = gen.GetGeneratedSource(sourceLang);
                    if (langSrc == null)
                    {
                        continue;
                    }
                    src.AppendLine(langSrc);
                }

                if (src.Length == 0)
                {
                    continue;
                }

                var fileName = OutFile + ExtensionForLanguage(sourceLang);
                var f        = new StreamWriter(fileName);
                src.Insert(0, PreambleForLanguage(sourceLang));
                src.Append(PostambleForLanguage(sourceLang));
                // sanitize line endings
                src = src.Replace("\r\n", "\n");
                f.Write(src);
                f.Close();
            }
        }