Beispiel #1
0
void CallGraph::OnShowCallGraph(wxCommandEvent& event)
{
    // myLog("wxThread::IsMain(%d)", (int)wxThread::IsMain());

    IConfigTool *config_tool = m_mgr->GetConfigTool();

    config_tool->ReadObject(wxT("CallGraph"), &confData);

    if (!wxFileExists(GetGprofPath()) || !wxFileExists(GetDotPath()))
        return MessageBox(_T("Failed to locate required tools (gprof, dot). Please check the plugin settings."), wxICON_ERROR);

    Workspace   *ws = m_mgr->GetWorkspace();
    if (!ws)		return MessageBox(_("Unable to get opened workspace."), wxICON_ERROR);

    wxFileName  ws_cfn = ws->GetWorkspaceFileName();

    wxString projectName = ws->GetActiveProjectName();

    BuildMatrixPtr	  mtx = ws->GetBuildMatrix();
    if (!mtx)	   return MessageBox(_("Unable to get current build matrix."), wxICON_ERROR);

    wxString	build_config_name = mtx->GetSelectedConfigurationName();

    BuildConfigPtr	  bldConf = ws->GetProjBuildConf(projectName, build_config_name);
    if (!bldConf)   return MessageBox(_("Unable to get opened workspace."), wxICON_ERROR);

    wxString	projOutputFn = bldConf->GetOutputFileName();
    wxString	projWorkingDir = bldConf->GetWorkingDirectory();

    /*
    myLog("WorkspaceFileName = \"%s\"", ws_cfn.GetFullPath());
    myLog("projectName \"%s\"", projectName);
    myLog("build_config_name = \"%s\"", build_config_name);
    myLog("projOutputFn = \"%s\"", projOutputFn);
    myLog("projWorkingDir = \"%s\"", projWorkingDir);
    */

    wxFileName  cfn(ws_cfn.GetPath(), projOutputFn);
    cfn.Normalize();

    // base path
    const wxString	base_path = ws_cfn.GetPath();

    // check source binary exists
    wxString	bin_fpath = cfn.GetFullPath();
    if (!cfn.Exists()) {
        bin_fpath = wxFileSelector("Please select the binary to analyze", base_path, "", "");
        if (bin_fpath.IsEmpty())		return MessageBox("selected binary was canceled", wxICON_ERROR);

        cfn.Assign(bin_fpath, wxPATH_NATIVE);
    }
    if (!cfn.IsFileExecutable())		return MessageBox("bin/exe isn't executable", wxICON_ERROR);

    // check 'gmon.out' file exists
    wxFileName  gmon_cfn(base_path, GMON_FILENAME_OUT);
    if (!gmon_cfn.Exists())
        gmon_cfn.Normalize();

    wxString	gmonfn = gmon_cfn.GetFullPath();
    if (!gmon_cfn.Exists()) {
        gmonfn = wxFileSelector("Please select the gprof file", gmon_cfn.GetPath(), "gmon", "out");
        if (gmonfn.IsEmpty())		return MessageBox("selected gprof was canceled", wxICON_ERROR);

        gmon_cfn.Assign(gmonfn, wxPATH_NATIVE);
    }

    wxString	bin, arg1, arg2;

    bin = GetGprofPath();
    arg1 = bin_fpath;
    arg2 = gmonfn;

    wxString cmdgprof = wxString::Format("%s %s %s", bin, arg1, arg2);

    // myLog("about to wxExecute(\"%s\")", cmdgprof);

    wxProcess	*proc = new wxProcess(wxPROCESS_REDIRECT);

    // wxStopWatch	sw;

    const int	err = ::wxExecute(cmdgprof, wxEXEC_SYNC, proc);
    // on sync returns 0 (success), -1 (failure / "couldn't be started")

    // myLog("wxExecute() returned err %d, had pid %d", err, (int)proc->GetPid());

    wxInputStream	   *process_is = proc->GetInputStream();
    if (!process_is || !process_is->CanRead())
        return MessageBox(_("wxProcess::GetInputStream() can't be opened, aborting"), wxICON_ERROR);

    // start parsing and writing to dot language file
    GprofParser pgp;

    pgp.GprofParserStream(process_is);

    // myLog("gprof done (read %d lines)", (int) pgp.lines.GetCount());

    delete proc;

    ConfCallGraph conf;

    config_tool->ReadObject(wxT("CallGraph"), &conf);

    DotWriter dotWriter;

    // DotWriter
    dotWriter.SetLineParser(&(pgp.lines));

    int suggestedThreshold = pgp.GetSuggestedNodeThreshold();

    if (suggestedThreshold <= conf.GetTresholdNode()) {
        suggestedThreshold = conf.GetTresholdNode();

        dotWriter.SetDotWriterFromDialogSettings(m_mgr);

    } else {
        dotWriter.SetDotWriterFromDetails(conf.GetColorsNode(),
                                          conf.GetColorsEdge(),
                                          suggestedThreshold,
                                          conf.GetTresholdEdge(),
                                          conf.GetHideParams(),
                                          conf.GetStripParams(),
                                          conf.GetHideNamespaces());

        wxString	suggest_msg = wxString::Format(_("The CallGraph plugin has suggested node threshold %d to speed-up the call graph creation. You can alter it on the call graph panel."), suggestedThreshold);

        MessageBox(suggest_msg, wxICON_INFORMATION);
    }

    dotWriter.WriteToDotLanguage();

    // build output dir
    cfn.Assign(base_path, "");
    cfn.AppendDir(CALLGRAPH_DIR);
    cfn.Normalize();

    if (!cfn.DirExists())	   cfn.Mkdir(wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);

    cfn.SetFullName(DOT_FILENAME_TXT);
    wxString dot_fn = cfn.GetFullPath();

    dotWriter.SendToDotAppOutputDirectory(dot_fn);

    cfn.SetFullName(DOT_FILENAME_PNG);
    wxString output_png_fn = cfn.GetFullPath();

    // delete any existing PNG
    if (wxFileExists(output_png_fn))	wxRemoveFile(output_png_fn);

    wxString cmddot_ln;

    cmddot_ln << GetDotPath() << " -Tpng -o" << output_png_fn << " " << dot_fn;

    // myLog("wxExecute(\"%s\")", cmddot_ln);

    wxExecute(cmddot_ln, wxEXEC_SYNC);

    // myLog("dot done");

    if (!wxFileExists(output_png_fn))
        return MessageBox(_("Failed to open file CallGraph.png. Please check the project settings, rebuild the project and try again."), wxICON_INFORMATION);

    // show image and create table in the editor tab page
    uicallgraphpanel	*panel = new uicallgraphpanel(m_mgr->GetEditorPaneNotebook(), m_mgr, output_png_fn, base_path, suggestedThreshold, &(pgp.lines));

    wxString	tstamp = wxDateTime::Now().Format(wxT(" %Y-%m-%d %H:%M:%S"));

    wxString	  title = wxT("Call graph for \"") + output_png_fn + wxT("\" " + tstamp);

    m_mgr->AddEditorPage(panel, title);
}