public void ExecutionProcessReadingStdIn()
        {
            FileArtifact   stdOut      = CreateOutputFileArtifact();
            ProcessBuilder builder     = CreatePipBuilder(new[] { Operation.ReadStdIn() });
            PipDataBuilder dataBuilder = new PipDataBuilder(Context.PathTable.StringTable);

            dataBuilder.Add("Data0");
            dataBuilder.Add("Data1");
            dataBuilder.Add("Data2");
            builder.StandardInput = global::BuildXL.Pips.StandardInput.CreateFromData(dataBuilder.ToPipData(Environment.NewLine, PipDataFragmentEscaping.NoEscaping));
            builder.SetStandardOutputFile(stdOut.Path);
            builder.Options |= Process.Options.RequiresAdmin;
            ProcessWithOutputs process = SchedulePipBuilder(builder);

            RunScheduler().AssertSuccess();

            string[] output        = File.ReadAllLines(ArtifactToString(stdOut));
            string   actualContent = string.Join(Environment.NewLine, output);

            XAssert.AreEqual(3, output.Length, "Actual content: {0}{1}", Environment.NewLine, string.Join(Environment.NewLine, output));
            for (int i = 0; i < 3; ++i)
            {
                XAssert.AreEqual("Data" + i, output[i], "Actual content: {0}", output[i]);
            }
        }
Beispiel #2
0
        public PipDataTests(ITestOutputHelper output)
            : base(output)
        {
            m_pathTable         = new PathTable();
            m_expectedStringId0 = StringId.Create(m_pathTable.StringTable, ExpectedString0);
            m_pipDataBuilder    = new PipDataBuilder(m_pathTable.StringTable);

            m_expectedStringId0 = StringId.Create(m_pathTable.StringTable, ExpectedString0);
            m_uniqueEntry0      = AbsolutePath.Create(m_pathTable, A("c", "unique to fragment 0"));

            // BEGIN ADDING ARGUMENTS
            m_cursorStart = m_pipDataBuilder.CreateCursor();

            AddStandardBlock(m_pipDataBuilder);

            m_cursor0 = m_pipDataBuilder.CreateCursor();

            using (m_pipDataBuilder.StartFragment(Escaping0, m_separator0))
            {
                m_pipDataBuilder.Add(m_uniqueEntry0);
                AddStandardBlock(m_pipDataBuilder);
            }

            m_cursor1 = m_pipDataBuilder.CreateCursor();

            using (m_pipDataBuilder.StartFragment(Escaping1, Separator1))
            {
                AddStandardBlock(m_pipDataBuilder);
                m_pipDataBuilder.Add(UniqueEntry1);
            }

            m_cursorEnd = m_pipDataBuilder.CreateCursor();

            // END ADDING ARGUMENTS
        }
