public static bool Run(string DoxygenPath, string WorkingDir, DoxygenConfig Config, bool bVerbose) { // Create the output directory if (!Directory.Exists(Config.OutputPath)) { Directory.CreateDirectory(Config.OutputPath); } // Write the doxygen config file string ConfigFilePath = Path.Combine(Config.OutputPath, "Doxyfile"); Config.Write(ConfigFilePath, DoxygenPath); // Spawn doxygen using (Process DoxygenProcess = new Process()) { DoxygenProcess.StartInfo.WorkingDirectory = WorkingDir; DoxygenProcess.StartInfo.FileName = DoxygenPath; DoxygenProcess.StartInfo.Arguments = "\"" + ConfigFilePath + "\" -b"; DoxygenProcess.StartInfo.UseShellExecute = false; DoxygenProcess.StartInfo.RedirectStandardOutput = true; DoxygenProcess.StartInfo.RedirectStandardError = true; using (StreamWriter DoxygenOutputWriter = new StreamWriter(Path.Combine(Config.OutputPath, "Doxygen.log"))) { using (TextWriter SynchronizedDoxygenOutputWriter = TextWriter.Synchronized(DoxygenOutputWriter)) { DoxygenProcess.OutputDataReceived += new DataReceivedEventHandler((x, y) => OutputReceived(x, y, SynchronizedDoxygenOutputWriter, bVerbose)); DoxygenProcess.ErrorDataReceived += new DataReceivedEventHandler((x, y) => OutputReceived(x, y, SynchronizedDoxygenOutputWriter, bVerbose)); try { DoxygenProcess.Start(); DoxygenProcess.BeginOutputReadLine(); DoxygenProcess.BeginErrorReadLine(); DoxygenProcess.WaitForExit(); return(DoxygenProcess.ExitCode == 0); } catch (Exception Ex) { Console.WriteLine(Ex.ToString() + "\n" + Ex.StackTrace); return(false); } } } } }
public static bool Run(string DoxygenPath, string WorkingDir, DoxygenConfig Config, bool bVerbose) { // Create the output directory if (!Directory.Exists(Config.OutputPath)) { Directory.CreateDirectory(Config.OutputPath); } // Write the doxygen config file string ConfigFilePath = Path.Combine(Config.OutputPath, "Doxyfile"); Config.Write(ConfigFilePath); // Spawn doxygen using (Process DoxygenProcess = new Process()) { DoxygenProcess.StartInfo.WorkingDirectory = WorkingDir; DoxygenProcess.StartInfo.FileName = DoxygenPath; DoxygenProcess.StartInfo.Arguments = "\"" + ConfigFilePath + "\" -b"; DoxygenProcess.StartInfo.UseShellExecute = false; DoxygenProcess.StartInfo.RedirectStandardOutput = true; DoxygenProcess.StartInfo.RedirectStandardError = true; using (StreamWriter DoxygenOutputWriter = new StreamWriter(Path.Combine(Config.OutputPath, "Doxygen.log"))) { using (TextWriter SynchronizedDoxygenOutputWriter = TextWriter.Synchronized(DoxygenOutputWriter)) { DoxygenProcess.OutputDataReceived += new DataReceivedEventHandler((x, y) => OutputReceived(x, y, SynchronizedDoxygenOutputWriter, bVerbose)); DoxygenProcess.ErrorDataReceived += new DataReceivedEventHandler((x, y) => ErrorReceived(x, y, SynchronizedDoxygenOutputWriter, bVerbose)); try { DoxygenProcess.Start(); DoxygenProcess.BeginOutputReadLine(); DoxygenProcess.BeginErrorReadLine(); DoxygenProcess.WaitForExit(); return DoxygenProcess.ExitCode == 0; } catch (Exception Ex) { Console.WriteLine(Ex.ToString() + "\n" + Ex.StackTrace); return false; } } } } }
static bool BuildXml(string EngineDir, string TargetInfoPath, string DoxygenPath, string XmlDir, List<string> Filters = null, bool bVerbose = false) { // Read the target that we're building BuildTarget Target = BuildTarget.Read(TargetInfoPath); // Create an invariant list of exclude directories string[] InvariantExcludeDirectories = ExcludeSourceDirectories.Select(x => x.ToLowerInvariant()).ToArray(); // Flatten the target into a list of modules List<BuildModule> InputModules = new List<BuildModule>(); foreach (BuildBinary Binary in Target.Binaries.Where(x => x.Type == "cpp")) { foreach(BuildModule Module in Binary.Modules) { if(Module.Type == "cpp" && !Module.Path.ToLowerInvariant().Contains("\\engine\\plugins\\")) { if(!Module.Path.ToLowerInvariant().Split('\\', '/').Any(x => InvariantExcludeDirectories.Contains(x))) { InputModules.Add(Module); } } } } #if TEST_INDEX_PAGE // Just use all the input modules List<BuildModule> ParsedModules = new List<BuildModule>(InputModules); #else // Filter the input module list if (Filters != null && Filters.Count > 0) { InputModules = new List<BuildModule>(InputModules.Where(x => Filters.Exists(y => y.StartsWith(x.Name + "/", StringComparison.InvariantCultureIgnoreCase)))); } // Sort all the modules into the required build order Console.WriteLine("Sorting module parse order..."); List<BuildModule> SortedModules = SortModules(InputModules); // List all the modules which have circular dependencies foreach (BuildModule Module in SortedModules) { if (SortedModules.Count(x => x == Module) > 1) { Console.WriteLine(" Circular dependency on {0}; module will be parsed twice", Module.Name); } } // Set our error mode so as to not bring up the WER dialog if Doxygen crashes (which it often does) SetErrorMode(0x0007); // Create the output directory Utility.SafeCreateDirectory(XmlDir); // Build all the modules List<BuildModule> ParsedModules = new List<BuildModule>(); Dictionary<string, string> ModuleToTagfile = new Dictionary<string, string>(); for (int Idx = 0; Idx < SortedModules.Count; Idx++) { BuildModule Module = SortedModules[Idx]; Console.WriteLine("Parsing source for {0}... ({1}/{2})", Module.Name, Idx + 1, SortedModules.Count); string ModuleDir = Path.Combine(XmlDir, Module.Name); // Build the configuration for this module DoxygenConfig Config = new DoxygenConfig(Module.Name, Module.Path, ModuleDir); Config.Definitions.AddRange(Module.Definitions.Select(x => x.Replace("DLLIMPORT", "").Replace("DLLEXPORT", ""))); Config.Definitions.AddRange(DoxygenPredefinedMacros); Config.ExpandAsDefined.AddRange(DoxygenExpandedMacros); Config.IncludePaths.AddRange(Module.IncludePaths.Select(x => ExpandIncludePath(EngineDir, x).TrimEnd('\\'))); Config.ExcludePatterns.AddRange(ExcludeSourceDirectories.Select(x => "*/" + x + "/*")); Config.ExcludePatterns.AddRange(ExcludeSourceFiles); Config.OutputTagfile = Path.Combine(ModuleDir, "tags.xml"); // Add all the valid tagfiles foreach (string Dependency in Module.Dependencies) { string Tagfile; if (ModuleToTagfile.TryGetValue(Dependency, out Tagfile)) { Config.InputTagfiles.Add(Tagfile); } } // Run doxygen if (Doxygen.Run(DoxygenPath, Path.Combine(EngineDir, "Source"), Config, bVerbose)) { if (!ModuleToTagfile.ContainsKey(Module.Name)) { ModuleToTagfile.Add(Module.Name, Config.OutputTagfile); ParsedModules.Add(Module); } } else { Console.WriteLine(" Doxygen crashed. Skipping."); } } #endif // Write the modules file WriteModulesXml(XmlDir, ParsedModules); return true; }
static bool BuildMetadata(string DoxygenPath, string EngineDir, string MetadataDir, string MetadataPath) { string MetadataInputPath = Path.Combine(EngineDir, "Source\\Runtime\\CoreUObject\\Public\\UObject\\ObjectBase.h"); Console.WriteLine("Building metadata descriptions from '{0}'...", MetadataInputPath); DoxygenConfig Config = new DoxygenConfig("Metadata", MetadataInputPath, MetadataDir); if (Doxygen.Run(DoxygenPath, Path.Combine(EngineDir, "Source"), Config, true)) { MetadataLookup.Reset(); // Parse the xml output ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_c.xml"), MetadataLookup.ClassTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_i.xml"), MetadataLookup.InterfaceTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_f.xml"), MetadataLookup.FunctionTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_p.xml"), MetadataLookup.PropertyTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_s.xml"), MetadataLookup.StructTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_m.xml"), MetadataLookup.MetaTags); // Rebuild all the reference names now that we've parsed a bunch of new tags MetadataLookup.BuildReferenceNameList(); // Write it to a summary file MetadataLookup.Save(MetadataPath); return true; } return false; }
static bool BuildCodeXml(string EngineDir, string TargetInfoPath, string DoxygenPath, string XmlDir, string ArchivePath, List<string> Filters, BuildActions Actions) { if ((Actions & BuildActions.Clean) != 0) { Console.WriteLine("Cleaning '{0}'", XmlDir); Utility.SafeDeleteDirectoryContents(XmlDir, true); } if ((Actions & BuildActions.Build) != 0) { Console.WriteLine("Building XML..."); Utility.SafeCreateDirectory(XmlDir); // Read the target that we're building BuildTarget Target = new BuildTarget(Path.Combine(EngineDir, "Source"), TargetInfoPath); // Create an invariant list of exclude directories string[] InvariantExcludeDirectories = ExcludeSourceDirectories.Select(x => x.ToLowerInvariant()).ToArray(); // Get the list of folders to filter against List<string> FolderFilters = new List<string>(); if (Filters != null) { foreach (string Filter in Filters) { int Idx = Filter.IndexOf('/'); if (Idx != -1) { FolderFilters.Add("\\" + Filter.Substring(0, Idx) + "\\"); } } } // Flatten the target into a list of modules List<string> InputModules = new List<string>(); foreach (string DirectoryName in Target.DirectoryNames) { for (DirectoryInfo ModuleDirectory = new DirectoryInfo(DirectoryName); ModuleDirectory.Parent != null; ModuleDirectory = ModuleDirectory.Parent) { IEnumerator<FileInfo> ModuleFile = ModuleDirectory.EnumerateFiles("*.build.cs").GetEnumerator(); if (ModuleFile.MoveNext() && (FolderFilters.Count == 0 || FolderFilters.Any(x => ModuleFile.Current.FullName.Contains(x)))) { InputModules.AddUnique(ModuleFile.Current.FullName); break; } } } // Just use all the input modules if (!bIndexOnly) { // Set our error mode so as to not bring up the WER dialog if Doxygen crashes (which it often does) SetErrorMode(0x0007); // Create the output directory Utility.SafeCreateDirectory(XmlDir); // Build all the modules Console.WriteLine("Parsing source..."); // Build the list of definitions List<string> Definitions = new List<string>(); foreach (string Definition in Target.Definitions) { if (!Definition.StartsWith("ORIGINAL_FILE_NAME=")) { Definitions.Add(Definition.Replace("DLLIMPORT", "").Replace("DLLEXPORT", "")); } } // Build a list of input paths List<string> InputPaths = new List<string>(); foreach (string InputModule in InputModules) { foreach (string DirectoryName in Directory.EnumerateDirectories(Path.GetDirectoryName(InputModule), "*", SearchOption.AllDirectories)) { // Find the relative path from the engine directory string NormalizedDirectoryName = DirectoryName; if (NormalizedDirectoryName.StartsWith(EngineDir)) { NormalizedDirectoryName = NormalizedDirectoryName.Substring(EngineDir.Length); } if (!NormalizedDirectoryName.EndsWith("\\")) { NormalizedDirectoryName += "\\"; } // Check we can include it if (!ExcludeSourceDirectories.Any(x => NormalizedDirectoryName.Contains("\\" + x + "\\"))) { if (FolderFilters.Count == 0 || FolderFilters.Any(x => NormalizedDirectoryName.Contains(x))) { InputPaths.Add(DirectoryName); } } } } // Build the configuration for this module DoxygenConfig Config = new DoxygenConfig("UE4", InputPaths.ToArray(), XmlDir); Config.Definitions.AddRange(Definitions); Config.Definitions.AddRange(DoxygenPredefinedMacros); Config.ExpandAsDefined.AddRange(DoxygenExpandedMacros); Config.IncludePaths.AddRange(Target.IncludePaths); Config.ExcludePatterns.AddRange(ExcludeSourceDirectories.Select(x => "*/" + x + "/*")); Config.ExcludePatterns.AddRange(ExcludeSourceFiles); // Run Doxygen if (!Doxygen.Run(DoxygenPath, Path.Combine(EngineDir, "Source"), Config, true)) { Console.WriteLine(" error: Doxygen crashed. Skipping."); return false; } } // Write the modules file File.WriteAllLines(Path.Combine(XmlDir, "modules.txt"), InputModules); } if ((Actions & BuildActions.Archive) != 0) { Console.WriteLine("Creating archive '{0}'", ArchivePath); Utility.CreateTgzFromDir(ArchivePath, XmlDir); } return true; }
static bool BuildCodeMetadata(string DoxygenPath, string EngineDir, string MetadataDir, string MetadataPath, string ArchivePath, BuildActions Actions) { if((Actions & BuildActions.Clean) != 0) { Console.WriteLine("Cleaning '{0}'", MetadataDir); Utility.SafeDeleteDirectoryContents(MetadataDir, true); } if((Actions & BuildActions.Build) != 0) { string MetadataInputPath = Path.Combine(EngineDir, "Source\\Runtime\\CoreUObject\\Public\\UObject\\ObjectBase.h"); Console.WriteLine("Building metadata descriptions from '{0}'...", MetadataInputPath); DoxygenConfig Config = new DoxygenConfig("Metadata", new string[]{ MetadataInputPath }, MetadataDir); if (!Doxygen.Run(DoxygenPath, Path.Combine(EngineDir, "Source"), Config, true)) { return false; } MetadataLookup.Reset(); // Parse the xml output ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_c.xml"), MetadataLookup.ClassTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_i.xml"), MetadataLookup.InterfaceTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_f.xml"), MetadataLookup.FunctionTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_p.xml"), MetadataLookup.PropertyTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_s.xml"), MetadataLookup.StructTags); ParseMetadataTags(Path.Combine(MetadataDir, "xml\\namespace_u_m.xml"), MetadataLookup.MetaTags); // Rebuild all the reference names now that we've parsed a bunch of new tags MetadataLookup.BuildReferenceNameList(); // Write it to a summary file MetadataLookup.Save(MetadataPath); } if ((Actions & BuildActions.Archive) != 0) { Console.WriteLine("Creating archive '{0}'", ArchivePath); Utility.CreateTgzFromDir(ArchivePath, MetadataDir); } return true; }