⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compilergcc.cpp

📁 非常好用的可移植的多平台C/C++源代码编辑器
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        return;

	if (!CheckProject())
		return;

    FileType ft = FileTypeOf(arg);

    if (arg.IsEmpty())
    {
        // popup menu in empty space in ProjectManager
        menu->Append(idMenuCompileAll, _("Build all projects"));
        menu->Append(idMenuRebuildAll, _("Rebuild all projects"));
    }
    else
    {
        // see if the arg is a project name
        bool found = false;
        ProjectsArray* array = Manager::Get()->GetProjectManager()->GetProjects();
        if (array)
        {
            for (size_t i = 0; i < array->GetCount(); ++i)
            {
                cbProject* cur = array->Item(i);
                if (cur && cur->GetTitle() == arg)
                {
                    found = true;
                    break;
                }
            }
        }

        if (found)
        {
            // popup menu on a project
            menu->AppendSeparator();
            menu->Append(idMenuCompileFromProjectManager, _("Build\tCtrl-F9"));
            menu->Append(idMenuRebuildFromProjectManager, _("Rebuild\tCtrl-F11"));
            menu->Append(idMenuCleanFromProjectManager, _("Clean"));
            menu->Append(idMenuDistCleanFromProjectManager, _("Dist-clean"));
            wxMenu* subMenu = new wxMenu();
            subMenu->Append(idMenuCompileTargetFromProjectManager, _("Build"));
            subMenu->Append(idMenuRebuildTargetFromProjectManager, _("Rebuild"));
            subMenu->Append(idMenuCleanTargetFromProjectManager, _("Clean"));
            subMenu->Append(idMenuDistCleanTargetFromProjectManager, _("Dist-clean"));
            subMenu->AppendSeparator();
            subMenu->Append(idMenuTargetCompilerOptions, _("Build options"));
            menu->Append(idMenuTargetCompilerOptionsSub, _("Specific build target..."), subMenu);
            menu->AppendSeparator();
            menu->Append(idMenuProjectCompilerOptions, _("Build options"));
        }
        else if (ft == ftSource || ft == ftHeader)
        {
            // popup menu on a compilable file
            menu->AppendSeparator();
            menu->Append(idMenuCompileFileFromProjectManager, _("Compile file"));
        }
    }
}

bool CompilerGCC::BuildToolBar(wxToolBar* toolBar)
{
	if (!m_IsAttached || !toolBar)
		return false;
    m_pTbar = toolBar;
    wxString my_16x16=Manager::isToolBar16x16(toolBar) ? _T("_16x16") : _T("");
    Manager::Get()->AddonToolBar(toolBar,_T("compiler_toolbar")+my_16x16);

    // neither the generic nor Motif native toolbars really support this
    #if (wxUSE_TOOLBAR_NATIVE && !USE_GENERIC_TBAR) && !defined(__WXMOTIF__) && !defined(__WXX11__) && !defined(__WXMAC__)
    m_ToolTarget = XRCCTRL(*toolBar, "idToolTarget", wxComboBox);
    #endif
    toolBar->Realize();
    DoRecreateTargetMenu(); // make sure the tool target combo is up-to-date
    return true;
}

void CompilerGCC::SetupEnvironment()
{
    if (!CompilerFactory::CompilerIndexOK(m_CompilerIdx))
        return;

    m_EnvironmentMsg.Clear();

	wxString path;
	Manager::Get()->GetMessageManager()->DebugLog(_("Setting up compiler environment..."));

    // reset PATH to original value
    if (!m_OriginalPath.IsEmpty())
        wxSetEnv(_T("PATH"), m_OriginalPath);

    // look for valid compiler in path
	if (wxGetEnv(_T("PATH"), &path))
	{
        if (m_OriginalPath.IsEmpty())
            m_OriginalPath = path;

        wxArrayInt compilers;
        if(m_Project)
        {
            for (int x = 0; x < m_Project->GetBuildTargetsCount(); ++x)
            {
                ProjectBuildTarget* target = m_Project->GetBuildTarget(x);
                int idx = target->GetCompilerIndex();

                // one time per compiler
                if (compilers.Index(idx) != wxNOT_FOUND || !CompilerFactory::CompilerIndexOK(idx))
                    continue;
                compilers.Add(idx);
                SetEnvironmentForCompilerIndex(idx, path);
            }
        }
        else
            SetEnvironmentForCompilerIndex(CompilerFactory::GetDefaultCompilerIndex(), path);
	}
	else
		m_EnvironmentMsg = _("Could not read the PATH environment variable!\n"
					"This can't be good. There may be problems running "
					"system commands and the application might not behave "
					"the way it was designed to...");
//    wxGetEnv("PATH", &path);
//    Manager::Get()->GetMessageManager()->Log(m_PageIndex, "PATH set to: %s", path.c_str());
}

