예제 #1
0
        /// <summary>
        /// Runs iwyu. Blocks until finished.
        /// </summary>
        static public string RunIncludeWhatYouUse(string fullFileName, EnvDTE.Project project, IncludeWhatYouUseOptionsPage settings)
        {
            string reasonForFailure;
            string preprocessorDefintions = VSUtils.VCUtils.GetCompilerSetting_PreprocessorDefinitions(project, out reasonForFailure);

            if (preprocessorDefintions == null)
            {
                Output.Instance.ErrorMsg("Can't run IWYU: {0}", reasonForFailure);
                return(null);
            }

            string output = "";

            using (var process = new System.Diagnostics.Process())
            {
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.StartInfo.FileName  = settings.ExecutablePath;
                process.StartInfo.Arguments = "";

                // Include-paths and Preprocessor.
                var includeEntries = VSUtils.GetProjectIncludeDirectories(project, false);
                process.StartInfo.Arguments = includeEntries.Aggregate("", (current, inc) => current + ("-I \"" + inc + "\" "));
                process.StartInfo.Arguments = preprocessorDefintions.
                                              Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).
                                              Aggregate(process.StartInfo.Arguments, (current, def) => current + ("-D" + def + " "));

                // Clang options
                // Disable all diagnostics
                process.StartInfo.Arguments += "-w ";
                // ... despite of that "invalid token paste" comes through a lot. Disable it.
                process.StartInfo.Arguments += "-Wno-invalid-token-paste ";
                // Assume C++14
                process.StartInfo.Arguments += "-std=c++14 ";
                // MSVC specific. See https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
                process.StartInfo.Arguments += "-fms-compatibility -fms-extensions -fdelayed-template-parsing ";
                process.StartInfo.Arguments += $"-fmsc-version={VSUtils.GetMSCVerString()} ";
                // Architecture
                var targetMachine = VSUtils.VCUtils.GetLinkerSetting_TargetMachine(project, out reasonForFailure);
                if (!targetMachine.HasValue)
                {
                    Output.Instance.ErrorMsg("Failed to query for target machine: {0}", reasonForFailure);
                }
                else
                {
                    switch (targetMachine.Value)
                    {
                    // Most targets give an error of this form:
                    // "error: unknown target CPU 'x86'"
                    // It seems iwyu is only really fine with x86-64

                    /*case VCProjectUtils.Base.TargetMachineType.X86:
                     *  process.StartInfo.Arguments += "-march=x86 ";
                     *  break;*/
                    case VCProjectUtils.Base.TargetMachineType.AMD64:
                        process.StartInfo.Arguments += "-march=x86-64 ";
                        break;

                        /*case VCProjectUtils.Base.TargetMachineType.ARM:
                         *  process.StartInfo.Arguments += "-march=arm ";
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.MIPS:
                         *  process.StartInfo.Arguments += "-march=mips ";
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.THUMB:
                         *  process.StartInfo.Arguments += "-march=thumb ";
                         *  break;*/
                    }
                }

                // icwyu options
                {
                    process.StartInfo.Arguments += "-Xiwyu --verbose=" + settings.LogVerbosity + " ";
                    for (int i = 0; i < settings.MappingFiles.Length; ++i)
                    {
                        process.StartInfo.Arguments += "-Xiwyu --mapping_file=\"" + settings.MappingFiles[i] + "\" ";
                    }
                    if (settings.NoDefaultMappings)
                    {
                        process.StartInfo.Arguments += "-Xiwyu --no_default_mappings ";
                    }
                    if (settings.PCHInCode)
                    {
                        process.StartInfo.Arguments += "-Xiwyu --pch_in_code ";
                    }
                    switch (settings.PrefixHeaderIncludes)
                    {
                    case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Add:
                        process.StartInfo.Arguments += "-Xiwyu --prefix_header_includes=add ";
                        break;

                    case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Remove:
                        process.StartInfo.Arguments += "-Xiwyu --prefix_header_includes=remove ";
                        break;

                    case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Keep:
                        process.StartInfo.Arguments += "-Xiwyu --prefix_header_includes=keep ";
                        break;
                    }
                    if (settings.TransitiveIncludesOnly)
                    {
                        process.StartInfo.Arguments += "-Xiwyu --transitive_includes_only ";
                    }

                    // Set max line length so something large so we don't loose comment information.
                    // Documentation:
                    // --max_line_length: maximum line length for includes. Note that this only affects comments and alignment thereof,
                    // the maximum line length can still be exceeded with long file names(default: 80).
                    process.StartInfo.Arguments += "-Xiwyu --max_line_length=1024 ";

                    // Custom stuff.
                    process.StartInfo.Arguments += settings.AdditionalParameters;
                    process.StartInfo.Arguments += " ";
                }


                // Finally, the file itself.
                process.StartInfo.Arguments += "\"";
                process.StartInfo.Arguments += fullFileName;
                process.StartInfo.Arguments += "\"";

                Output.Instance.Write("Running command '{0}' with following arguments:\n{1}\n\n", process.StartInfo.FileName, process.StartInfo.Arguments);

                // Start the child process.
                process.EnableRaisingEvents = true;
                process.OutputDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };
                process.ErrorDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };
                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();
                process.CancelOutputRead();
                process.CancelErrorRead();
            }

            return(output);
        }
예제 #2
0
        /// <summary>
        /// Runs iwyu. Blocks until finished.
        /// </summary>
        static public string RunIncludeWhatYouUse(string fullFileName, EnvDTE.Project project, IncludeWhatYouUseOptionsPage settings)
        {
            string reasonForFailure;
            string preprocessorDefintions = VSUtils.VCUtils.GetCompilerSetting_PreprocessorDefinitions(project, out reasonForFailure);

            if (preprocessorDefintions == null)
            {
                Output.Instance.ErrorMsg("Can't run IWYU: {0}", reasonForFailure);
                return(null);
            }

            string output = "";

            using (var process = new System.Diagnostics.Process())
            {
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.StartInfo.FileName = settings.ExecutablePath;

                // Clang options
                // Disable all diagnostics
                var iwyuOptions = "-w ";
                // ... despite of that "invalid token paste" comes through a lot. Disable it.
                iwyuOptions += "-Wno-invalid-token-paste ";
                // Assume C++14
                // arguments += "-std=c++14 ";
                // MSVC specific. See https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
                iwyuOptions += "-fms-extensions -fms-compatibility -fdelayed-template-parsing ";
                iwyuOptions += $"-fmsc-version={VSUtils.GetMSCVerString()} ";
                // Architecture
                var targetMachine = VSUtils.VCUtils.GetLinkerSetting_TargetMachine(project, out reasonForFailure);
                if (!targetMachine.HasValue)
                {
                    Output.Instance.ErrorMsg("Failed to query for target machine: {0}", reasonForFailure);
                }
                else
                {
                    switch (targetMachine.Value)
                    {
                    // Most targets give an error of this form:
                    // "error: unknown target CPU 'x86'"
                    // It seems iwyu is only really fine with x86-64

                    /*case VCProjectUtils.Base.TargetMachineType.X86:
                     *  clangOptions += "-march=x86 ";
                     *  break;*/
                    case VCProjectUtils.Base.TargetMachineType.AMD64:
                        iwyuOptions += "-march=x86-64 ";
                        break;

                        /*case VCProjectUtils.Base.TargetMachineType.ARM:
                         *  clangOptions += "-march=arm ";
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.MIPS:
                         *  clangOptions += "-march=mips ";
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.THUMB:
                         *  clangOptions += "-march=thumb ";
                         *  break;*/
                    }
                }


                iwyuOptions += "-Xiwyu --verbose=" + settings.LogVerbosity + " ";
                if (settings.MappingFiles.Length == 0)
                {
                    settings.MappingFiles = new string[] { "stl.c.headers.imp", "msvc.imp", "boost-all.imp", "boost-all-private.imp" };
                }
                for (int i = 0; i < settings.MappingFiles.Length; ++i)
                {
                    iwyuOptions += "-Xiwyu --mapping_file=\"" + settings.MappingFiles[i] + "\" ";
                }
                if (settings.NoDefaultMappings)
                {
                    iwyuOptions += "-Xiwyu --no_default_mappings ";
                }
                if (settings.PCHInCode)
                {
                    iwyuOptions += "-Xiwyu --pch_in_code ";
                }
                switch (settings.PrefixHeaderIncludes)
                {
                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Add:
                    iwyuOptions += "-Xiwyu --prefix_header_includes=add ";
                    break;

                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Remove:
                    iwyuOptions += "-Xiwyu --prefix_header_includes=remove ";
                    break;

                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Keep:
                    iwyuOptions += "-Xiwyu --prefix_header_includes=keep ";
                    break;
                }
                if (settings.TransitiveIncludesOnly)
                {
                    iwyuOptions += "-Xiwyu --transitive_includes_only ";
                }

                // Set max line length so something large so we don't loose comment information.
                // Documentation:
                // --max_line_length: maximum line length for includes. Note that this only affects comments and alignment thereof,
                // the maximum line length can still be exceeded with long file names(default: 80).
                iwyuOptions += "-Xiwyu --max_line_length=1024 ";

                // Include-paths and Preprocessor.
                var includeEntries = VSUtils.GetProjectIncludeDirectories(project, false);
                var includes       = includeEntries.Aggregate("", (current, inc) => current + ("-I \"" + Regex.Escape(inc) + "\" "));

                var defines = " -D " + string.Join(" -D", preprocessorDefintions.Split(';'));

                // write support file. Long argument lists lead to an error. Support files are the solution here.
                // https://github.com/Wumpf/IncludeToolbox/issues/36
                var supportFile    = Path.GetTempFileName();
                var supportContent = includes + " " + defines + " " + Regex.Escape(fullFileName);
                File.WriteAllText(supportFile, supportContent);

                process.StartInfo.Arguments = $"{iwyuOptions} {settings.AdditionalParameters} @{supportFile}";
                Output.Instance.Write("Running command '{0}' with following arguments:\n{1}\n\n", process.StartInfo.FileName, process.StartInfo.Arguments);

                // Start the child process.
                process.EnableRaisingEvents = true;
                process.OutputDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };
                process.ErrorDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };

                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();
                process.CancelOutputRead();
                process.CancelErrorRead();
            }
            output = Regex.Replace(output, @"#include <moduleworks_dummy.*?>.*?\n", "");

            return(output);
        }
