Beispiel #1
0
        private static ProjectStats GetStats(IEnumerable <Pip> pips, BuildGraph graph)
        {
            ProjectStats     stats       = default(ProjectStats);
            HashSet <string> inputFiles  = new HashSet <string>();
            HashSet <string> outputFiles = new HashSet <string>();

            foreach (Pip pip in pips)
            {
                Process process = pip as Process;

                if (process != null)
                {
                    stats.ProcessCount++;
                    foreach (int consumes in process.Consumes)
                    {
                        File f;
                        if (graph.Files.TryGetValue(consumes, out f))
                        {
                            inputFiles.Add(f.Location);
                        }
                    }

                    foreach (int produces in process.Produces)
                    {
                        File f;
                        if (graph.Files.TryGetValue(produces, out f))
                        {
                            outputFiles.Add(f.Location);
                        }
                    }

                    continue;
                }

                CopyFile copyFile = pip as CopyFile;
                if (copyFile != null)
                {
                    stats.CopyFileCount++;
                    continue;
                }

                WriteFile writeFile = pip as WriteFile;
                if (writeFile != null)
                {
                    stats.WriteFileCount++;
                    continue;
                }
            }

            stats.CppFileCount    = inputFiles.Where(f => f.EndsWith(".cpp", StringComparison.OrdinalIgnoreCase)).Count();
            stats.CsFileCount     = inputFiles.Where(f => f.EndsWith(".cs", StringComparison.OrdinalIgnoreCase)).Count();
            stats.OutputFileCount = outputFiles.Count;

            return(stats);
        }
Beispiel #2
0
        private void Duplicate(int multiplicationFactor, int maxPipsPerSpec)
        {
            Console.WriteLine("Duplicating Graph {0} times", multiplicationFactor);

            // Take a snapshot of the pips currently in the graph before any multiplication is applied.
            Process[]   originalProcesses  = m_graph.Pips.Values.OfType <Process>().ToArray();
            WriteFile[] originalWriteFiles = m_graph.Pips.Values.OfType <WriteFile>().ToArray();

            // The basic strategy here is to clone every pip in a parallelizeable way. Each pip gets n copies with same
            // source inputs, but different outputs. Dependencies within the original set are translated to the new set
            for (int i = 0; i < multiplicationFactor; i++)
            {
                Console.WriteLine("Duplicating Graph iteration {0}", i);
                string newRoot = i.ToString(CultureInfo.InvariantCulture);
                for (int j = 0; j < originalProcesses.Length; j++)
                {
                    Process    p = originalProcesses[j];
                    List <int> clonedConsumes = new List <int>(p.Consumes.Count);
                    List <int> clonedProduces = new List <int>(p.Produces.Count);
                    foreach (int consume in p.Consumes)
                    {
                        int producingPip;
                        if (m_graph.OutputArtifactToProducingPip.TryGetValue(consume, out producingPip))
                        {
                            Process   process   = m_graph.Pips[producingPip] as Process;
                            WriteFile writeFile = m_graph.Pips[producingPip] as WriteFile;
                            if (process != null || writeFile != null)
                            {
                                // This is an output file created by a pip that will also be cloned. We need to translate it to the new path
                                File f;
                                if (!m_graph.Files.TryGetValue(consume, out f))
                                {
                                    throw new MimicGeneratorException("Failed to find referenced file with id: {0}", consume);
                                }

                                clonedConsumes.Add(m_graph.DuplicateFile(f, newRoot));
                                continue;
                            }
                        }

                        // If the path isn't translated based on cloning, just consume it directly.
                        clonedConsumes.Add(consume);
                    }

                    foreach (int produce in p.Produces)
                    {
                        File f;
                        if (!m_graph.Files.TryGetValue(produce, out f))
                        {
                            throw new MimicGeneratorException("Failed to find referenced file with id: {0}", produce);
                        }

                        clonedProduces.Add(m_graph.DuplicateFile(f, newRoot));
                    }

                    Process cloned   = new Process(0, string.Empty, BuildGraph.DuplicatePath(GetSpecName(p.Spec, j, maxPipsPerSpec), newRoot), clonedProduces, clonedConsumes, p.Semaphores);
                    int     newPipId = m_graph.AddWithNewPipId(cloned, p.PipId);

                    // Need to register all of the outputs of the cloned pip so consumers reference it as an output
                    // rather than a source file when specs are generated
                    foreach (var file in clonedProduces)
                    {
                        m_graph.OutputArtifactToProducingPip.TryAdd(file, newPipId);
                    }
                }

                for (int j = 0; j < originalWriteFiles.Length; j++)
                {
                    WriteFile wf = originalWriteFiles[j];
                    File      f;
                    if (!m_graph.Files.TryGetValue(wf.Destination, out f))
                    {
                        throw new MimicGeneratorException("Failed to find referenced file with id: {0}", wf.Destination);
                    }

                    int       clonedDestination = m_graph.DuplicateFile(f, newRoot);
                    WriteFile cloned            = new WriteFile(0, string.Empty, BuildGraph.DuplicatePath(GetSpecName(wf.Spec, j, maxPipsPerSpec), newRoot), clonedDestination);
                    int       newPipId          = m_graph.AddWithNewPipId(cloned, wf.PipId);
                    m_graph.OutputArtifactToProducingPip.TryAdd(clonedDestination, newPipId);
                }
            }

            // TODO: Mirror CopyFile pips
        }