Beispiel #3
0
        private void SetProcessEnvironmentVariables(IReadOnlyDictionary <string, string> environment, ProcessBuilder processBuilder)
        {
            foreach (KeyValuePair <string, string> kvp in environment)
            {
                if (kvp.Value != null)
                {
                    var envPipData = new PipDataBuilder(m_context.StringTable);

                    // Casing for paths is not stable as reported by BuildPrediction. So here we try to guess if the value
                    // represents a path, and normalize it
                    string value = kvp.Value;
                    if (!string.IsNullOrEmpty(value) && AbsolutePath.TryCreate(PathTable, value, out var absolutePath))
                    {
                        envPipData.Add(absolutePath);
                    }
                    else
                    {
                        envPipData.Add(value);
                    }

                    processBuilder.SetEnvironmentVariable(
                        StringId.Create(m_context.StringTable, kvp.Key),
                        envPipData.ToPipData(string.Empty, PipDataFragmentEscaping.NoEscaping));
                }
            }

            if (m_userDefinedPassthroughVariables != null)
            {
                foreach (string passThroughVariable in m_userDefinedPassthroughVariables)
                {
                    processBuilder.SetPassthroughEnvironmentVariable(StringId.Create(m_context.StringTable, passThroughVariable));
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Creates an instance of <see cref="ArgumentsDataBuilder"/>
        /// </summary>
        public ArgumentsDataBuilder(PipDataBuilder builder)
        {
            Contract.Requires(builder != null);

            m_builder  = builder;
            m_finished = false;
        }
        private PipProvenance CreatePipProvenance(string description)
        {
            var usage = string.IsNullOrEmpty(description)
                ? PipData.Invalid
                : PipDataBuilder.CreatePipData(Context.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping, description);

            return(CreatePipProvenance(usage));
        }
Beispiel #6
0
        /// <summary>
        /// Creates arguments.
        /// </summary>
        protected PipData CreateArguments(
            IEnumerable <Operation> processOperations,
            StringTable stringTable)
        {
            var pipDataBuilder = new PipDataBuilder(stringTable);

            CreateArguments(pipDataBuilder, processOperations, stringTable);
            return(pipDataBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules));
        }
Beispiel #7
0
        /// <nodoc />
        public void SetEnvironmentVariable(StringId key, PipDataAtom value)
        {
            Contract.Requires(key.IsValid);
            Contract.Requires(value.IsValid);

            var pipData = PipDataBuilder.CreatePipData(m_pathTable.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping, value);

            SetEnvironmentVariable(key, pipData);
        }
Beispiel #8
0
 private static void AddLogArgument(PipDataBuilder pipDataBuilder, int loggerNumber, AbsolutePath logFile, string verbosity)
 {
     using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
     {
         pipDataBuilder.Add(PipDataAtom.FromString(I($"/flp{loggerNumber}:logfile=")));
         pipDataBuilder.Add((PipDataAtom.FromAbsolutePath(logFile)));
         pipDataBuilder.Add(PipDataAtom.FromString(I($";{verbosity}")));
     }
 }
Beispiel #9
0
 /// <summary>
 /// Creates arguments.
 /// </summary>
 protected void CreateArguments(
     PipDataBuilder pipDataBuilder,
     IEnumerable <Operation> processOperations,
     StringTable stringTable)
 {
     foreach (var op in processOperations)
     {
         pipDataBuilder.Add(op.ToCommandLine(Context.PathTable));
     }
 }
        private TransformerExecuteArgumentsProcessor(Context context, ProcessBuilder processBuilder)
        {
            Contract.Requires(processBuilder != null);
            Contract.Requires(context != null);

            ArgumentsBuilder = processBuilder.ArgumentsBuilder;
            m_processBuilder = processBuilder;
            m_context        = context;
            EmptyStringId    = context.StringTable.Empty;
        }
Beispiel #11
0
        private static Pip CreateCmdPip(BuildXLContext context, string tempDirectory, string outFile, bool is64Bit)
        {
            Contract.Requires(context != null);
            Contract.Requires(tempDirectory != null);
            Contract.Requires(!string.IsNullOrEmpty(outFile));

            var pathTable = context.PathTable;

            string       executable         = is64Bit ? CmdHelper.CmdX64 : CmdHelper.CmdX86;
            FileArtifact executableArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, executable));

            string       workingDirectory             = AssemblyDirectory;
            AbsolutePath workingDirectoryAbsolutePath = AbsolutePath.Create(pathTable, workingDirectory);

            AbsolutePath outFilePath     = AbsolutePath.Create(pathTable, outFile);
            FileArtifact outFileArtifact = FileArtifact.CreateSourceFile(outFilePath).CreateNextWrittenVersion();
            var          pip             = new BuildXL.Pips.Operations.Process(
                executableArtifact,
                workingDirectoryAbsolutePath,
                PipDataBuilder.CreatePipData(
                    context.StringTable,
                    " ",
                    PipDataFragmentEscaping.CRuntimeArgumentRules,
                    "/d",
                    "/c",
                    "echo",
                    "hello",
                    ">",
                    outFileArtifact),
                FileArtifact.Invalid,
                PipData.Invalid,
                ReadOnlyArray <EnvironmentVariable> .Empty,
                FileArtifact.Invalid,
                FileArtifact.Invalid,
                FileArtifact.Invalid,
                AbsolutePath.Create(pathTable, tempDirectory),
                null,
                null,
                ReadOnlyArray <FileArtifact> .FromWithoutCopy(executableArtifact),
                ReadOnlyArray <FileArtifactWithAttributes> .FromWithoutCopy(outFileArtifact.WithAttributes()),
                ReadOnlyArray <DirectoryArtifact> .Empty,
                ReadOnlyArray <DirectoryArtifact> .Empty,
                ReadOnlyArray <PipId> .Empty,
                ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencies(pathTable)),
                ReadOnlyArray <AbsolutePath> .From(CmdHelper.GetCmdDependencyScopes(pathTable)),
                ReadOnlyArray <StringId> .Empty,
                ReadOnlyArray <int> .Empty,
                ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                provenance: PipProvenance.CreateDummy(context),
                toolDescription: StringId.Invalid,
                additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty);

            return(pip);
        }