예제 #3
0
        /// <summary>
        /// Runs iwyu. Blocks until finished.
        /// </summary>
        static public async Task <string> RunIncludeWhatYouUse(string fullFileName, EnvDTE.Project project, IncludeWhatYouUseOptionsPage settings)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();

            string preprocessorDefintions;

            try
            {
                preprocessorDefintions = VSUtils.VCUtils.GetCompilerSetting_PreprocessorDefinitions(project);
            }
            catch (VCQueryFailure e)
            {
                await Output.Instance.ErrorMsg("Can't run IWYU: {0}", e.Message);

                return(null);
            }

            string output = "";

            using (var process = new System.Diagnostics.Process())
            {
                process.StartInfo.UseShellExecute        = false;
                process.StartInfo.CreateNoWindow         = true;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError  = true;
                process.StartInfo.FileName = settings.ExecutablePath;

                // Clang options
                var clangOptionList = new List <string>();
                // Disable all diagnostics
                clangOptionList.Add("-w");
                // ... despite of that "invalid token paste" comes through a lot. Disable it.
                clangOptionList.Add("-Wno-invalid-token-paste");
                // Assume C++14
                clangOptionList.Add("-std=c++14");
                // MSVC specific. See https://clang.llvm.org/docs/UsersManual.html#microsoft-extensions
                clangOptionList.Add("-fms-compatibility -fms-extensions -fdelayed-template-parsing");
                clangOptionList.Add($"-fmsc-version={VSUtils.GetMSCVerString()}");
                // Architecture
                try
                {
                    switch (VSUtils.VCUtils.GetLinkerSetting_TargetMachine(project))
                    {
                    // Most targets give an error of this form:
                    // "error: unknown target CPU 'x86'"
                    // It seems iwyu is only really fine with x86-64

                    /*case VCProjectUtils.Base.TargetMachineType.X86:
                     *  clangOptions.Add("-march=x86");
                     *  break;*/
                    case VCHelper.TargetMachineType.AMD64:
                        clangOptionList.Add("-march=x86-64");
                        break;

                        /*case VCProjectUtils.Base.TargetMachineType.ARM:
                         *  clangOptions.Add("-march=arm");
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.MIPS:
                         *  clangOptions.Add(""-march=mips");
                         *  break;
                         * case VCProjectUtils.Base.TargetMachineType.THUMB:
                         *  clangOptions.Add(""-march=thumb");
                         *  break;*/
                    }
                }
                catch (VCQueryFailure e)
                {
                    await Output.Instance.ErrorMsg($"Failed to query for target machine: {e.Message}");
                }

                // icwyu options
                var iwyuOptionList = new List <string>();
                iwyuOptionList.Add("--verbose=" + settings.LogVerbosity);
                for (int i = 0; i < settings.MappingFiles.Length; ++i)
                {
                    iwyuOptionList.Add("--mapping_file=\"" + settings.MappingFiles[i] + "\"");
                }
                if (settings.NoDefaultMappings)
                {
                    iwyuOptionList.Add("--no_default_mappings");
                }
                if (settings.PCHInCode)
                {
                    iwyuOptionList.Add("--pch_in_code");
                }
                switch (settings.PrefixHeaderIncludes)
                {
                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Add:
                    iwyuOptionList.Add("--prefix_header_includes=add");
                    break;

                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Remove:
                    iwyuOptionList.Add("--prefix_header_includes=remove");
                    break;

                case IncludeWhatYouUseOptionsPage.PrefixHeaderMode.Keep:
                    iwyuOptionList.Add("--prefix_header_includes=keep");
                    break;
                }
                if (settings.TransitiveIncludesOnly)
                {
                    iwyuOptionList.Add("--transitive_includes_only");
                }

                // Set max line length so something large so we don't loose comment information.
                // Documentation:
                // --max_line_length: maximum line length for includes. Note that this only affects comments and alignment thereof,
                // the maximum line length can still be exceeded with long file names(default: 80).
                iwyuOptionList.Add("--max_line_length=1024");

                /// write support file with includes, defines and the targetgile. Long argument lists lead to an error. Support files are the solution here.
                /// https://github.com/Wumpf/IncludeToolbox/issues/36
                // Include-paths and Preprocessor.
                var includes        = string.Join(" ", VSUtils.GetProjectIncludeDirectories(project, false).Select(x => "-I \"" + x.Replace("\\", "\\\\") + "\""));
                var defines         = string.Join(" ", preprocessorDefintions.Split(';').Select(x => "-D" + x));
                var filename        = "\"" + fullFileName.Replace("\\", "\\\\") + "\"";
                var supportFilePath = Path.GetTempFileName();
                File.WriteAllText(supportFilePath, includes + " " + defines + " " + filename);

                var clangOptions = string.Join(" ", clangOptionList);
                // each include-what-you-use parameter has an -Xiwyu prefix
                var iwyuOptions = string.Join(" ", iwyuOptionList.Select(x => " -Xiwyu " + x));
                process.StartInfo.Arguments = $"{clangOptions} {iwyuOptions} {settings.AdditionalParameters} \"@{supportFilePath}\"";

                Output.Instance.Write("Running command '{0}' with following arguments:\n{1}\n\n", process.StartInfo.FileName, process.StartInfo.Arguments);

                // Start the child process.
                process.EnableRaisingEvents = true;
                process.OutputDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };
                process.ErrorDataReceived += (s, args) =>
                {
                    Output.Instance.WriteLine(args.Data);
                    output += args.Data + "\n";
                };
                process.Start();

                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();
                process.CancelOutputRead();
                process.CancelErrorRead();
            }

            return(output);
        }