private void validate() { if (_arch == null) { if (_verbose) { Console.WriteLine("Defaulting architecture to x64."); } _arch = "x64"; } if (_build == null) { if (_verbose) { Console.WriteLine("Defaulting build to Debug."); } _build = "Debug"; } if (_os == null) { if (_verbose) { Console.WriteLine("Discovering operating system."); } SetPlatform(); if (_verbose) { Console.WriteLine("Operating system is {0}", _os); } } if (_srcDirectory == null) { if (_verbose) { Console.WriteLine("Formatting jit directory."); } _srcDirectory = "jit"; } if (_projects.Count == 0 && _verbose) { Console.WriteLine("Formatting dll project."); } if (!_untidy && ((_arch == null) || (_os == null) || (_build == null))) { _syntaxResult.ReportError("Specify --arch, --os, and --build for clang-tidy run."); } if (_rootPath == null) { if (_verbose) { Console.WriteLine("Discovering --coreclr."); } _rootPath = Utility.GetRepoRoot(_verbose); _rootPath = Path.Combine(_rootPath, "src", "coreclr"); if (_rootPath == null) { _syntaxResult.ReportError("Specify --coreclr"); } else { Console.WriteLine("Using --coreclr={0}", _rootPath); } } if (!Directory.Exists(_rootPath)) { // If _rootPath doesn't exist, it is an invalid path _syntaxResult.ReportError("Invalid path to coreclr directory. Specify with --coreclr"); } else if (!File.Exists(Path.Combine(_rootPath, "build-runtime.cmd")) || !File.Exists(Path.Combine(_rootPath, "build-runtime.sh")) || !File.Exists(Path.Combine(_rootPath, "clr.featuredefines.props"))) { // Doesn't look like the coreclr directory. _syntaxResult.ReportError("Invalid path to coreclr directory. Specify with --coreclr"); } // Check that we can find compile_commands.json on windows if (_os.ToLower() == "windows") { // If the user didn't specify a compile_commands.json, we need to see if one exists, and if not, create it. if (!_untidy && _compileCommands == null) { string[] compileCommandsPath = { _rootPath, "..", "..", "artifacts", "nmakeobj", _os + "." + _arch + "." + _build, "compile_commands.json" }; _compileCommands = Path.Combine(compileCommandsPath); _rewriteCompileCommands = true; if (!File.Exists(_compileCommands)) { // We haven't done a build, so we need to do one. if (_verbose) { Console.WriteLine("Neither compile_commands.json exists, nor is there a build log. Running CMake to generate compile_commands.json."); } string[] commandArgs = { _arch, _build, "usenmakemakefiles" }; string buildPath = Path.Combine(_rootPath, "build-runtime.cmd"); if (_verbose) { Console.WriteLine("Running: {0} {1}", buildPath, String.Join(" ", commandArgs)); } ProcessResult result = Utility.ExecuteProcess(buildPath, commandArgs, !_verbose, _rootPath); if (result.ExitCode != 0) { Console.WriteLine("There was an error running CMake to generate compile_commands.json. Please do a full build to generate a build log."); Environment.Exit(-1); } } } } // Check that we can find the compile_commands.json file on other platforms else { // If the user didn't specify a compile_commands.json, we need to see if one exists, and if not, create it. if (!_untidy && _compileCommands == null) { string[] compileCommandsPath = { _rootPath, "..", "..", "artifacts", "obj", "coreclr", _os + "." + _arch + "." + _build, "compile_commands.json" }; _compileCommands = Path.Combine(compileCommandsPath); _rewriteCompileCommands = true; if (!File.Exists(Path.Combine(compileCommandsPath))) { Console.WriteLine("Can't find compile_commands.json file. Running configure."); string[] commandArgs = { _arch, _build, "configureonly", "-cmakeargs", "-DCMAKE_EXPORT_COMPILE_COMMANDS=1" }; string buildPath = Path.Combine(_rootPath, "build-runtime.sh"); if (_verbose) { Console.WriteLine("Running: {0} {1}", buildPath, String.Join(" ", commandArgs)); } ProcessResult result = Utility.ExecuteProcess(buildPath, commandArgs, true, _rootPath); if (result.ExitCode != 0) { Console.WriteLine("There was an error running CMake to generate compile_commands.json. Please run build-runtime.sh configureonly"); Environment.Exit(-1); } } } } }
public static bool RunClangFormat(List <string> filenames, bool fix, bool verbose) { string formatFix = fix ? "-i" : ""; string outputReplacementXml = fix ? "" : "-output-replacements-xml"; bool formatOk = true; int quietErrorLimit = 10; List <string> clangFormatErrors = new List <string>(); Parallel.ForEach(filenames, (filename) => { Process process = new Process(); // Run clang-format List <string> commandArgs = new List <string> { formatFix, "-style=file", outputReplacementXml, filename }; if (verbose) { Console.WriteLine("Running: {0} {1}", "clang-format", String.Join(" ", commandArgs)); } ProcessResult result = Utility.ExecuteProcess("clang-format", commandArgs, true); if (result.StdOut.Contains("<replacement ") && !fix) { if (verbose) { // Read in the file string fileContents = File.ReadAllText(filename); string[] fileContentsList = fileContents.Split(new[] { Environment.NewLine }, StringSplitOptions.None); int offsetChange = 0; // Read in the xml generated by clang-format var doc = new XmlDocument(); doc.LoadXml(result.StdOut); XmlNodeList replacements = doc.DocumentElement.ChildNodes; string output = "clang-format: there are formatting errors in " + filename + "\n"; foreach (XmlNode replacement in replacements) { // Figure out offset and length for each replacement if (replacement.Name.Equals("replacement")) { // We use offsetChange to calculate the new offset based on other formatting // changes that have already been made. int offset = Int32.Parse(replacement.Attributes["offset"].Value) + offsetChange; int length = Int32.Parse(replacement.Attributes["length"].Value); string replacementText = replacement.InnerText; // Undo the replacements clang-format makes when it prints the xml replacementText = replacementText.Replace(" ", "\\n"); replacementText = replacementText.Replace(" ", "\\r"); replacementText = replacementText.Replace("<;", "<"); replacementText = replacementText.Replace("&", "&"); // To calculate the cummulative amount of bytes of change we have made, we // subtract the length of text that we will be replacing, and add the // length of text that we will be inserting. offsetChange = offsetChange - length + replacementText.Length; // To calculate the line numbers, we scan to the offset in the file, and // count the number of new lines we have seen. To calculate the end line // number of the code snippet, we count the number of newlines up to the // location of offset + length var startLineNumber = fileContents.Take(offset).Count(c => c == '\n'); var endLineNumber = fileContents.Take(offset + length).Count(c => c == '\n'); output = output + "At Line " + (startLineNumber + 1) + " Before:\n"; foreach (string line in fileContentsList.Skip(startLineNumber).Take(endLineNumber - startLineNumber + 1)) { output = output + line + "\n"; } output = output + "After:\n"; // To do the replacement, we remove the old text between offset and offset + length // and insert the new text fileContents = fileContents.Remove(offset, length).Insert(offset, replacementText); fileContentsList = fileContents.Split(new[] { Environment.NewLine }, StringSplitOptions.None); startLineNumber = fileContents.Take(offset).Count(c => c == '\n'); endLineNumber = fileContents.Take(offset + replacementText.Length).Count(c => c == '\n'); foreach (string line in fileContentsList.Skip(startLineNumber).Take(endLineNumber - startLineNumber + 1)) { output = output + line + "\n"; } } } clangFormatErrors.Add(output); } formatOk = false; } }); int quietErrorCount = 0; foreach (string failure in clangFormatErrors) { if (verbose || quietErrorCount < quietErrorLimit) { Console.WriteLine(""); Console.WriteLine("{0}", failure); quietErrorCount++; } } return(formatOk); }
private void SetPlatform() { // Extract system RID from dotnet cli List <string> commandArgs = new List <string> { "--info" }; if (_verbose) { Console.WriteLine("Running: {0} {1}", "dotnet", String.Join(" ", commandArgs)); } // Running "dotnet" (the executable, not the .cmd/.sh wrapper script) when the current // directory is within a runtime repo clone does not give us the information we want: // it is missing the "OS Platform" and "RID" lines. So, pick some other directory that // is expected to not be in a repo clone, and run the "dotnet" command from that directory. string commandWorkingDirectory = ""; OperatingSystem os = Environment.OSVersion; PlatformID pid = os.Platform; switch (pid) { case PlatformID.Win32NT: commandWorkingDirectory = Environment.SystemDirectory; break; case PlatformID.Unix: commandWorkingDirectory = "/"; // Use the root directory break; default: break; } ProcessResult result = Utility.ExecuteProcess("dotnet", commandArgs, true, commandWorkingDirectory); if (result.ExitCode != 0) { Console.Error.WriteLine("dotnet --info returned non-zero"); } var lines = result.StdOut.Split(new[] { Environment.NewLine }, StringSplitOptions.None); foreach (var line in lines) { Regex pattern = new Regex(@"OS Platform:([\sA-Za-z0-9\.-]*)$"); Match match = pattern.Match(line); if (match.Success) { if (match.Groups[1].Value.Trim() == "Windows") { _os = "Windows"; } else if (match.Groups[1].Value.Trim() == "Darwin") { _os = "OSX"; } else if (match.Groups[1].Value.Trim() == "Linux") { // Assuming anything other than Windows or OSX is a Linux flavor _os = "Linux"; } else { Console.WriteLine("Unknown operating system. Please specify with --os"); Environment.Exit(-1); } } } }