Beispiel #12
0
        private void SetEnvironmentVariables(ProcessBuilder processBuilder, NinjaNode node)
        {
            foreach (KeyValuePair <string, string> kvp in m_environmentVariables.Value)
            {
                if (kvp.Value != null)
                {
                    var envPipData = new PipDataBuilder(m_context.StringTable);
                    if (SpecialEnvironmentVariables.PassThroughPrefixes.All(prefix => !kvp.Key.StartsWith(prefix)))
                    {
                        envPipData.Add(kvp.Value);
                        processBuilder.SetEnvironmentVariable(StringId.Create(m_context.StringTable, kvp.Key), envPipData.ToPipData(string.Empty, PipDataFragmentEscaping.NoEscaping));
                    }
                }
            }

            foreach (var kvp in m_passThroughEnvironmentVariables.Value)
            {
                processBuilder.SetPassthroughEnvironmentVariable(StringId.Create(m_context.StringTable, kvp.Key));
            }

            foreach (var envVar in SpecialEnvironmentVariables.CloudBuildEnvironment)
            {
                processBuilder.SetPassthroughEnvironmentVariable(StringId.Create(m_context.StringTable, envVar));
            }

            // GlobalUnsafePassthroughEnvironmentVariables
            processBuilder.SetGlobalPassthroughEnvironmentVariable(m_frontEndHost.Configuration.FrontEnd.GlobalUnsafePassthroughEnvironmentVariables, m_context.StringTable);

            // We will specify a different MSPDBSRV endpoint for every pip.
            // This means every pip that needs to communicate to MSPDBSRV will
            // spawn a different child process.
            // This is because if two pips use the same endpoint at the same time
            // then second one will fail after the first one finishes, because the
            // first one was the one that spawned MSPDBSRV.EXE as a child
            // (which gets killed).
            //
            // IMPORTANT: This will cause the build to fail if two pips target the same PDB file.
            // Both LINK.EXE and CL.EXE can use MSPDBSRV.EXE:
            //   - If all linkers specify a different /pdb argument (or don't specify this argument and
            //   are linking programs with different names
            //   [https://docs.microsoft.com/en-us/cpp/build/reference/debug-generate-debug-info])
            //   then this won't happen
            //
            //   - We're forcing the compiler to not output to PDBs (/Z7)
            //
            // so this should work in the normal cases.
            var mspdbsrvPipDataBuilder = new PipDataBuilder(m_context.StringTable);

            mspdbsrvPipDataBuilder.Add(PipConstructionUtilities.ComputeSha256(node.Command));   // Unique value for each pip
            processBuilder.SetEnvironmentVariable(
                StringId.Create(m_context.StringTable, SpecialEnvironmentVariables.MsPdvSrvEndpoint),
                mspdbsrvPipDataBuilder.ToPipData(string.Empty, PipDataFragmentEscaping.NoEscaping));
        }
Beispiel #13
0
        private const int NumStandardBlockFragments = 8; // this number must match the number of fragments added in AddStandardBlock

        private void AddStandardBlock(PipDataBuilder pipDataBuilder)
        {
            pipDataBuilder.Add(Path1);
            pipDataBuilder.Add(Path2);
            pipDataBuilder.Add(CaseVaryingString);
            pipDataBuilder.Add(m_expectedStringId0);
            pipDataBuilder.AddVsoHash(SourceFile);
            pipDataBuilder.AddVsoHash(OutputFile);
            pipDataBuilder.AddVsoHash(RewrittenFile);
            pipDataBuilder.AddVsoHash(RewrittenFile2);

            // if you add more fragments here, update
            //   (1) NumStandardBlockFragments constant above
            //   (2) VerifyStandardBlock method below
        }
Beispiel #14
0
        /// <summary>
        /// Adds a fake write file pip that produces to the given destination path.
        /// </summary>
        public WriteFile AddWriteFilePip(AbsolutePath destinationPath)
        {
            Contract.Requires(destinationPath != null);

            FileArtifact destinationArtifact = FileArtifact.CreateSourceFile(destinationPath).CreateNextWrittenVersion();
            PipData      contents            = PipDataBuilder.CreatePipData(m_context.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "content");

            var writeFile = new WriteFile(destinationArtifact, contents, WriteFileEncoding.Utf8, ReadOnlyArray <StringId> .Empty, PipProvenance.CreateDummy(m_context));

            writeFile.PipId = AllocateNextPipId();
            m_pips.Add(writeFile.PipId, writeFile);
            m_pathProducers.Add(destinationArtifact, writeFile);

            return(writeFile);
        }
        /// <nodoc />
        public bool TrySealDirectory(
            AbsolutePath directoryRoot,
            SortedReadOnlyArray <FileArtifact, OrdinalFileArtifactComparer> contents,
            SortedReadOnlyArray <DirectoryArtifact, OrdinalDirectoryArtifactComparer> outputDirectorycontents,
            SealDirectoryKind kind,
            string[] tags,
            string description,
            string[] patterns,
            out DirectoryArtifact sealedDirectory,
            bool scrub = false)
        {
            Contract.Requires(directoryRoot.IsValid);
            Contract.Requires(contents.IsValid);
            Contract.Requires(outputDirectorycontents.IsValid);

            PipData usage = PipDataBuilder.CreatePipData(Context.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping, description != null
                ? new PipDataAtom[] { description }
                : new PipDataAtom[] { "'", directoryRoot, "' [", contents.Length.ToString(CultureInfo.InvariantCulture), " files - ",
                                      outputDirectorycontents.Length.ToString(CultureInfo.InvariantCulture), " output directories]" });

            var pip = new SealDirectory(
                directoryRoot,
                contents,
                outputDirectorycontents,
                kind,
                CreatePipProvenance(usage),
                ToStringIds(tags),
                ToStringIds(patterns),
                scrub);

            if (PipGraph != null)
            {
                sealedDirectory = PipGraph.AddSealDirectory(pip, GetValuePipId());
                if (!sealedDirectory.IsValid)
                {
                    return(false);
                }
            }
            else
            {
                sealedDirectory = DirectoryArtifact.CreateWithZeroPartialSealId(directoryRoot);
            }

            return(true);
        }
        public static void Add(this PipDataBuilder @this, string prefix, RelativePath value)
        {
            var escaping  = PipDataFragmentEscaping.CRuntimeArgumentRules;
            var separator = System.IO.Path.DirectorySeparatorChar.ToString();

            using (@this.StartFragment(escaping, separator))
            {
                if (!string.IsNullOrEmpty(prefix))
                {
                    @this.Add(prefix);
                }

                foreach (var atom in value.GetAtoms())
                {
                    @this.Add(atom);
                }
            }
        }
        /// <nodoc/>
        public bool TryComposeSharedOpaqueDirectory(
            AbsolutePath directoryRoot,
            IReadOnlyList <DirectoryArtifact> contents,
            SealDirectoryContentFilter?contentFilter,
            [CanBeNull] string description,
            [CanBeNull] string[] tags,
            out DirectoryArtifact sharedOpaqueDirectory)
        {
            Contract.Requires(directoryRoot.IsValid);
            Contract.Requires(contents != null);

            if (PipGraph == null)
            {
                sharedOpaqueDirectory = DirectoryArtifact.CreateWithZeroPartialSealId(directoryRoot);
                return(true);
            }

            PipData usage = PipDataBuilder.CreatePipData(Context.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping, description != null
                ? new PipDataAtom[] { description }
                : new PipDataAtom[] { "'", directoryRoot, "' [", contents.Count.ToString(CultureInfo.InvariantCulture),
                                      " shared opaque directories, filter: ",
                                      contentFilter.HasValue ? $"'{contentFilter.Value.Regex}' (kind: {Enum.GetName(typeof(SealDirectoryContentFilter.ContentFilterKind),     contentFilter.Value.Kind)})" : "''", "]" });

            sharedOpaqueDirectory = PipGraph.ReserveSharedOpaqueDirectory(directoryRoot);

            var pip = new CompositeSharedOpaqueSealDirectory(
                directoryRoot,
                contents,
                CreatePipProvenance(usage),
                ToStringIds(tags),
                contentFilter);

            // The seal directory is ready to be initialized, since the directory artifact has been reserved already
            pip.SetDirectoryArtifact(sharedOpaqueDirectory);

            sharedOpaqueDirectory = PipGraph.AddSealDirectory(pip, GetValuePipId());
            if (!sharedOpaqueDirectory.IsValid)
            {
                return(false);
            }

            return(true);
        }
Beispiel #18
0
 private static void AddMsBuildProperty(PipDataBuilder pipDataBuilder, string key, string value)
 {
     // Make sure properties are always quoted, since MSBuild doesn't handle semicolon separated
     // properties without quotes
     using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
     {
         pipDataBuilder.Add(PipDataAtom.FromString("/p:"));
         using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, string.Empty))
         {
             pipDataBuilder.Add(PipDataAtom.FromString(key));
         }
         pipDataBuilder.Add(PipDataAtom.FromString("=\""));
         using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, string.Empty))
         {
             pipDataBuilder.Add(PipDataAtom.FromString(value));
         }
         pipDataBuilder.Add(PipDataAtom.FromString("\""));
     }
 }
        public FileArtifact WriteFile(AbsolutePath destination, PipDataAtom content, WriteFileEncoding?encoding = null)
        {
            PipDataBuilder pipDataBuilder = new PipDataBuilder(Context.StringTable);

            pipDataBuilder.Add(content);

            if (!PipConstructionHelper.TryWriteFile(
                    destination,
                    pipDataBuilder.ToPipData(Context.StringTable.Empty, PipDataFragmentEscaping.NoEscaping),
                    encoding ?? WriteFileEncoding.Utf8,
                    null,
                    null,
                    out var result))
            {
                throw new BuildXLTestException("Failed to add writefile pip");
            }

            return(result);
        }
Beispiel #20
0
        /// <summary>
        /// Schedules a pip to produce a file at the specified path under the given output directory.
        /// </summary>
        private static bool TryScheduleWriteOutputFileUnderDirectory(
            TestEnv env,
            AbsolutePath directory,
            string relativePath,
            out FileArtifact target)
        {
            Contract.Requires(env != null);
            Contract.Requires(directory.IsValid);
            Contract.Requires(!string.IsNullOrEmpty(relativePath));

            target = FileArtifact.CreateSourceFile(env.Paths.CreateAbsolutePath(directory, env.Paths.CreateRelativePath(relativePath))).CreateNextWrittenVersion();
            var pip = new WriteFile(
                target,
                PipDataBuilder.CreatePipData(env.PathTable.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping, "content"),
                WriteFileEncoding.Utf8,
                ReadOnlyArray <StringId> .Empty,
                env.CreatePipProvenance(StringId.Invalid));

            return(env.PipGraph.AddWriteFile(pip, PipId.Invalid));
        }
Beispiel #21
0
        public void PipFragmentEquality()
        {
            var pathTable = new PathTable();

            StructTester.TestEquality(
                baseValue: PipFragment.FromString("mystring", pathTable.StringTable),
                equalValue: PipFragment.FromString("mystring", pathTable.StringTable),
                notEqualValues: new[]
            {
                PipFragment.FromString("MyString", pathTable.StringTable),
                PipFragment.FromAbsolutePathForTesting(
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, A("t", "file1.txt")))),
                PipFragment.FromAbsolutePathForTesting(
                    FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, A("t", "file1.txt"))).CreateNextWrittenVersion()),
                PipFragment.CreateNestedFragment(
                    PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules))
            },
                eq: (left, right) => left == right,
                neq: (left, right) => left != right);
        }
        /// <summary>
        /// Adds a fake process pip that produces only the given path.
        /// </summary>
        public Process AddProcess(AbsolutePath producedPath, DoubleWritePolicy doubleWritePolicy = DoubleWritePolicy.DoubleWritesAreErrors)
        {
            Contract.Assume(!m_pathProducers.ContainsKey(producedPath), "Each path may have only one producer (no rewrites)");

            AbsolutePath workingDirectory = AbsolutePath.Create(m_context.PathTable, PathGeneratorUtilities.GetAbsolutePath("X", ""));
            AbsolutePath exe = AbsolutePath.Create(m_context.PathTable, PathGeneratorUtilities.GetAbsolutePath("X", "fake.exe"));

            var process = new Process(
                executable: FileArtifact.CreateSourceFile(exe),
                workingDirectory: workingDirectory,
                arguments: PipDataBuilder.CreatePipData(m_context.StringTable, string.Empty, PipDataFragmentEscaping.NoEscaping),
                responseFile: FileArtifact.Invalid,
                responseFileData: PipData.Invalid,
                environmentVariables: ReadOnlyArray <EnvironmentVariable> .Empty,
                standardInput: FileArtifact.Invalid,
                standardOutput: FileArtifact.Invalid,
                standardError: FileArtifact.Invalid,
                standardDirectory: workingDirectory,
                warningTimeout: null,
                timeout: null,
                dependencies: ReadOnlyArray <FileArtifact> .FromWithoutCopy(FileArtifact.CreateSourceFile(exe)),
                outputs: ReadOnlyArray <FileArtifactWithAttributes> .FromWithoutCopy(FileArtifact.CreateSourceFile(producedPath).CreateNextWrittenVersion().WithAttributes()),
                directoryDependencies: ReadOnlyArray <DirectoryArtifact> .Empty,
                directoryOutputs: ReadOnlyArray <DirectoryArtifact> .Empty,
                orderDependencies: ReadOnlyArray <PipId> .Empty,
                untrackedPaths: ReadOnlyArray <AbsolutePath> .Empty,
                untrackedScopes: ReadOnlyArray <AbsolutePath> .Empty,
                tags: ReadOnlyArray <StringId> .Empty,
                successExitCodes: ReadOnlyArray <int> .Empty,
                semaphores: ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                provenance: PipProvenance.CreateDummy(m_context),
                toolDescription: StringId.Invalid,
                additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty,
                doubleWritePolicy: doubleWritePolicy);

            process.PipId = AllocateNextPipId();
            m_pips.Add(process.PipId, process);
            m_pathProducers.Add(producedPath, process);

            return(process);
        }
