Пример #1
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            ProjectWithPredictions project,
            ProcessBuilder processBuilder)
        {
            // Add all predicted inputs
            foreach (AbsolutePath buildInput in project.PredictedInputFiles)
            {
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(buildInput));
            }

            IEnumerable <ProjectWithPredictions> references;

            // The default for EnableTransitiveProjectReferences is false, so it has to be true explicitly to kick in
            if (m_resolverSettings.EnableTransitiveProjectReferences == true)
            {
                // In this case all the transitive closure is automatically exposed to the project as direct references
                var transitiveReferences = new HashSet <ProjectWithPredictions>();
                ComputeTransitiveDependenciesFor(project, transitiveReferences);
                references = transitiveReferences;
            }
            else
            {
                // Only direct dependencies are declared.
                // Add all known explicit inputs from project references. But rule out
                // projects that have a known empty list of targets: those projects are not scheduled, so
                // there is nothing to consume from them.
                references = project.ProjectReferences.Where(projectReference => !projectReference.PredictedTargetsToExecute.TargetsAreKnownToBeEmpty);
            }

            var argumentsBuilder = processBuilder.ArgumentsBuilder;

            foreach (ProjectWithPredictions projectReference in references)
            {
                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out MSBuildProjectOutputs projectOutputs);
                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: {projectReference.FullPath.ToString(PathTable)} missing, dependency of {project.FullPath.ToString(PathTable)}");
                }

                // Add all known output directories
                foreach (StaticDirectory output in projectOutputs.OutputDirectories)
                {
                    processBuilder.AddInputDirectory(output.Root);
                }

                // If the dependency was built in isolation, this project needs to access the generated cache files
                if (projectOutputs.BuildsInIsolation)
                {
                    var outputCache = projectOutputs.OutputCacheFile;
                    processBuilder.AddInputFile(outputCache);
                    // Instruct MSBuild to use the cache file from the associated dependency as an input.
                    // Flag /irc is the short form of /inputResultsCaches, and part of MSBuild 'build in isolation' mode.
                    using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
                    {
                        argumentsBuilder.Add(PipDataAtom.FromString("/irc:"));
                        argumentsBuilder.Add(PipDataAtom.FromAbsolutePath(outputCache));
                    }
                }
            }
        }
Пример #2
0
            /// <summary>
            /// Augments the processBuilder with the OS dependencies
            /// </summary>
            public bool ProcessDefaults(ProcessBuilder processBuilder)
            {
                if ((processBuilder.Options & Process.Options.DependsOnCurrentOs) != 0)
                {
                    var defaultSourceSealDirs = m_lazySourceSealDirectories.Value;
                    if (!defaultSourceSealDirs.IsValid)
                    {
                        return(false);
                    }

                    foreach (var inputDirectory in defaultSourceSealDirs.Directories)
                    {
                        processBuilder.AddInputDirectory(inputDirectory);
                    }

                    foreach (var untrackedFile in m_untrackedFiles)
                    {
                        processBuilder.AddUntrackedFile(untrackedFile);
                    }

                    foreach (var untrackedDirectory in m_untrackedDirectories)
                    {
                        processBuilder.AddUntrackedDirectoryScope(untrackedDirectory);
                    }
                }

                return(true);
            }
Пример #3
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            RushProject project,
            ProcessBuilder processBuilder)
        {
            var argumentsBuilder = processBuilder.ArgumentsBuilder;

            IEnumerable <RushProject> references;

            // In this case all the transitive closure is automatically exposed to the project as direct references. This is standard for
            // JavaScript projects.
            var transitiveReferences = new HashSet <RushProject>();

            ComputeTransitiveDependenciesFor(project, transitiveReferences);
            references = transitiveReferences;

            foreach (RushProject projectReference in references)
            {
                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out var processOutputs);
                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: {projectReference.ProjectFolder.ToString(PathTable)} missing, dependency of {project.ProjectFolder.ToString(PathTable)}");
                }

                // Add all known output directories
                foreach (StaticDirectory output in processOutputs.GetOutputDirectories())
                {
                    processBuilder.AddInputDirectory(output.Root);
                }
                // Add all known output files
                foreach (FileArtifact output in processOutputs.GetOutputFiles())
                {
                    processBuilder.AddInputFile(output);
                }
            }
        }