void CompilerGCC::SetEnvironmentForCompilerIndex(int idx, wxString& envPath)
{
    if (!CompilerFactory::CompilerIndexOK(idx))
        return;

    Compiler* compiler = CompilerFactory::Compilers[idx];
    wxString sep = wxFileName::GetPathSeparator();

    wxString masterPath = compiler->GetMasterPath();
    while (masterPath.Last() == '\\' || masterPath.Last() == '/')
        masterPath.RemoveLast();
    wxString gcc = compiler->GetPrograms().C;
    const wxArrayString& extraPaths = compiler->GetExtraPaths();

    wxPathList pathList;
    pathList.Add(masterPath + sep + _T("bin"));
    for (unsigned int i = 0; i < extraPaths.GetCount(); ++i)
    {
        if (!extraPaths[i].IsEmpty())
            pathList.Add(extraPaths[i]);
    }
    pathList.AddEnvList(_T("PATH"));
    wxString binPath = pathList.FindAbsoluteValidPath(gcc);
    // it seems, under Win32, the above command doesn't search in paths with spaces...
    // look directly for the file in question in masterPath
    if (binPath.IsEmpty() || !pathList.Member(wxPathOnly(binPath)))
    {
        if (wxFileExists(masterPath + sep + _T("bin") + sep + gcc))
            binPath = masterPath + sep + _T("bin");
        else if (wxFileExists(masterPath + sep + gcc))
            binPath = masterPath;
        else
        {
            for (unsigned int i = 0; i < extraPaths.GetCount(); ++i)
            {
                if (!extraPaths[i].IsEmpty())
                {
                    if (wxFileExists(extraPaths[i] + sep + gcc))
                    {
                        binPath = extraPaths[i];
                        break;
                    }
                }
            }
        }
    }

    if (binPath.IsEmpty() || !pathList.Member(wxPathOnly(binPath)))
    {
        m_EnvironmentMsg << _("Can't find compiler executable in your search path for ") << compiler->GetName() << _T('\n');
        Manager::Get()->GetMessageManager()->DebugLog(_("Can't find compiler executable in your search path (%s)..."), compiler->GetName().c_str());
    }
    else
    {
        m_EnvironmentMsg.Clear();
#ifdef __WXMSW__
#define PATH_SEP _T(";")
#else
#define PATH_SEP _T(":")
#endif
        // add extra compiler paths in PATH
        wxString oldpath = envPath;
        envPath.Clear();
        for (unsigned int i = 0; i < extraPaths.GetCount(); ++i)
        {
            if (!extraPaths[i].IsEmpty())
            {
                envPath += extraPaths[i] + PATH_SEP;
            }
        }
        envPath = envPath + oldpath;

        // add bin path to PATH env. var.
        if (wxFileExists(masterPath + sep + _T("bin") + sep + gcc))
            envPath = masterPath + sep + _T("bin") + PATH_SEP + envPath;
        else if (wxFileExists(masterPath + sep + gcc))
            envPath = masterPath + PATH_SEP + envPath;
        wxSetEnv(_T("PATH"), envPath);
#undef PATH_SEP
    }
}

void CompilerGCC::SaveOptions()
{
	// save compiler sets
    CompilerFactory::SaveSettings();
}

void CompilerGCC::LoadOptions()
{
    // load compiler sets
    CompilerFactory::LoadSettings();
}

int CompilerGCC::GetCurrentCompilerIndex()
{
    return CompilerFactory::CompilerIndexOK(m_CompilerIdx) ? m_CompilerIdx : 0;
}

void CompilerGCC::SwitchCompiler(int compilerIdx)
{
    if (!CompilerFactory::CompilerIndexOK(compilerIdx))
        return;
    m_CompilerIdx = compilerIdx;
    SetupEnvironment();
}

void CompilerGCC::AskForActiveProject()
{
    m_Project = Manager::Get()->GetProjectManager()->GetActiveProject();
}

bool CompilerGCC::CheckProject()
{
    AskForActiveProject();
    if (m_Project && m_Project->GetCompilerIndex() != m_CompilerIdx)
        SwitchCompiler(m_Project->GetCompilerIndex());
    return m_Project;
}

wxString CompilerGCC::ProjectMakefile()
{
    AskForActiveProject();
    if (!m_Project)
        return wxEmptyString;

    return m_Project->GetMakefile();
}

void CompilerGCC::ClearLog()
{
    if (m_Log)
        m_Log->GetTextControl()->Clear();
}