Beispiel #23
0
        /// <summary>
        /// Configure the environment for a process
        /// </summary>
        public static void SetProcessEnvironmentVariables(
            IReadOnlyDictionary <string, string> userDefinedEnvironment,
            [CanBeNull] IEnumerable <string> userDefinedPassthroughVariables,
            ProcessBuilder processBuilder,
            PathTable pathTable)
        {
            Contract.RequiresNotNull(userDefinedEnvironment);
            Contract.RequiresNotNull(processBuilder);

            foreach (KeyValuePair <string, string> kvp in userDefinedEnvironment)
            {
                if (kvp.Value != null)
                {
                    var envPipData = new PipDataBuilder(pathTable.StringTable);

                    // Casing for paths is not stable as reported by BuildPrediction. So here we try to guess if the value
                    // represents a path, and normalize it
                    string value = kvp.Value;
                    if (!string.IsNullOrEmpty(value) && AbsolutePath.TryCreate(pathTable, value, out var absolutePath))
                    {
                        envPipData.Add(absolutePath);
                    }
                    else
                    {
                        envPipData.Add(value);
                    }

                    processBuilder.SetEnvironmentVariable(
                        StringId.Create(pathTable.StringTable, kvp.Key),
                        envPipData.ToPipData(string.Empty, PipDataFragmentEscaping.NoEscaping));
                }
            }

            if (userDefinedPassthroughVariables != null)
            {
                foreach (string passThroughVariable in userDefinedPassthroughVariables)
                {
                    processBuilder.SetPassthroughEnvironmentVariable(StringId.Create(pathTable.StringTable, passThroughVariable));
                }
            }
        }
        private PerProcessPipPerformanceInformation CreateSamplePip(int index)
        {
            Func <RunnablePip, Task <PipResult> > taskFactory = async(runnablePip) =>
            {
                PipResult result;
                var       operationTracker = new OperationTracker(runnablePip.LoggingContext);
                var       pip = runnablePip.Pip;
                using (var operationContext = operationTracker.StartOperation(PipExecutorCounter.PipRunningStateDuration, pip.PipId, pip.PipType, runnablePip.LoggingContext))
                {
                    result = await TestPipExecutor.ExecuteAsync(operationContext, m_executionEnvironment, pip);
                }

                return(result);
            };

            var pathTable = m_context.PathTable;

            var executable   = FileArtifact.CreateSourceFile(AbsolutePath.Create(pathTable, X("/x/pkgs/tool.exe")));
            var dependencies = new HashSet <FileArtifact> {
                executable
            };

            var processBuilder = new ProcessBuilder()
                                 .WithExecutable(executable)
                                 .WithWorkingDirectory(AbsolutePath.Create(pathTable, X("/x/obj/working")))
                                 .WithArguments(PipDataBuilder.CreatePipData(pathTable.StringTable, " ", PipDataFragmentEscaping.CRuntimeArgumentRules, "-loadargs"))
                                 .WithStandardDirectory(AbsolutePath.Create(pathTable, X("/x/obj/working.std")))
                                 .WithDependencies(dependencies)
                                 .WithContext(m_context);

            var dataBuilder = new PipDataBuilder(m_context.PathTable.StringTable);
            var pipData     = dataBuilder.ToPipData(" ", PipDataFragmentEscaping.NoEscaping);
            var pip         = processBuilder.WithArguments(pipData).Build();
            var pipId       = m_executionEnvironment.PipTable.Add((uint)(index + 1), pip);

            var runnableProcessPip = (ProcessRunnablePip)(RunnablePip.Create(m_loggingContext, m_executionEnvironment, pipId, PipType.Process, 0, taskFactory, 0));

            m_runnablePips.Add(index, runnableProcessPip);      // For verification

            return(GeneratePipInfoWithRunnablePipAndIndex(ref runnableProcessPip, index));
        }
Beispiel #25
0
        /// <summary>
        /// Gets the command line arguments for the process.
        /// </summary>
        public PipData GetArgumentsDataFromProcess(Process process)
        {
            PipData arguments = process.Arguments;

            if (process.ResponseFile.IsValid)
            {
                var            responseFileData = process.ResponseFileData;
                PipDataBuilder pipDataBuilder   = new PipDataBuilder(StringTable);

                // Add all the arguments from the command line excluding the response file (the last fragment)
                foreach (var fragment in process.Arguments.Take(process.Arguments.FragmentCount - 1).Concat(responseFileData))
                {
                    Contract.Assume(fragment.FragmentType != PipFragmentType.Invalid);

                    pipDataBuilder.Add(fragment);
                }

                arguments = pipDataBuilder.ToPipData(arguments.FragmentSeparator, arguments.FragmentEscaping);
            }

            return(arguments);
        }
        private void AddJavaScriptArgumentToBuilder(PipDataBuilder argumentsBuilder, JavaScriptArgument value)
        {
            switch (value.GetValue())
            {
            case string s:
                using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, m_context.StringTable.Empty))
                {
                    argumentsBuilder.Add(s);
                }
                break;

            case AbsolutePath absolutePath:
                using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, m_context.StringTable.Empty))
                {
                    argumentsBuilder.Add(absolutePath);
                }
                break;

            case RelativePath relativePath:
                using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, m_context.StringTable.Empty))
                {
                    argumentsBuilder.Add(relativePath);
                }
                break;

            case PathAtom pathAtom:
                using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, m_context.StringTable.Empty))
                {
                    argumentsBuilder.Add(pathAtom);
                }
                break;

            default:
                Contract.Assert(false, $"Unexpected argument '{value.GetType()}'");
                break;
            }
        }
