diff --git a/src/coreclr/tools/Common/CommandLineHelpers.cs b/src/coreclr/tools/Common/CommandLineHelpers.cs index 2e8028abfd841a..f7d4a46ebe7a1d 100644 --- a/src/coreclr/tools/Common/CommandLineHelpers.cs +++ b/src/coreclr/tools/Common/CommandLineHelpers.cs @@ -287,5 +287,58 @@ private static void AppendExpandedPaths(Dictionary dictionary, s } } } + + /// + /// Read the response file line by line and treat each line as a single token. + /// Skip the comment lines that start with `#`. + /// A return value indicates whether the operation succeeded. + /// + /// + /// This method does not support: + /// * referencing another response file. + /// * inline `#` comments. + /// + public static bool TryReadResponseFile(string filePath, out IReadOnlyList newTokens, out string error) + { + try + { + var tokens = new List(); + foreach (string line in File.ReadAllLines(filePath)) + { + string token = line.Trim(); + if (token.Length > 0 && token[0] != '#') + { + if (token.EndsWith('"')) + { + int firstQuotePosition = token.IndexOf('"'); + + // strip leading and trailing quotes from value. + if (firstQuotePosition >= 0 && firstQuotePosition < token.Length - 1 && + (firstQuotePosition == 0 || token[firstQuotePosition - 1] != '\\')) + { + token = token[..firstQuotePosition] + token[(firstQuotePosition + 1)..^1]; + } + } + + tokens.Add(token); + } + } + + newTokens = tokens; + error = null; + return true; + } + catch (FileNotFoundException) + { + error = $"Response file not found: '{filePath}'"; + } + catch (IOException e) + { + error = $"Error reading response file '{filePath}': {e}"; + } + + newTokens = null; + return false; + } } } diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index 6d73b489c0b518..a3b268fa418826 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -761,6 +761,7 @@ private static IEnumerable ProcessWarningCodes(IEnumerable warningC private static int Main(string[] args) => new CommandLineBuilder(new ILCompilerRootCommand(args)) + .UseTokenReplacer(Helpers.TryReadResponseFile) .UseVersionOption("-v") .UseHelp(context => context.HelpBuilder.CustomizeLayout(ILCompilerRootCommand.GetExtendedHelp)) .UseParseErrorReporting() diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index 9a407f9eeb0ae6..72ef597a41d535 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -974,6 +974,7 @@ internal static bool IsValidPublicKey(byte[] blob) private static int Main(string[] args) => new CommandLineBuilder(new Crossgen2RootCommand(args)) + .UseTokenReplacer(Helpers.TryReadResponseFile) .UseVersionOption("-v") .UseHelp(context => context.HelpBuilder.CustomizeLayout(Crossgen2RootCommand.GetExtendedHelp)) .UseParseErrorReporting()