FileTreeData* CompilerGCC::DoSwitchProjectTemporarily()
{
	wxTreeCtrl* tree = Manager::Get()->GetProjectManager()->GetTree();
	wxTreeItemId sel = tree->GetSelection();
    FileTreeData* ftd = (FileTreeData*)tree->GetItemData(sel);
    if (!ftd)
        return 0L;
    // copy ftd to a new instance, because after the SetProject() call
    // that follows, ftd will no longer be valid...
    FileTreeData* newFtd = new FileTreeData(ftd->GetProject(), ftd->GetFileIndex());
    Manager::Get()->GetProjectManager()->SetProject(ftd->GetProject(), false);
    AskForActiveProject();

    return newFtd;
}

int CompilerGCC::DoRunQueue()
{
    wxLogNull ln;

	// leave if already running
	if (m_Process)
		return -2;

    MessageManager* msgMan = Manager::Get()->GetMessageManager();
    msgMan->SwitchTo(m_PageIndex);

	// leave if no active project
    AskForActiveProject();

    // make sure all project files are saved
    if (m_Project && !m_Project->SaveAllFiles())
        msgMan->Log(_("Could not save all files..."));

    if (m_Queue.GetCount() == 0)
	{
        m_Log->GetTextControl()->SetDefaultStyle(wxTextAttr(*wxBLUE, wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
        msgMan->Log(m_PageIndex, _("Nothing to be done."));
        m_Log->GetTextControl()->SetDefaultStyle(wxTextAttr(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
        m_LastExitCode = 0;
        OnJobEnd();
        return 0;
	}

	// leave if no commands in queue
    if (m_QueueIndex >= m_Queue.GetCount())
	{
        msgMan->DebugLog(_("Queue has been emptied! (count=%d, index=%d)"), m_Queue.GetCount(), m_QueueIndex);
        return -3;
	}

	m_Log->GetTextControl()->SetDefaultStyle(wxTextAttr(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
    wxString dir;// = m_Project->GetBasePath();
    wxString cmd;

    // loop added for compiler log when not working with Makefiles
    wxString mySimpleLog = wxString(COMPILER_SIMPLE_LOG);
    wxString myTargetChange = wxString(COMPILER_TARGET_CHANGE);
    while (true)
    {
        cmd = m_Queue[m_QueueIndex];
//	    msgMan->Log(m_PageIndex, "cmd='%s' in '%s'", cmd.c_str(), m_CdRun.c_str());

        // logging
        if (cmd.StartsWith(mySimpleLog))
        {
            cmd.Remove(0, mySimpleLog.Length());
            msgMan->Log(m_PageIndex, cmd);
        }
        // compiler change
        else if (cmd.StartsWith(myTargetChange))
        {
            cmd.Remove(0, myTargetChange.Length());
            // using other compiler now: find it and set it
            ProjectBuildTarget* bt = m_Project->GetBuildTarget(cmd);
            if (bt)
            {
                SwitchCompiler(bt->GetCompilerIndex());
                // re-apply the env vars for this target
                if (CompilerFactory::CompilerIndexOK(m_CompilerIdx))
                    CompilerFactory::Compilers[m_CompilerIdx]->GetCustomVars().ApplyVarsToEnvironment();
                m_Project->GetCustomVars().ApplyVarsToEnvironment();
                bt->GetCustomVars().ApplyVarsToEnvironment();
            }
            else
                msgMan->Log(m_PageIndex, _("Can't locate target '%s'!"), cmd.c_str());
        }
        else
        {
        	// compile command; apply custom vars
        	Manager::Get()->GetMacrosManager()->ReplaceEnvVars(cmd);
            break;
        }

        ++m_QueueIndex;
        if (m_QueueIndex >= m_Queue.GetCount())
        {
            msgMan->Log(m_PageIndex, _("Nothing to be done."));
            m_LastExitCode = 0;
            OnJobEnd();
            return 0;
        }
    }

    // if message manager is auto-hiding, this will lock it open
    Manager::Get()->GetMessageManager()->LockOpen();

	bool pipe = true;
	int flags = wxEXEC_ASYNC;
	if (m_RunAfterCompile && m_IsRun && m_QueueIndex == m_Queue.GetCount() - 1)
	{
		pipe = false; // no need to pipe output channels...
		flags |= wxEXEC_NOHIDE;
		m_IsRun = false;
		dir = m_CdRun;
#ifndef __WXMSW__
		wxSetEnv(_T("LD_LIBRARY_PATH"), _T("."));
#endif
	}

    m_Process = new PipedProcess((void**)&m_Process, this, idGCCProcess, pipe, dir);
    m_Pid = wxExecute(cmd, flags, m_Process);
    if ( !m_Pid )
    {
        m_Log->GetTextControl()->SetDefaultStyle(wxTextAttr(*wxRED, *wxWHITE));
        msgMan->Log(m_PageIndex, _("Execution of '%s' in '%s' failed."), m_Queue[m_QueueIndex].c_str(), wxGetCwd().c_str());
		m_Log->GetTextControl()->SetDefaultStyle(wxTextAttr(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT), wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)));
        delete m_Process;
        m_Process = NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -