コード例 #1
0
        /// <summary>
        /// Generate a report showing the number of preprocessed lines in the selected files
        /// </summary>
        /// <param name="ReportFileLocation">Output file for the report</param>
        /// <param name="InputDir"></param>
        /// <param name="Target"></param>
        /// <param name="SourceFileToCompileEnvironment"></param>
        /// <param name="Log">Writer for log output</param>
        public static void Generate(FileReference ReportFileLocation, DirectoryReference InputDir, BuildTarget Target, Dictionary <SourceFile, CompileEnvironment> SourceFileToCompileEnvironment, TextWriter Log)
        {
            Log.WriteLine("Writing {0}...", ReportFileLocation.FullName);

            // Create a map from source file to the number of times it's included
            Dictionary <FileReference, PchInfo> FileToPchInfo = new Dictionary <FileReference, PchInfo>();

            FindPchInfo(Target, SourceFileToCompileEnvironment, FileToPchInfo, Log);

            // Write out a CSV report containing the list of files and their line counts
            using (StreamWriter Writer = new StreamWriter(ReportFileLocation.FullName))
            {
                Writer.WriteLine("PCH,File,Num Includes,Pct Includes");
                foreach (FileReference PchFile in FileToPchInfo.Keys)
                {
                    PchInfo PchInfo = FileToPchInfo[PchFile];
                    foreach (KeyValuePair <SourceFile, int> Pair in PchInfo.IncludedFiles.OrderByDescending(x => x.Value))
                    {
                        if ((Pair.Key.Flags & SourceFileFlags.Pinned) == 0 && (Pair.Key.Flags & SourceFileFlags.External) == 0 && (Pair.Key.Flags & SourceFileFlags.Inline) == 0)
                        {
                            Writer.WriteLine("{0},{1},{2},{3:0.00}", PchFile.GetFileName(), Pair.Key.Location.MakeRelativeTo(InputDir), Pair.Value, (Pair.Value * 100.0) / PchInfo.SourceFiles.Count);
                        }
                    }
                }
            }
        }
コード例 #2
0
        /// <summary>
        /// Generate optimized PCHs which include headers used by a ratio of the source files
        /// </summary>
        /// <param name="Target">The target being built</param>
        /// <param name="SourceFileToCompileEnvironment">Source files to consider</param>
        /// <param name="IncludePaths">Include paths to base output includes from</param>
        /// <param name="SystemIncludePaths">System include paths to base output includes from</param>
        /// <param name="OutputFileContents">Dictionary which receives the files to output</param>
        /// <param name="MinRatio">Ratio of source files which must include a header for it to be included in the pch</param>
        /// <param name="Log">Writer for log output</param>
        public static void GeneratePCHs(BuildTarget Target, Dictionary <SourceFile, CompileEnvironment> SourceFileToCompileEnvironment, IEnumerable <DirectoryReference> IncludePaths, IEnumerable <DirectoryReference> SystemIncludePaths, Dictionary <FileReference, string> OutputFileContents, float MinRatio, TextWriter Log)
        {
            Log.WriteLine("Optimizing precompiled headers...");

            // Create a map from source file to the number of times it's included
            Dictionary <FileReference, PchInfo> FileToPchInfo = new Dictionary <FileReference, PchInfo>();

            FindPchInfo(Target, SourceFileToCompileEnvironment, FileToPchInfo, Log);

            // Create an ordering of all the modules
            Dictionary <BuildModule, int> ModuleToIndex = new Dictionary <BuildModule, int>();

            FindModuleOrder(SourceFileToCompileEnvironment.Keys.Select(x => x.Module).Distinct(), ModuleToIndex, new HashSet <BuildModule>());

            // Create the output files
            foreach (FileReference PchFile in FileToPchInfo.Keys)
            {
                PchInfo PchInfo = FileToPchInfo[PchFile];

                // Get the minimum number of includes to use in the PCH
                int MinIncludes = (int)(MinRatio * PchInfo.SourceFiles.Count);

                // Get a list of all the files to include above a threshold
                List <SourceFile> IncludeFiles = new List <SourceFile>();
                foreach (SourceFile IncludedFile in PchInfo.IncludedFiles.Where(x => x.Value >= MinIncludes).OrderByDescending(x => x.Value).Select(x => x.Key))
                {
                    if ((IncludedFile.Flags & SourceFileFlags.Pinned) == 0 && (IncludedFile.Flags & SourceFileFlags.External) == 0 && (IncludedFile.Flags & SourceFileFlags.Inline) == 0 && PchInfo.PublicIncludePathModules.Contains(IncludedFile.Module))
                    {
                        IncludeFiles.Add(IncludedFile);
                    }
                }

                // Generate the output file text
                StringBuilder Contents = new StringBuilder();
                using (StringWriter Writer = new StringWriter(Contents))
                {
                    Writer.WriteLine("// Copyright 1998-{0} Epic Games, Inc. All Rights Reserved.", DateTime.Now.Year);
                    Writer.WriteLine();
                    Writer.WriteLine("#pragma once");
                    foreach (IGrouping <BuildModule, SourceFile> Group in IncludeFiles.GroupBy(x => x.Module).OrderBy(x => ModuleToIndex[x.Key]))
                    {
                        Writer.WriteLine();
                        Writer.WriteLine("// From {0}:", Group.Key.Name);
                        foreach (SourceFile IncludeFile in Group)
                        {
                            string Include;
                            if (SourceFile.TryFormatInclude(PchFile.Directory, IncludeFile.Location, IncludePaths, SystemIncludePaths, out Include))
                            {
                                Writer.WriteLine("#include {0}", Include);
                            }
                        }
                    }
                }

                // Add it to the output map
                OutputFileContents.Add(PchFile, Contents.ToString());
            }
        }