Beispiel #3
0
        /// <summary>
        /// Writes out build files
        /// </summary>
        public bool WriteBuildFiles()
        {
            bool success = true;

            Console.WriteLine("Writing build files and inputs");

            Directory.CreateDirectory(m_outputDirectory);

            using (var textWriter = new StreamWriter(Path.Combine(m_outputDirectory, "stats.txt")))
            {
                m_buildGraph.OutputFileStats.Write(textWriter);
                m_buildGraph.SourceFileStats.Write(textWriter);
                m_buildGraph.PipDurationStats.Write(textWriter);
                m_buildGraph.BuildInterval.Write(textWriter);
                m_buildGraph.ProcessPipStats.Write(textWriter);
            }

            // Write out the cache config file
            System.IO.File.WriteAllText(
                Path.Combine(m_outputDirectory, "cacheConfig.json"),
                GetEmbeddedResourceFile("Tool.MimicGenerator.Content.CacheConfig.json"));
            WriteBuildScript();

            var provider = new LanguageProvider(m_language);

            using (var configWriter = provider.CreateConfigWriter(Path.Combine(m_outputDirectory, "mimic")))
            {
                using (var moduleWriter = provider.CreateModuleWriter(m_outputDirectory, "MimicModule", new string[] { "{EngineLayout.DefaultMounts.DeploymentRootPath.Path.Combine('BuildXL.Transformers.Runners.dll')}" }))
                {
                    configWriter.AddModule(moduleWriter);

                    // Write each pip into its spec file
                    using (Timer updateTimer = new Timer(ReportProgress, null, TimeSpan.FromSeconds(30), TimeSpan.FromSeconds(30)))
                    {
                        Parallel.ForEach(m_specFileToPipsLookup, specPips =>
                        {
                            using (var writer = provider.CreateSpecWriter(RemapPath(specPips.Key)))
                            {
                                List <Process> allProcesses = new List <Process>();
                                foreach (var p in specPips)
                                {
                                    Interlocked.Increment(ref m_processesEncountered);

                                    lock (moduleWriter)
                                    {
                                        int lengthToStrip = m_outputDirectory.Length;
                                        if (!(m_outputDirectory.EndsWith(@"/", StringComparison.Ordinal) || m_outputDirectory.EndsWith(@"\", StringComparison.Ordinal)))
                                        {
                                            lengthToStrip++;
                                        }

                                        string specPath = writer.AbsolutePath.Remove(0, lengthToStrip);
                                        moduleWriter.AddSpec(specPath, writer);
                                    }

                                    Process process = p as Process;
                                    if (process != null)
                                    {
                                        allProcesses.Add(process);
                                    }

                                    CopyFile copyFile = p as CopyFile;
                                    if (copyFile != null)
                                    {
                                        bool isDirectory;
                                        bool isResponseFile;
                                        writer.AddCopyFile(
                                            GetProcessOutputName(p.PipId),
                                            GetInputExpression(copyFile.Source, writer, configWriter, out isDirectory, out isResponseFile),
                                            GetOutputExpression(copyFile.Destination, configWriter));
                                        if (isDirectory)
                                        {
                                            throw new MimicGeneratorException("CopyFile shouldn't produce a directory");
                                        }
                                    }

                                    WriteFile writeFile = p as WriteFile;
                                    if (writeFile != null)
                                    {
                                        bool ignore = false;
                                        if (m_ignoreResponseFiles)
                                        {
                                            File f;
                                            if (m_buildGraph.Files.TryGetValue(writeFile.Destination, out f))
                                            {
                                                if (f.Location.EndsWith(ResponseFileName, StringComparison.OrdinalIgnoreCase))
                                                {
                                                    ignore = true;
                                                }
                                            }
                                        }

                                        if (!ignore)
                                        {
                                            writer.AddWriteFile(GetProcessOutputName(p.PipId), GetOutputExpression(writeFile.Destination, configWriter));
                                        }
                                    }

                                    SealDirectory sealDirectory = p as SealDirectory;
                                    if (sealDirectory != null)
                                    {
                                        HandleSealDirectory(sealDirectory, writer, configWriter);
                                    }
                                }

                                HandleProcesses(writer, configWriter, allProcesses);
                            }
                        });

                        success &= WriteQueuedInputFiles();
                    }
                }
            }

            Console.WriteLine("Write {0} input files", m_inputsWritten);
            Console.WriteLine("{0} Input files were using the default size", m_inputsWithDefaultSize);

            return(success);
        }