Пример #4
0
            /// <summary>
            /// Augments the processBuilder with the OS dependencies
            /// </summary>
            public void ProcessDefaults(ProcessBuilder processBuilder)
            {
                if ((processBuilder.Options & Process.Options.DependsOnCurrentOs) != 0)
                {
                    foreach (var inputFile in m_inputFiles)
                    {
                        processBuilder.AddInputFile(inputFile);
                    }

                    foreach (var inputDirectory in m_inputDirectories)
                    {
                        processBuilder.AddInputDirectory(inputDirectory);
                    }

                    foreach (var untrackedFile in m_untrackedFiles)
                    {
                        processBuilder.AddUntrackedFile(untrackedFile);
                    }

                    foreach (var untrackedDirectory in m_untrackedDirectories)
                    {
                        processBuilder.AddUntrackedDirectoryScope(untrackedDirectory);
                    }
                }
            }
Пример #5
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            RushProject project,
            ProcessBuilder processBuilder)
        {
            // Add all explicitly declared source files
            foreach (AbsolutePath sourceFile in project.SourceFiles)
            {
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(sourceFile));
            }

            // Add package.json, which should always be present at the root of the project
            processBuilder.AddInputFile(FileArtifact.CreateSourceFile(project.PackageJsonFile(PathTable)));

            // If dependencies should be tracked via the project-level shrinkwrap-deps file, then force an input
            // dependency on it
            if (m_resolverSettings.TrackDependenciesWithShrinkwrapDepsFile == true)
            {
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(project.ShrinkwrapDepsFile(PathTable)));
            }

            // In this case all the transitive closure is automatically exposed to the project as direct references. This is standard for
            // JavaScript projects.
            var transitiveReferences = new HashSet <RushProject>();

            ComputeTransitiveDependenciesFor(project, transitiveReferences);
            IEnumerable <RushProject> references = transitiveReferences;

            foreach (RushProject projectReference in references)
            {
                // If the project is referencing something that was not scheduled, just skip it
                if (!projectReference.CanBeScheduled())
                {
                    // We have already logged this case as an informational when building the project graph
                    continue;
                }

                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out var processOutputs);
                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: {projectReference.ProjectFolder.ToString(PathTable)} missing, dependency of {project.ProjectFolder.ToString(PathTable)}");
                }

                // Add all known output directories
                foreach (StaticDirectory output in processOutputs.GetOutputDirectories())
                {
                    processBuilder.AddInputDirectory(output.Root);
                }

                // Add all known output files, but exclude logs
                foreach (FileArtifact output in processOutputs.GetOutputFiles()
                         .Where(fa => !fa.Path.IsWithin(m_context.PathTable, LogDirectoryBase(m_frontEndHost.Configuration, m_context.PathTable))))
                {
                    processBuilder.AddInputFile(output);
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Adds input directory.
        /// </summary>
        public ArgumentsBuilder AddInputDirectoryOption(string optionName, DirectoryArtifact inputDirectory)
        {
            Contract.Requires(!string.IsNullOrEmpty(optionName));
            Contract.Requires(inputDirectory.IsValid);
            Contract.Assert(!m_finished);

            m_dataBuilder.AddPathOption(optionName, inputDirectory.Path);
            m_processBuilder.AddInputDirectory(inputDirectory);
            return(this);
        }
Пример #7
0
        public void ExecutionRecordsReportedFileAccesses()
        {
            FileArtifact sourceFile = CreateSourceFile();

            SealDirectory  sourceDirectory = CreateAndScheduleSealDirectory(sourceFile.Path.GetParent(Context.PathTable), SealDirectoryKind.SourceAllDirectories);
            ProcessBuilder builder         = CreatePipBuilder(new[] { Operation.ReadFile(sourceFile, doNotInfer: true), Operation.WriteFile(CreateOutputFileArtifact()) });

            builder.AddInputDirectory(sourceDirectory.Directory);
            builder.Options |= Process.Options.RequiresAdmin;
            ProcessWithOutputs process = SchedulePipBuilder(builder);

            RunScheduler().AssertSuccess();
            RunScheduler().AssertCacheHit(process.Process.PipId);

            File.WriteAllText(ArtifactToString(sourceFile), Guid.NewGuid().ToString());

            RunScheduler().AssertCacheMiss(process.Process.PipId);
        }
Пример #8
0
            /// <summary>
            /// Augments the processBuilder with the OS dependencies.
            /// </summary>
            /// <param name="processBuilder">builder to use</param>
            /// <param name="untrackInsteadSourceSeal">when true, directories that are meant to be source sealed are untracked instead</param>
            public bool ProcessDefaults(ProcessBuilder processBuilder, bool untrackInsteadSourceSeal = false)
            {
                if (processBuilder.Options.HasFlag(Process.Options.DependsOnCurrentOs))
                {
                    // process source seal directories: either source seal them or untrack them, depending on 'untrackInsteadSourceSeal'
                    if (untrackInsteadSourceSeal)
                    {
                        foreach (var sourceSealDirPath in m_sourceSealDirectoryPaths)
                        {
                            processBuilder.AddUntrackedDirectoryScope(DirectoryArtifact.CreateWithZeroPartialSealId(sourceSealDirPath));
                        }
                    }
                    else
                    {
                        var defaultSourceSealDirs = m_lazySourceSealDirectories.Value;
                        if (!defaultSourceSealDirs.IsValid)
                        {
                            return(false);
                        }

                        foreach (var inputDirectory in defaultSourceSealDirs.Directories)
                        {
                            processBuilder.AddInputDirectory(inputDirectory);
                        }
                    }

                    // add untracked files
                    foreach (var untrackedFile in m_untrackedFiles)
                    {
                        processBuilder.AddUntrackedFile(untrackedFile);
                    }

                    // add untracked directories
                    foreach (var untrackedDirectory in m_untrackedDirectories)
                    {
                        processBuilder.AddUntrackedDirectoryScope(untrackedDirectory);
                    }
                }

                return(true);
            }
Пример #9
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            ProjectWithPredictions project,
            ProcessBuilder processBuilder)
        {
            // Add all predicted inputs
            foreach (AbsolutePath buildInput in project.PredictedInputFiles)
            {
                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(buildInput));
            }

            IEnumerable <ProjectWithPredictions> references;

            // The default for EnableTransitiveProjectReferences is false, so it has to be true explicitly to kick in
            if (m_resolverSettings.EnableTransitiveProjectReferences == true)
            {
                // In this case all the transitive closure is automatically exposed to the project as direct references
                var transitiveReferences = new HashSet <ProjectWithPredictions>();
                ComputeTransitiveDependenciesFor(project, transitiveReferences);
                references = transitiveReferences;
            }
            else
            {
                // Only direct dependencies are declared.
                // Add all known explicit inputs from project references. But rule out
                // projects that have a known empty list of targets: those projects are not scheduled, so
                // there is nothing to consume from them.
                references = project.ProjectReferences.Where(projectReference => !projectReference.PredictedTargetsToExecute.TargetsAreKnownToBeEmpty);
            }

            foreach (ProjectWithPredictions projectReference in references)
            {
                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out ProcessOutputs processOutputs);
                Contract.Assert(outputsPresent, $"Pips must have been presented in dependency order: {projectReference.FullPath.ToString(PathTable)} missing, dependency of {project.FullPath.ToString(PathTable)}");

                // Add all known opaque directories
                foreach (StaticDirectory output in processOutputs.GetOutputDirectories())
                {
                    processBuilder.AddInputDirectory(output.Root);
                }
            }
        }
