private PipData FinishArgumentsAndOverflowArgumentsToResponseFile(DirectoryArtifact defaultDirectory) { Contract.Requires(defaultDirectory.IsValid); PipData arguments = default; var argumentsBuilder = m_argumentsBuilder.Instance; if (!m_responseFileFirstArg.IsDefault) { bool mkRespFile = m_responseFileForceCreation; if (!mkRespFile) { // make a response file only if the command-line is too long arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); // Normalize choice to use response file by assuming paths are of length max path with a space. This will // ensure there are no cases where changing the root will change whether a response file is used. int cmdLineLength = arguments.GetMaxPossibleLength(m_pathTable.StringTable); mkRespFile = cmdLineLength > MaxCommandLineLength; } if (mkRespFile) { // create a pip data for the stuff in the response file ResponseFileData = argumentsBuilder.ToPipData("\r\n", PipDataFragmentEscaping.CRuntimeArgumentRules, m_responseFileFirstArg); // generate the file ResponseFile = FileArtifact.CreateSourceFile(defaultDirectory.Path.Combine(m_pathTable, PathAtom.Create(m_pathTable.StringTable, "args.rsp"))); argumentsBuilder.TrimEnd(m_responseFileFirstArg); AddUntrackedFile(ResponseFile); if (string.IsNullOrEmpty(m_responseFilePrefix)) { argumentsBuilder.Add(ResponseFile); } else { using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, m_pathTable.StringTable.Empty)) { argumentsBuilder.Add(m_responseFilePrefix); argumentsBuilder.Add(ResponseFile); } } arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); } } else { arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); } return(arguments); }
/// <summary> /// Configure the processBuilder's ResponseFile and ResponseFileData according to this specification. /// This method mutates the processBuilder, changing its argumentsBuilder, ResponseFile and ResponseFileData accordingly. /// We return the arguments to be passed to the process. /// </summary> internal PipData SplitArgumentsAndCreateResponseFileIfNeeded(ProcessBuilder processBuilder, DirectoryArtifact defaultDirectory, PathTable pathTable) { PipData arguments = default; // We'll return the actual arguments to be passed to the process. var argumentsBuilder = processBuilder.ArgumentsBuilder; var cutoffArg = m_firstArg; // We will create a response file in the following cases: // 1. If an explicit response file content was specified, either by having m_explicitData or // by having m_forceCreation = true // 2. If the argument line is too long (longer than MaxCommandLineLength) and m_firstArg is not the default. // An additional argument is added to the process specifying the response file location, prefixed // by m_prefix, unless m_requiresArgument was set to false. if (!m_firstArg.IsDefault || m_explicitData.IsValid) { bool argumentLineTooLong = false; if (!m_forceCreation) { // make a response file only if the command-line is too long arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); // Normalize choice to use response file by assuming paths are of length max path with a space. This will // ensure there are no cases where changing the root will change whether a response file is used. int cmdLineLength = arguments.GetMaxPossibleLength(pathTable.StringTable); argumentLineTooLong = cmdLineLength > ProcessBuilder.MaxCommandLineLength; } if (m_forceCreation || argumentLineTooLong || m_explicitData.IsValid) { // add the explicit contents if we have to if (m_explicitData.IsValid) { if (!argumentLineTooLong) { // If there was no overflow, we mark 'here' as the starting // point for the response file before adding the explicit data as an 'argument'. cutoffArg = argumentsBuilder.CreateCursor(); } argumentsBuilder.Add(m_explicitData); } // create a pip data for the stuff in the response file processBuilder.ResponseFileData = argumentsBuilder.ToPipData(Environment.NewLine, PipDataFragmentEscaping.CRuntimeArgumentRules, cutoffArg); // generate the file processBuilder.ResponseFile = FileArtifact.CreateSourceFile(GetResponseFilePath(defaultDirectory, pathTable)); argumentsBuilder.TrimEnd(cutoffArg); processBuilder.AddUntrackedFile(processBuilder.ResponseFile); if (m_requiresArgument) { if (string.IsNullOrEmpty(m_prefix)) { argumentsBuilder.Add(processBuilder.ResponseFile); } else { using (argumentsBuilder.StartFragment(PipDataFragmentEscaping.CRuntimeArgumentRules, pathTable.StringTable.Empty)) { argumentsBuilder.Add(m_prefix); argumentsBuilder.Add(processBuilder.ResponseFile); } } } arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); } } else { arguments = argumentsBuilder.ToPipData(" ", PipDataFragmentEscaping.CRuntimeArgumentRules); } return(arguments); }