Example #1
0
        public override bool Execute()
        {
            PrepareExecute();

            ExtensibilityDriver.Instance.LoadExtensions(SharpGenLogger,
                                                        ExtensionAssemblies.Select(x => x.ItemSpec).ToArray());

            var config = new ConfigFile
            {
                Files = ConfigFiles.Select(file => file.ItemSpec).ToList(),
                Id    = "SharpGen-MSBuild"
            };

            try
            {
                config = LoadConfig(config);

                return(!SharpGenLogger.HasErrors && Execute(config));
            }
            catch (CodeGenFailedException ex)
            {
                SharpGenLogger.Fatal("Internal SharpGen exception", ex);
                return(false);
            }
        }
        public override bool Execute()
        {
            PrepareExecute();

            var cacheItemSpec = PropertyCache.ItemSpec;

            Utilities.RequireAbsolutePath(cacheItemSpec, nameof(PropertyCache));

            var currentHash = HashSettings();

            bool writeNeeded;

            if (File.Exists(cacheItemSpec))
            {
                ReadOnlySpan <byte> currentHashSpan = currentHash;
                ReadOnlySpan <byte> cachedHash      = File.ReadAllBytes(cacheItemSpec);

                if (currentHashSpan.SequenceEqual(cachedHash))
                {
                    SharpGenLogger.Message("Properties hash matches cached value.");
                    writeNeeded = false;
                }
                else
                {
                    SharpGenLogger.Message("Properties hash mismatch, writing a new property cache file.");
                    writeNeeded = true;
                }
            }
            else
            {
                SharpGenLogger.Message("Properties cache doesn't exist.");
                writeNeeded = true;
            }

            if (writeNeeded)
            {
                File.WriteAllBytes(cacheItemSpec, currentHash);
            }

            return(true);
        }
Example #3
0
        private ConfigFile LoadConfig(ConfigFile config)
        {
            config = ConfigFile.Load(config, Macros, SharpGenLogger);

            var sdkResolver = new SdkResolver(SharpGenLogger);

            SharpGenLogger.Message("Resolving SDKs...");
            foreach (var cfg in config.ConfigFilesLoaded)
            {
                SharpGenLogger.Message("Resolving SDK for Config {0}", cfg);
                foreach (var sdk in cfg.Sdks)
                {
                    SharpGenLogger.Message("Resolving {0}: Version {1}", sdk.Name, sdk.Version);
                    foreach (var directory in sdkResolver.ResolveIncludeDirsForSdk(sdk))
                    {
                        SharpGenLogger.Message("Resolved include directory {0}", directory);
                        cfg.IncludeDirs.Add(directory);
                    }
                }
            }

            return(config);
        }