Beispiel #27
0
        public static Process CreateDummyProcessWithInputs(IEnumerable <FileArtifact> inputs, BuildXLContext context)
        {
            FileArtifact output = FileArtifact.CreateSourceFile(AbsolutePath.Create(context.PathTable, @"\\FAKEPATH\output" + s_procCounter + ".txt")).CreateNextWrittenVersion();

            s_procCounter++;
            FileArtifact exe = FileArtifact.CreateSourceFile(AbsolutePath.Create(context.PathTable, @"\\FAKEPATH\tool.exe"));

            var pipDataBuilder = new PipDataBuilder(context.StringTable);

            return(new Process(
                       executable: exe,
                       workingDirectory: AbsolutePath.Create(context.PathTable, @"\\FAKEPATH\"),
                       arguments: pipDataBuilder.ToPipData(" ", PipDataFragmentEscaping.NoEscaping),
                       responseFile: FileArtifact.Invalid,
                       responseFileData: PipData.Invalid,
                       environmentVariables: ReadOnlyArray <EnvironmentVariable> .Empty,
                       standardInput: FileArtifact.Invalid,
                       standardOutput: FileArtifact.Invalid,
                       standardError: FileArtifact.Invalid,
                       standardDirectory: output.Path.GetParent(context.PathTable),
                       warningTimeout: null,
                       timeout: null,
                       dependencies: ReadOnlyArray <FileArtifact> .From(inputs.Union(new[] { exe })),
                       outputs: ReadOnlyArray <FileArtifactWithAttributes> .FromWithoutCopy(output.WithAttributes()),
                       directoryDependencies: ReadOnlyArray <DirectoryArtifact> .Empty,
                       directoryOutputs: ReadOnlyArray <DirectoryArtifact> .Empty,
                       orderDependencies: ReadOnlyArray <PipId> .Empty,
                       untrackedPaths: ReadOnlyArray <AbsolutePath> .Empty,
                       untrackedScopes: ReadOnlyArray <AbsolutePath> .Empty,
                       tags: ReadOnlyArray <StringId> .Empty,
                       successExitCodes: ReadOnlyArray <int> .Empty,
                       semaphores: ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                       provenance: PipProvenance.CreateDummy(context),
                       toolDescription: StringId.Invalid,
                       additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty));
        }
Beispiel #28
0
        private static Process CreateConsoleProcessInContainer(
            BuildXLContext context,
            TempFileStorage tempFiles,
            PathTable pt,
            string arguments,
            ReadOnlyArray <FileArtifactWithAttributes> outputFiles,
            ReadOnlyArray <DirectoryArtifact> directoryOutputs,
            ContainerIsolationLevel containerIsolationLevel = ContainerIsolationLevel.IsolateAllOutputs)
        {
            var executableFileArtifact = FileArtifact.CreateSourceFile(AbsolutePath.Create(context.PathTable, CmdHelper.CmdX64));

            var argumentBuilder = new PipDataBuilder(context.PathTable.StringTable);

            argumentBuilder.Add("/d");
            argumentBuilder.Add("/c");
            using (argumentBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, " "))
            {
                foreach (var arg in arguments.Split(new[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries))
                {
                    argumentBuilder.Add(arg);
                }
            }

            string workingDirectory             = tempFiles.GetUniqueDirectory();
            var    workingDirectoryAbsolutePath = AbsolutePath.Create(context.PathTable, workingDirectory);

            string uniqueOutputDirectory     = tempFiles.GetUniqueDirectory();
            var    uniqueOutputDirectoryPath = AbsolutePath.Create(context.PathTable, uniqueOutputDirectory);

            string uniqueRedirectedOutputDirectory     = tempFiles.GetUniqueDirectory("redirected");
            var    uniqueRedirectedOutputDirectoryPath = AbsolutePath.Create(context.PathTable, uniqueRedirectedOutputDirectory);

            var pip = new Process(
                executableFileArtifact,
                workingDirectoryAbsolutePath,
                argumentBuilder.ToPipData(" ", PipDataFragmentEscaping.NoEscaping),
                FileArtifact.Invalid,
                PipData.Invalid,
                ReadOnlyArray <EnvironmentVariable> .FromWithoutCopy(),
                FileArtifact.Invalid,
                FileArtifact.Invalid,
                FileArtifact.Invalid,
                tempFiles.GetUniqueDirectory(pt),
                null,
                null,
                dependencies: ReadOnlyArray <FileArtifact> .FromWithoutCopy(new[] { executableFileArtifact }),
                outputs: outputFiles,
                directoryDependencies: ReadOnlyArray <DirectoryArtifact> .Empty,
                directoryOutputs: directoryOutputs,
                orderDependencies: ReadOnlyArray <PipId> .Empty,
                untrackedPaths: ReadOnlyArray <AbsolutePath> .Empty,
                untrackedScopes: ReadOnlyArray <AbsolutePath> .Empty,
                tags: ReadOnlyArray <StringId> .Empty,
                successExitCodes: ReadOnlyArray <int> .Empty,
                semaphores: ReadOnlyArray <ProcessSemaphoreInfo> .Empty,
                provenance: PipProvenance.CreateDummy(context),
                toolDescription: StringId.Invalid,
                additionalTempDirectories: ReadOnlyArray <AbsolutePath> .Empty,
                options: Process.Options.NeedsToRunInContainer,
                uniqueOutputDirectory: uniqueOutputDirectoryPath,
                uniqueRedirectedDirectoryRoot: uniqueRedirectedOutputDirectoryPath,
                containerIsolationLevel: containerIsolationLevel);

            return(pip);
        }
Beispiel #29
0
 internal FragmentScope(PipDataBuilder pipDataBuilder)
 {
     m_pipDataBuilder = pipDataBuilder;
 }
Beispiel #30
0
        private bool TryAddMsBuildArguments(ProjectWithPredictions project, PipDataBuilder pipDataBuilder, AbsolutePath logDirectory, AbsolutePath outputResultCacheFile, out string failureDetail)
        {
            // Common arguments to all MsBuildExe invocations
            pipDataBuilder.AddRange(s_commonArgumentsToMsBuildExe.Select(argument => PipDataAtom.FromString(argument)));

            // Log verbosity
            if (!TryGetLogVerbosity(m_resolverSettings.LogVerbosity, out string logVerbosity))
            {
                failureDetail = $"Cannot set the MSBuild log verbosity. '{m_resolverSettings.LogVerbosity}' is not a valid option.";
                return(false);
            }

            AddLogArgument(pipDataBuilder, 1, logDirectory.Combine(PathTable, "msbuild.log"), $"Verbosity={logVerbosity}");
            AddLogArgument(pipDataBuilder, 2, logDirectory.Combine(PathTable, "msbuild.wrn"), "Verbosity=Quiet;warningsonly");
            AddLogArgument(pipDataBuilder, 3, logDirectory.Combine(PathTable, "msbuild.err"), "Verbosity=Quiet;errorsonly");
            AddLogArgument(pipDataBuilder, 4, logDirectory.Combine(PathTable, "msbuild.prf"), "PerformanceSummary");

            // Global properties on the project are turned into build parameters
            foreach (var kvp in project.GlobalProperties)
            {
                AddMsBuildProperty(pipDataBuilder, kvp.Key, kvp.Value);
            }

            // Configure binary logger if specified
            if (m_resolverSettings.EnableBinLogTracing == true)
            {
                using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
                {
                    pipDataBuilder.Add(PipDataAtom.FromString("/binaryLogger:"));
                    pipDataBuilder.Add(PipDataAtom.FromAbsolutePath(logDirectory.Combine(PathTable, "msbuild.binlog")));
                }
            }

            // Targets to execute.
            var targets = project.PredictedTargetsToExecute.Targets;

            Contract.Assert(targets.Count > 0);
            foreach (string target in targets)
            {
                pipDataBuilder.Add(PipDataAtom.FromString($"/t:{target}"));
            }


            // Pass the output result cache file if present
            if (outputResultCacheFile != AbsolutePath.Invalid)
            {
                using (pipDataBuilder.StartFragment(PipDataFragmentEscaping.NoEscaping, string.Empty))
                {
                    // Flag /orc is the short form of /outputResultsCache, and part of MSBuild 'build in isolation' mode.
                    // By specifying this flag, MSBuild will write the build result at the end of this invocation into the cache file
                    pipDataBuilder.Add(PipDataAtom.FromString("/orc:"));
                    pipDataBuilder.Add(PipDataAtom.FromAbsolutePath(outputResultCacheFile));
                }
            }
            else
            {
                // In legacy (non-isolated) mode, we still have to rely on SDKs honoring this flag
                pipDataBuilder.Add(PipDataAtom.FromString("/p:buildprojectreferences=false"));
            }

            failureDetail = string.Empty;
            return(true);
        }