コード例 #3
0
        /// <summary>
        /// Find a mapping from PCH to the most included files by the files using it
        /// </summary>
        /// <param name="SourceFileToCompileEnvironment">Files being compiled</param>
        /// <param name="PchToIncludeFileCount">Mapping of PCH to included files</param>
        /// <param name="Log">Writer for log messages</param>
        static void FindPchInfo(BuildTarget Target, Dictionary <SourceFile, CompileEnvironment> SourceFileToCompileEnvironment, Dictionary <FileReference, PchInfo> FileToPchInfo, TextWriter Log)
        {
            // Create a map of module to the shared PCH it uses
            Dictionary <BuildModule, FileReference> ModuleToPch = new Dictionary <BuildModule, FileReference>();

            // Recurse through all the includes for each source file
            Dictionary <FileReference, int> UsingPchCount = new Dictionary <FileReference, int>();

            foreach (KeyValuePair <SourceFile, CompileEnvironment> Pair in SourceFileToCompileEnvironment)
            {
                // Figure out which module it's in
                BuildModule Module = Pair.Key.Module;

                // Determine which PCH it's using
                FileReference UsingPch;
                if (!ModuleToPch.TryGetValue(Module, out UsingPch))
                {
                    if (Module.PrivatePCH != null)
                    {
                        UsingPch = Module.PrivatePCH;
                    }
                    else if (Module.PCHUsage == BuildModulePCHUsage.UseExplicitOrSharedPCHs || Module.PCHUsage == BuildModulePCHUsage.UseSharedPCHs || Module.PCHUsage == BuildModulePCHUsage.Default)
                    {
                        HashSet <BuildModule> PossibleModules = new HashSet <BuildModule>(Module.NonCircularDependencies.Where(x => x.SharedPCH != null));
                        foreach (BuildModule PossibleModule in PossibleModules.ToArray())
                        {
                            PossibleModules.ExceptWith(PossibleModule.NonCircularDependencies);
                        }
                        if (PossibleModules.Count == 0)
                        {
                            Log.WriteLine("warning: No valid PCH found for {0}", Module);
                        }
                        else if (PossibleModules.Count == 1)
                        {
                            UsingPch = PossibleModules.First().SharedPCH;
                        }
                        else
                        {
                            Log.WriteLine("warning: Multiple valid PCHs for {0}: {1}", Module, String.Join(",", PossibleModules.Select(x => x.Name)));
                        }
                    }
                    else
                    {
                        Log.WriteLine("warning: Unknown PCH for {0}", Module);
                    }
                    ModuleToPch[Module] = UsingPch;
                }

                // Make sure we're using a PCH
                if (UsingPch != null)
                {
                    // Get the info for this PCH
                    PchInfo Info;
                    if (!FileToPchInfo.TryGetValue(UsingPch, out Info))
                    {
                        Info = new PchInfo(UsingPch);

                        Info.PublicIncludePathModules.Add(Target.Modules.First(x => UsingPch.IsUnderDirectory(x.Directory)));
                        for (int Idx = 0; Idx < Info.PublicIncludePathModules.Count; Idx++)
                        {
                            BuildModule NextModule = Info.PublicIncludePathModules[Idx];
                            Info.PublicIncludePathModules.UnionWith(NextModule.PublicDependencyModules.Except(NextModule.CircularlyReferencedModules));
                        }

                        FileToPchInfo.Add(UsingPch, Info);
                    }

                    // Increment the number of files using this PCH
                    Info.SourceFiles.Add(Pair.Key.Location);

                    // Find all the included files
                    HashSet <SourceFile> IncludedFiles = new HashSet <SourceFile>();
                    FindIncludedFiles(Pair.Key, IncludedFiles);

                    // Update the counts for each one
                    foreach (SourceFile IncludedFile in IncludedFiles)
                    {
                        int IncludeCount;
                        Info.IncludedFiles.TryGetValue(IncludedFile, out IncludeCount);
                        Info.IncludedFiles[IncludedFile] = IncludeCount + 1;
                    }
                }
            }
        }