Пример #10
0
        /// <summary>
        /// Adds all predicted dependencies as inputs, plus all individual inputs predicted for the project
        /// </summary>
        /// <remarks>
        /// Adding all predicted dependencies is key to get the right scheduling. On the other hand, all predicted inputs
        /// are not really needed since we are running in undeclared read mode. However, they contribute to make the weak fingerprint stronger (that
        /// otherwise will likely be just a shared opaque output at the root).
        /// </remarks>
        private void ProcessInputs(
            ProjectWithPredictions project,
            ProcessBuilder processBuilder)
        {
            // Predicted output directories for all direct dependencies, plus the output directories for the given project itself
            var knownOutputDirectories = project.ProjectReferences.SelectMany(reference => reference.PredictedOutputFolders).Union(project.PredictedOutputFolders);

            // Add all predicted inputs that are recognized as true source files
            // This is done to make the weak fingerprint stronger. Pips are scheduled so undeclared source reads are allowed. This means
            // we don't actually need accurate (or in fact any) input predictions to run successfully. But we are trying to avoid the degenerate case
            // of a very small weak fingerprint with too many candidates, that can slow down two-phase cache look-up.
            foreach (AbsolutePath buildInput in project.PredictedInputFiles)
            {
                // If any of the predicted inputs is under the predicted output folder of a dependency, then there is a very good chance the predicted input is actually an intermediate file
                // In that case, don't add the input as a source file to stay on the safe side. Otherwise we will have a file that is both declared as a source file and contained in a directory
                // dependency.
                if (knownOutputDirectories.Any(outputFolder => buildInput.IsWithin(PathTable, outputFolder)))
                {
                    continue;
                }

                // If any of the predicted inputs is under an untracked directory scope, don't add it as an input
                if (processBuilder.GetUntrackedDirectoryScopesSoFar().Any(untrackedDirectory => buildInput.IsWithin(PathTable, untrackedDirectory)))
                {
                    continue;
                }

                processBuilder.AddInputFile(FileArtifact.CreateSourceFile(buildInput));
            }

            IEnumerable <ProjectWithPredictions> references;

            // The default for EnableTransitiveProjectReferences is false, so it has to be true explicitly to kick in
            if (m_resolverSettings.EnableTransitiveProjectReferences == true)
            {
                // In this case all the transitive closure is automatically exposed to the project as direct references
                var transitiveReferences = new HashSet <ProjectWithPredictions>();
                ComputeTransitiveDependenciesFor(project, transitiveReferences);
                references = transitiveReferences;
            }
            else
            {
                // Only direct dependencies are declared.
                // Add all known explicit inputs from project references. But rule out
                // projects that have a known empty list of targets: those projects are not scheduled, so
                // there is nothing to consume from them.
                references = project.ProjectReferences.Where(projectReference => projectReference.PredictedTargetsToExecute.Targets.Count != 0);
            }

            var argumentsBuilder = processBuilder.ArgumentsBuilder;

            foreach (ProjectWithPredictions projectReference in references)
            {
                bool outputsPresent = m_processOutputsPerProject.TryGetValue(projectReference, out MSBuildProjectOutputs projectOutputs);
                if (!outputsPresent)
                {
                    Contract.Assert(false, $"Pips must have been presented in dependency order: {projectReference.FullPath.ToString(PathTable)} missing, dependency of {project.FullPath.ToString(PathTable)}");
                }

                // Add all known output directories
                foreach (StaticDirectory output in projectOutputs.OutputDirectories)
                {
                    processBuilder.AddInputDirectory(output.Root);
                }

                // If the dependency was built in isolation, this project needs to access the generated cache files
                if (projectOutputs.BuildsInIsolation)
                {
                    var outputCache = projectOutputs.OutputCacheFile;
                    processBuilder.AddInputFile(outputCache);
                    // Instruct MSBuild to use the cache file from the associated dependency as an input.
                    // Flag /irc is the short form of /inputResultsCaches, and part of MSBuild 'build in isolation' mode.
                    using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
                    {
                        argumentsBuilder.Add(PipDataAtom.FromString("/irc:"));
                        argumentsBuilder.Add(PipDataAtom.FromAbsolutePath(outputCache));
                    }
                }
            }
        }