Example #4
0
        private bool Execute(ConfigFile config)
        {
            config.GetFilesWithIncludesAndExtensionHeaders(
                out var configsWithHeaders,
                out var configsWithExtensionHeaders
                );

            var cppHeaderGenerator = new CppHeaderGenerator(SharpGenLogger, OutputPath);

            var cppHeaderGenerationResult = cppHeaderGenerator.GenerateCppHeaders(config, configsWithHeaders, configsWithExtensionHeaders);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var resolver = new IncludeDirectoryResolver(SharpGenLogger);

            resolver.Configure(config);

            var castXml = new CastXmlRunner(SharpGenLogger, resolver, CastXmlExecutable.ItemSpec, CastXmlArguments)
            {
                OutputPath = OutputPath
            };

            var macroManager = new MacroManager(castXml);

            var cppExtensionGenerator = new CppExtensionHeaderGenerator();

            var module = config.CreateSkeletonModule();

            macroManager.Parse(Path.Combine(OutputPath, config.HeaderFileName), module);

            cppExtensionGenerator.GenerateExtensionHeaders(
                config, OutputPath, module, configsWithExtensionHeaders, cppHeaderGenerationResult.UpdatedConfigs
                );

            GenerateInputsCache(
                macroManager.IncludedFiles
                .Concat(config.ConfigFilesLoaded.Select(x => x.AbsoluteFilePath))
                .Concat(configsWithExtensionHeaders.Select(x => Path.Combine(OutputPath, x.ExtensionFileName)))
                .Select(s => Utilities.FixFilePath(s, Utilities.EmptyFilePathBehavior.Ignore))
                .Where(x => x != null)
                .Distinct()
                );

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            // Run the parser
            var parser = new CppParser(SharpGenLogger, config)
            {
                OutputPath = OutputPath
            };

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            CppModule group;

            using (var xmlReader = castXml.Process(parser.RootConfigHeaderFileName))
            {
                // Run the C++ parser
                group = parser.Run(module, xmlReader);
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            config.ExpandDynamicVariables(SharpGenLogger, group);

            var docLinker    = new DocumentationLinker();
            var typeRegistry = new TypeRegistry(SharpGenLogger, docLinker);
            var namingRules  = new NamingRulesManager();

            var globalNamespace = new GlobalNamespaceProvider();

            foreach (var nameOverride in GlobalNamespaceOverrides)
            {
                var wellKnownName = nameOverride.ItemSpec;
                var overridenName = nameOverride.GetMetadata("Override");

                if (string.IsNullOrEmpty(overridenName))
                {
                    continue;
                }

                if (Enum.TryParse(wellKnownName, out WellKnownName name))
                {
                    globalNamespace.OverrideName(name, overridenName);
                }
                else
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidGlobalNamespaceOverride,
                        "Invalid override of \"{0}\": unknown class name, ignoring the override.",
                        wellKnownName
                        );
                }
            }

            // Run the main mapping process
            var transformer = new TransformManager(
                globalNamespace,
                namingRules,
                SharpGenLogger,
                typeRegistry,
                docLinker,
                new ConstantManager(namingRules, docLinker)
                );

            var(solution, defines) = transformer.Transform(group, config);

            var consumerConfig = new ConfigFile
            {
                Id            = ConsumerBindMappingConfigId,
                IncludeProlog = { cppHeaderGenerationResult.Prologue },
                Extension     = new List <ExtensionBaseRule>(defines)
            };

            var(bindings, generatedDefines) = transformer.GenerateTypeBindingsForConsumers();

            consumerConfig.Bindings.AddRange(bindings);
            consumerConfig.Extension.AddRange(generatedDefines);

            consumerConfig.Mappings.AddRange(
                docLinker.GetAllDocLinks().Select(
                    link => new MappingRule
            {
                DocItem          = link.cppName,
                MappingNameFinal = link.cSharpName
            }
                    )
                );

            GenerateConfigForConsumers(consumerConfig);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationCacheItemSpec = DocumentationCache.ItemSpec;

            Utilities.RequireAbsolutePath(documentationCacheItemSpec, nameof(DocumentationCache));

            var cache = File.Exists(documentationCacheItemSpec)
                            ? DocItemCache.Read(documentationCacheItemSpec)
                            : new DocItemCache();

            DocumentationLogger docLogger = new(SharpGenLogger) { MaxLevel = LogLevel.Warning };
            var docContext = new Lazy <DocumentationContext>(() => new DocumentationContext(docLogger));

            ExtensibilityDriver.Instance.DocumentModule(SharpGenLogger, cache, solution, docContext).Wait();

            if (docContext.IsValueCreated)
            {
                Regex[] silencePatterns    = null;
                var     docLogLevelDefault = DocumentationFailuresAsErrors ? LogLevel.Error : LogLevel.Warning;

                foreach (var queryFailure in docContext.Value.Failures)
                {
                    if (silencePatterns == null)
                    {
                        silencePatterns = new Regex[SilenceMissingDocumentationErrorIdentifierPatterns.Length];
                        for (var i = 0; i < silencePatterns.Length; i++)
                        {
                            silencePatterns[i] = new Regex(
                                SilenceMissingDocumentationErrorIdentifierPatterns[i].ItemSpec,
                                RegexOptions.CultureInvariant
                                );
                        }
                    }

                    if (silencePatterns.Length != 0)
                    {
                        bool SilencePredicate(Regex x) => x.Match(queryFailure.Query).Success;

                        if (silencePatterns.Any(SilencePredicate))
                        {
                            continue;
                        }
                    }

                    var providerName = queryFailure.FailedProviderName ?? "<null>";

                    var docLogLevel = queryFailure.TreatProviderFailuresAsErrors
                                          ? docLogLevelDefault
                                          : docLogLevelDefault > LogLevel.Warning
                                              ? LogLevel.Warning
                                              : docLogLevelDefault;

                    if (queryFailure.Exceptions == null || queryFailure.Exceptions.Count <= 1)
                    {
                        SharpGenLogger.LogRawMessage(
                            docLogLevel,
                            LoggingCodes.DocumentationProviderInternalError,
                            "Documentation provider [{0}] query for \"{1}\" failed.",
                            queryFailure.Exceptions?.FirstOrDefault(),
                            providerName,
                            queryFailure.Query
                            );
                    }
                    else
                    {
                        var exceptionsCount = queryFailure.Exceptions.Count;
                        for (var index = 0; index < exceptionsCount; index++)
                        {
                            var exception = queryFailure.Exceptions[index];

                            SharpGenLogger.LogRawMessage(
                                docLogLevel,
                                LoggingCodes.DocumentationProviderInternalError,
                                "Documentation provider [{0}] query for \"{1}\" failed ({2}/{3}).",
                                exception,
                                providerName,
                                queryFailure.Query,
                                index + 1,
                                exceptionsCount
                                );
                        }
                    }
                }
            }

            cache.WriteIfDirty(documentationCacheItemSpec);

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var documentationFiles = new Dictionary <string, XmlDocument>();

            foreach (var file in ExternalDocumentation)
            {
                using var stream = File.OpenRead(file.ItemSpec);

                var xml = new XmlDocument();
                xml.Load(stream);
                documentationFiles.Add(file.ItemSpec, xml);
            }

            PlatformDetectionType platformMask = 0;

            foreach (var platform in Platforms)
            {
                if (!Enum.TryParse <PlatformDetectionType>(platform.ItemSpec, out var parsedPlatform))
                {
                    SharpGenLogger.Warning(
                        LoggingCodes.InvalidPlatformDetectionType,
                        "The platform type {0} is an unknown platform to SharpGenTools. Falling back to Any platform detection.",
                        platform
                        );
                    platformMask = PlatformDetectionType.Any;
                }
                else
                {
                    platformMask |= parsedPlatform;
                }
            }

            if (platformMask == 0)
            {
                platformMask = PlatformDetectionType.Any;
            }

            if (SharpGenLogger.HasErrors)
            {
                return(false);
            }

            var generator = new RoslynGenerator(
                SharpGenLogger,
                globalNamespace,
                docLinker,
                new ExternalDocCommentsReader(documentationFiles),
                new GeneratorConfig
            {
                Platforms = platformMask
            }
                );

            generator.Run(solution, GeneratedCodeFolder);

            return(!SharpGenLogger.HasErrors);
        }