Exemple #1
0
        //---------------------------------------------------------------------
        _dispBuildEvents_OnBuildProjConfigDoneEventHandler CreateBuildHandler(
            string solutionConfigurationName,
            string projectName,
            Action <bool> userCallBack)
        {
            var buildContext = new BuildContext();
            _dispBuildEvents_OnBuildProjConfigDoneEventHandler onBuildDone =
                (string project, string projectConfig, string platform, string solutionConfig, bool success)
                => OnBuildProjConfigDone(
                    project, projectConfig, platform,
                    solutionConfig, success, buildContext);

            buildContext.OnBuildDone  = onBuildDone;
            buildContext.UserCallBack = userCallBack;
            buildContext.ProjectName  = projectName;
            buildContext.SolutionConfigurationName = solutionConfigurationName;

            return(onBuildDone);
        }
        // 1: show assembly code for currently open source file
        // 2: show preprocessed source code
        private void showCppOutput(int mode = 1)
        {
            string functionOfInterest;
            string curCodeLine;

            inspectCurrentCppFile(out functionOfInterest, out curCodeLine);

            // get current configuration
            Document             doc  = dte.ActiveDocument;
            Project              proj = doc.ProjectItem.ContainingProject;
            ConfigurationManager mgr  = proj.ConfigurationManager;
            string platform           = mgr.ActiveConfiguration.PlatformName;
            string conf = mgr.ActiveConfiguration.ConfigurationName;

            // find the currently active configuration for the current file
            // don't use SolutionBuild as there may be mixed platforms
            // use late binding for version independence
            dynamic file        = doc.ProjectItem.Object;                             // as VCFile
            dynamic fileconfigs = file.FileConfigurations;                            // as IVCCollection
            dynamic fileconfig  = fileconfigs.Item(conf + "|" + platform);            // as VCFileConfiguration
            dynamic tool        = fileconfig.Tool;                                    // VCCLCompilerTool

            // brute-force way to prevent project file modifications
            // copy to TEMP and restore later
            proj.Save();
            string tempCopyPath = Path.Combine(Path.GetTempPath(), proj.Name);

            File.Copy(proj.FullName, tempCopyPath, true);

            string generatedFile;

            if (mode == 1)
            {
                // asmListingAsmSrc => '.asm'
                generatedFile = Path.GetTempFileName() + ".asm";

                tool.WholeProgramOptimization = false;
                tool.AssemblerOutput          = Enum.Parse(tool.AssemblerOutput.GetType(), "asmListingAsmSrc");
                tool.AssemblerListingLocation = generatedFile;
                tool.WarnAsError = false;
            }
            else             /*if (mode == 2)*/
            {
                generatedFile = Path.GetTempFileName() + ".cpp";

                tool.GeneratePreprocessedFile = Enum.Parse(tool.GeneratePreprocessedFile.GetType(), "preprocessYes");
                // there's no separate option for this, so misuse /Fo
                tool.ObjectFile = generatedFile;
            }

            // VCFileConfiguration.Compile often does not work anymore and blocks the GUI
            // so just use the Compile command by installing a one-time callback
            _dispBuildEvents_OnBuildProjConfigDoneEventHandler onProjBuildDone = null;

            onProjBuildDone = (project, projectConfig, platfrm, solutionConfig, success) =>
            {
                // Unique name is project name including solution folders hierarchy
                if (project != proj.UniqueName)
                {
                    return;
                }

                dte.Events.BuildEvents.OnBuildProjConfigDone -= onProjBuildDone;

                if (File.Exists(tempCopyPath))                 // just to be safe
                {
                    File.Delete(proj.FullName);
                    File.Move(tempCopyPath, proj.FullName);
                }

                if (success)
                {
                    postCompileCpp(generatedFile, mode, functionOfInterest, curCodeLine);
                }
            };
            dte.Events.BuildEvents.OnBuildProjConfigDone += onProjBuildDone;
            dte.ExecuteCommand("Build.Compile");
        }
        // 1: show assembly code for currently open source file
        // 2: show preprocessed source code
        private void showCppOutput(int mode = 1)
        {
            // if in a header try to open the cpp file
            switchToCppFile();

            // get the currently active document from the IDE
            Document     doc  = dte.ActiveDocument;
            TextDocument tdoc = doc.Object("TextDocument") as TextDocument;

            if (tdoc == null)
            {
                package.showMsgBox("Could not obtain the active TextDocument object");
                return;
            }

            // get currently viewed function
            string        functionOfInterest = "";
            TextSelection selection          = tdoc.Selection;
            CodeElement   codeEl             = selection.ActivePoint.CodeElement[vsCMElement.vsCMElementFunction];

            if (codeEl == null)
            {
                dte.StatusBar.Text = "You should place the cursor inside a function.";
                dte.StatusBar.Highlight(true);
            }
            else
            {
                functionOfInterest = codeEl.FullName;
            }
            // TODO: in case of a template this gets something like funcName<T>, the assembly contains funcName<actualType>
            //       it doesn't in the case of macros either, e.g. gets _tmain but in the asm it will be wmain

            // http://www.viva64.com/en/a/0082/#ID0ELOBK
            // EditPoint directly manipulates text buffer data instead of operating with the text through the editor UI.
            int       line        = selection.ActivePoint.Line;
            EditPoint editPoint   = tdoc.CreateEditPoint();
            string    curCodeLine = editPoint.GetLines(line, line + 1);
            // TODO: comments are removed when preprocessing and thus can't find a line with comments

            // get current configuration
            Project proj             = doc.ProjectItem.ContainingProject;
            ConfigurationManager mgr = proj.ConfigurationManager;
            string platform          = mgr.ActiveConfiguration.PlatformName;
            string conf = mgr.ActiveConfiguration.ConfigurationName;

            // find the currently active configuration for the current file
            // don't use SolutionBuild as there may be mixed platforms
            // use late binding for version independence
            dynamic file        = doc.ProjectItem.Object;                             // as VCFile
            dynamic fileconfigs = file.FileConfigurations;                            // as IVCCollection
            dynamic fileconfig  = fileconfigs.Item(conf + "|" + platform);            // as VCFileConfiguration
            dynamic tool        = fileconfig.Tool;                                    // VCCLCompilerTool


            // save original settings to restore them later

            // there seems to be no better way
            // DTE undo contexts doesn't cover these project settings
            // unload/reload the project may close all open files
            // manipulating proj.Saved or .IsDirty does not work
            bool    lto             = tool.WholeProgramOptimization;
            dynamic asmtype         = tool.AssemblerOutput;
            dynamic genPreprocessed = tool.GeneratePreprocessedFile;
            string  asmloc          = tool.AssemblerListingLocation;
            string  objFileLocation = tool.ObjectFile;

            string generatedFile;

            if (mode == 1)
            {
                // asmListingAsmSrc => '.asm'
                generatedFile = Path.GetTempFileName() + ".asm";                 //System.IO.Path.GetTempPath

                tool.WholeProgramOptimization = false;
                tool.AssemblerOutput          = (dynamic)Enum.Parse(tool.AssemblerOutput.GetType(), "asmListingAsmSrc");
                tool.AssemblerListingLocation = generatedFile;
            }
            else             /*if (mode == 2)*/
            {
                // not generally applicable
                //generatedFile = prj.ProjectDirectory + prjconfig.IntermediateDirectory + Replace(file.Name, ".cpp", ".i");
                generatedFile = Path.GetTempFileName() + ".cpp";

                tool.GeneratePreprocessedFile = (dynamic)Enum.Parse(tool.GeneratePreprocessedFile.GetType(), "preprocessYes");
                // there's no separate option for this, so misuse /Fo
                tool.ObjectFile = generatedFile;
            }

            try
            {
                // forceBuild (even if up-to-date) and waitOnBuild
                fileconfig.Compile(true, true);
            }
            catch (Exception e)
            {
                package.writeStatus($"VCFileConfiguration.Compile() failed: {e.Message}. Trying command Build.Compile now...");

                _dispBuildEvents_OnBuildProjConfigDoneEventHandler onProjBuildDone = null;
                onProjBuildDone = (project, projectConfig, platfrm, solutionConfig, success) =>
                {
                    dte.Events.BuildEvents.OnBuildProjConfigDone -= onProjBuildDone;
                    // naive cleanup
                    if (mode == 1)
                    {
                        tool.WholeProgramOptimization = lto;
                        tool.AssemblerOutput          = asmtype;
                        tool.AssemblerListingLocation = asmloc;
                    }
                    else if (mode == 2)
                    {
                        tool.GeneratePreprocessedFile = genPreprocessed;
                        tool.ObjectFile = objFileLocation;
                    }

                    if (success)
                    {
                        postCompileCpp(generatedFile, mode, functionOfInterest, curCodeLine);
                    }
                };
                dte.Events.BuildEvents.OnBuildProjConfigDone += onProjBuildDone;
                dte.ExecuteCommand("Build.Compile");
                return;
            }

            // naive cleanup
            if (mode == 1)
            {
                tool.WholeProgramOptimization = lto;
                tool.AssemblerOutput          = asmtype;
                tool.AssemblerListingLocation = asmloc;
            }
            else if (mode == 2)
            {
                tool.GeneratePreprocessedFile = genPreprocessed;
                tool.ObjectFile = objFileLocation;
            }

            postCompileCpp(generatedFile, mode, functionOfInterest, curCodeLine);
        }