// The .NET Foundation licenses this file to you under the MIT license.
using System;
+using System.Collections;
using System.Collections.Generic;
using System.IO;
+using System.IO.Compression;
using System.Reflection;
using System.Text;
public IReadOnlyList<string> CodegenOptions;
+ public string MakeReproPath;
+
public bool CompositeOrInputBubble => Composite || InputBubble;
public CommandLineOptions(string[] args)
syntax.DefineOption("verify-type-and-field-layout", ref VerifyTypeAndFieldLayout, SR.VerifyTypeAndFieldLayoutOption);
syntax.DefineOption("callchain-profile", ref CallChainProfileFile, SR.CallChainProfileFile);
+ syntax.DefineOption("make-repro-path", ref MakeReproPath, SR.MakeReproPathHelp);
+
syntax.DefineOption("h|help", ref Help, SR.HelpOption);
syntax.DefineParameterList("in", ref InputFilePaths, SR.InputFilesToCompile);
HelpText = argSyntax.GetHelpText();
}
+
+ if (MakeReproPath != null)
+ {
+ // Create a repro package in the specified path
+ // This package will have the set of input files needed for compilation
+ // + the original command line arguments
+ // + a rsp file that should work to directly run out of the zip file
+
+ string makeReproPath = MakeReproPath;
+ Directory.CreateDirectory(makeReproPath);
+
+ List<string> crossgenDetails = new List<string>();
+ crossgenDetails.Add("CrossGen2 version");
+ try
+ {
+ crossgenDetails.Add(Environment.GetCommandLineArgs()[0]);
+ } catch {}
+ try
+ {
+ crossgenDetails.Add(System.Diagnostics.FileVersionInfo.GetVersionInfo(Environment.GetCommandLineArgs()[0]).ToString());
+ } catch {}
+
+ crossgenDetails.Add("------------------------");
+ crossgenDetails.Add("Actual Command Line Args");
+ crossgenDetails.Add("------------------------");
+ crossgenDetails.AddRange(args);
+ foreach (string arg in args)
+ {
+ if (arg.StartsWith('@'))
+ {
+ string rspFileName = arg.Substring(1);
+ crossgenDetails.Add("------------------------");
+ crossgenDetails.Add(rspFileName);
+ crossgenDetails.Add("------------------------");
+ try
+ {
+ crossgenDetails.AddRange(File.ReadAllLines(rspFileName));
+ } catch {}
+ }
+ }
+
+ HashCode hashCodeOfArgs = new HashCode();
+ foreach (string s in crossgenDetails)
+ hashCodeOfArgs.Add(s);
+
+ string zipFileName = ((uint)hashCodeOfArgs.ToHashCode()).ToString();
+
+ if (OutputFilePath != null)
+ zipFileName = zipFileName + "_" + Path.GetFileName(OutputFilePath);
+
+ zipFileName = Path.Combine(MakeReproPath, Path.ChangeExtension(zipFileName, ".zip"));
+
+ Console.WriteLine($"Creating {zipFileName}");
+ using (var archive = ZipFile.Open(zipFileName, ZipArchiveMode.Create))
+ {
+ ZipArchiveEntry commandEntry = archive.CreateEntry("crossgen2command.txt");
+ using (StreamWriter writer = new StreamWriter(commandEntry.Open()))
+ {
+ foreach (string s in crossgenDetails)
+ writer.WriteLine(s);
+ }
+
+ HashSet<string> inputOptionNames = new HashSet<string>();
+ inputOptionNames.Add("-r");
+ inputOptionNames.Add("-u");
+ inputOptionNames.Add("-m");
+ inputOptionNames.Add("--inputbubbleref");
+ Dictionary<string, string> inputToReproPackageFileName = new Dictionary<string, string>();
+
+ List<string> rspFile = new List<string>();
+ foreach (var option in argSyntax.GetOptions())
+ {
+ if (option.GetDisplayName() == "--make-repro-path")
+ {
+ continue;
+ }
+
+ if (option.Value != null && !option.Value.Equals(option.DefaultValue))
+ {
+ if (option.IsList)
+ {
+ if (inputOptionNames.Contains(option.GetDisplayName()))
+ {
+ Dictionary<string, string> dictionary = new Dictionary<string, string>();
+ foreach (string optInList in (IEnumerable)option.Value)
+ {
+ Helpers.AppendExpandedPaths(dictionary, optInList, false);
+ }
+ foreach (string inputFile in dictionary.Values)
+ {
+ rspFile.Add($"{option.GetDisplayName()}:{ConvertFromInputPathToReproPackagePath(inputFile)}");
+ }
+ }
+ else
+ {
+ foreach (object optInList in (IEnumerable)option.Value)
+ {
+ rspFile.Add($"{option.GetDisplayName()}:{optInList}");
+ }
+ }
+ }
+ else
+ {
+ rspFile.Add($"{option.GetDisplayName()}:{option.Value}");
+ }
+ }
+ }
+
+ foreach (var parameter in argSyntax.GetParameters())
+ {
+ if (parameter.Value != null)
+ {
+ if (parameter.IsList)
+ {
+ foreach (object optInList in (IEnumerable)parameter.Value)
+ {
+ rspFile.Add($"{ConvertFromInputPathToReproPackagePath((string)optInList)}");
+ }
+ }
+ else
+ {
+ rspFile.Add($"{ConvertFromInputPathToReproPackagePath((string)parameter.Value.ToString())}");
+ }
+ }
+ }
+
+ ZipArchiveEntry rspEntry = archive.CreateEntry("crossgen2repro.rsp");
+ using (StreamWriter writer = new StreamWriter(rspEntry.Open()))
+ {
+ foreach (string s in rspFile)
+ writer.WriteLine(s);
+ }
+
+ string ConvertFromInputPathToReproPackagePath(string inputPath)
+ {
+ if (inputToReproPackageFileName.TryGetValue(inputPath, out string reproPackagePath))
+ {
+ return reproPackagePath;
+ }
+
+ try
+ {
+ string inputFileDir = inputToReproPackageFileName.Count.ToString();
+ reproPackagePath = Path.Combine(inputFileDir, Path.GetFileName(inputPath));
+ archive.CreateEntryFromFile(inputPath, reproPackagePath);
+ inputToReproPackageFileName.Add(inputPath, reproPackagePath);
+
+ return reproPackagePath;
+ }
+ catch
+ {
+ return inputPath;
+ }
+ }
+ }
+ }
}
}
}