Beispiel #1
0
//------------------------------------------------------------------------------
wxString WizCompilerPanel::GetCompilerID() const
{
    Compiler* compiler = CompilerFactory::GetCompilerByName(m_pCompilerPanel->GetCompilerCombo()->GetStringSelection());
    if (compiler)
        return compiler->GetID();
    return wxEmptyString;
}
Beispiel #2
0
Compiler* CompilerFactory::CreateCompilerCopy(Compiler* compiler, const wxString& newName)
{
    if (!compiler)
        return nullptr;

    // abort if an existing compiler with the same name exists
    // this also avoids the possibility of throwing an exception
    // in the compiler->CreateCopy() call below...
    for (size_t i = 0; i < Compilers.GetCount(); ++i)
    {
        if (Compilers[i]->GetName() == newName)
            return nullptr;
    }

    Compiler* newC = compiler->CreateCopy();
    if (!newName.IsEmpty())
    {
        Compiler::m_CompilerIDs.Remove(newC->GetID());
        newC->SetName(newName);
        newC->m_ID = newName;
        newC->MakeValidID();
    }
    newC->ReloadOptions();
    RegisterCompiler(newC);
    newC->LoadSettings(_T("/user_sets"));
    Manager::Get()->GetLogManager()->DebugLog(F(_T("Added compiler \"%s\""), newC->GetName().wx_str()));
    return newC; // return the index for the new compiler
}
Beispiel #3
0
//------------------------------------------------------------------------------
wxString WizBuildTargetPanel::GetCompilerID() const
{
    if (!m_pBuildTargetPanel->GetCompilerCombo()->IsShown())
        return wxEmptyString;

    Compiler* compiler = CompilerFactory::GetCompilerByName(m_pBuildTargetPanel->GetCompilerCombo()->GetStringSelection());
    if (compiler)
        return compiler->GetID();
    return wxEmptyString;
}
Beispiel #4
0
WizBuildTargetPanel::WizBuildTargetPanel(const wxString& targetName, bool isDebug,
                                    wxWizard* parent, const wxBitmap& bitmap,
                                    bool showCompiler,
                                    const wxString& compilerID, const wxString& validCompilerIDs,
                                    bool allowCompilerChange)
    : WizPageBase(_T("BuildTargetPage"), parent, bitmap)
{
    m_pBuildTargetPanel = new BuildTargetPanel(this);
    m_pBuildTargetPanel->SetTargetName(targetName);
    m_pBuildTargetPanel->SetEnableDebug(isDebug);
    m_pBuildTargetPanel->ShowCompiler(showCompiler);

    if (showCompiler)
    {
        wxArrayString valids = GetArrayFromString(validCompilerIDs, _T(";"), true);
        wxString def = compilerID;
        if (def.IsEmpty())
            def = CompilerFactory::GetDefaultCompiler()->GetName();
        int id = 0;
        wxComboBox* cmb = m_pBuildTargetPanel->GetCompilerCombo();
        cmb->Clear();
        for (size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i)
        {
            for (size_t n = 0; n < valids.GetCount(); ++n)
            {
                Compiler* compiler = CompilerFactory::GetCompiler(i);
                if (compiler)
                {
                    if (compiler->GetID().Matches(valids[n]))
                    {
                        cmb->Append(compiler->GetName());
                        if (compiler->GetID().IsSameAs(def))
                            id = cmb->GetCount();
                        break;
                    }
                }
            }
        }
        cmb->SetSelection(id);
        cmb->Enable(allowCompilerChange);
    }
}
Beispiel #5
0
WizCompilerPanel::WizCompilerPanel(const wxString& compilerID, const wxString& validCompilerIDs, wxWizard* parent, const wxBitmap& bitmap,
                                    bool allowCompilerChange, bool allowConfigChange)
    : WizPageBase(_T("CompilerPage"), parent, bitmap),
    m_AllowConfigChange(allowConfigChange)
{
    m_pCompilerPanel = new CompilerPanel(this, GetParent());

    wxArrayString valids = GetArrayFromString(validCompilerIDs, _T(";"), true);
    wxString def = compilerID;
    if (def.IsEmpty())
        def = CompilerFactory::GetDefaultCompilerID();
    int id = 0;
    wxComboBox* cmb = m_pCompilerPanel->GetCompilerCombo();
    cmb->Clear();
    for (size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i)
    {
        Compiler* compiler = CompilerFactory::GetCompiler(i);
        if (compiler)
        {
            for (size_t n = 0; n < valids.GetCount(); ++n)
            {
                // match not only if IDs match, but if ID inherits from it too
                if (CompilerFactory::CompilerInheritsFrom(compiler, valids[n]))
                {
                    cmb->Append(compiler->GetName());
                    if (compiler->GetID().IsSameAs(def))
                        id = (cmb->GetCount() - 1) < 0 ? 0 : (cmb->GetCount() - 1);
                    break;
                }
            }
        }
    }
    cmb->SetSelection(id);
    cmb->Enable(allowCompilerChange);
    m_pCompilerPanel->EnableConfigurationTargets(m_AllowConfigChange);

    ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("scripts"));

    m_pCompilerPanel->SetWantDebug(cfg->ReadBool(_T("/generic_wizard/want_debug"), true));
    m_pCompilerPanel->SetDebugName(cfg->Read(_T("/generic_wizard/debug_name"), _T("Debug")));
    m_pCompilerPanel->SetDebugOutputDir(cfg->Read(_T("/generic_wizard/debug_output"), _T("bin") + wxString(wxFILE_SEP_PATH) + _T("Debug")));
    m_pCompilerPanel->SetDebugObjectOutputDir(cfg->Read(_T("/generic_wizard/debug_objects_output"), _T("obj") + wxString(wxFILE_SEP_PATH) + _T("Debug")));

    m_pCompilerPanel->SetWantRelease(cfg->ReadBool(_T("/generic_wizard/want_release"), true));
    m_pCompilerPanel->SetReleaseName(cfg->Read(_T("/generic_wizard/release_name"), _T("Release")));
    m_pCompilerPanel->SetReleaseOutputDir(cfg->Read(_T("/generic_wizard/release_output"), _T("bin") + wxString(wxFILE_SEP_PATH) + _T("Release")));
    m_pCompilerPanel->SetReleaseObjectOutputDir(cfg->Read(_T("/generic_wizard/release_objects_output"), _T("obj") + wxString(wxFILE_SEP_PATH) + _T("Release")));
}
Beispiel #6
0
// Don't call this function from within the scope of:
//      ClangPlugin::OnEditorHook
//      ClangPlugin::OnTimer
int ClangPlugin::UpdateCompileCommand(cbEditor* ed)
{
    wxString compileCommand;
    ProjectFile* pf = ed->GetProjectFile();

    m_UpdateCompileCommand++;
    if ( m_UpdateCompileCommand > 1 )
    {
        // Re-entry is not allowed
        m_UpdateCompileCommand--;
        return 0;
    }

    ProjectBuildTarget* target = nullptr;
    Compiler* comp = nullptr;
    if (pf && pf->GetParentProject() && !pf->GetBuildTargets().IsEmpty())
    {
        target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);
        comp = CompilerFactory::GetCompiler(target->GetCompilerID());
    }
    cbProject* proj = (pf ? pf->GetParentProject() : nullptr);
    if ( (!comp) && proj)
        comp = CompilerFactory::GetCompiler(proj->GetCompilerID());
    if (!comp)
    {
        cbProject* tmpPrj = Manager::Get()->GetProjectManager()->GetActiveProject();
        if (tmpPrj)
            comp = CompilerFactory::GetCompiler(tmpPrj->GetCompilerID());
    }
    if (!comp)
        comp = CompilerFactory::GetDefaultCompiler();

    if (pf && (!pf->GetBuildTargets().IsEmpty()) )
    {
        target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);

        if (pf->GetUseCustomBuildCommand(target->GetCompilerID() ))
            compileCommand = pf->GetCustomBuildCommand(target->GetCompilerID()).AfterFirst(wxT(' '));

    }

    if (compileCommand.IsEmpty())
        compileCommand = wxT("$options $includes");
    CompilerCommandGenerator* gen = comp->GetCommandGenerator(proj);
    if (gen)
        gen->GenerateCommandLine(compileCommand, target, pf, ed->GetFilename(),
                g_InvalidStr, g_InvalidStr, g_InvalidStr );
    delete gen;

    wxStringTokenizer tokenizer(compileCommand);
    compileCommand.Empty();
    wxString pathStr;
    while (tokenizer.HasMoreTokens())
    {
        wxString flag = tokenizer.GetNextToken();
        // make all include paths absolute, so clang does not choke if Code::Blocks switches directories
        if (flag.StartsWith(wxT("-I"), &pathStr))
        {
            wxFileName path(pathStr);
            if (path.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE))
                flag = wxT("-I") + path.GetFullPath();
        }
        compileCommand += flag + wxT(" ");
    }
    compileCommand += GetCompilerInclDirs(comp->GetID());

    m_UpdateCompileCommand--;

    if (compileCommand != m_CompileCommand)
    {
        m_CompileCommand = compileCommand;
        return 1;
    }
    return 0;
}
AutoDetectCompilers::AutoDetectCompilers(wxWindow* parent)
{
    //ctor
    wxXmlResource::Get()->LoadObject(this, parent, _T("dlgAutoDetectCompilers"),_T("wxScrollingDialog"));

    wxListCtrl* list = XRCCTRL(*this, "lcCompilers", wxListCtrl);
    if (list)
    {
        list->Connect(wxEVT_MOTION, wxMouseEventHandler(AutoDetectCompilers::OnMouseMotion));
        list->ClearAll();
        list->InsertColumn(0, _("Compiler"), wxLIST_FORMAT_LEFT, 380);
        list->InsertColumn(1, _("Status"),   wxLIST_FORMAT_LEFT, 100);

        for (size_t i = 0; i < CompilerFactory::GetCompilersCount(); ++i)
        {
            Compiler* compiler = CompilerFactory::GetCompiler(i);
            if (!compiler)
                continue;

            list->InsertItem(list->GetItemCount(), compiler->GetName());

            wxString path = compiler->GetMasterPath();
            wxString path_no_macros = compiler->GetMasterPath();
            Manager::Get()->GetMacrosManager()->ReplaceMacros(path_no_macros);

            int idx = list->GetItemCount() - 1;
            int highlight = 0;
            if (path.IsEmpty() && Manager::Get()->GetConfigManager(wxT("compiler"))->Exists(wxT("/sets/") + compiler->GetID() + wxT("/name")))
            {
                // Here, some user-interaction is required not to show this
                // dialog again on each new start-up of C::B.
                list->SetItem(idx, 1, _("Invalid"));
                // So we better clearly HIGHLIGHT this entry:
                highlight = 1;
            }
            else // The compiler is *probably* invalid, but at least a master-path is set
            {
                list->SetItem(idx, 1, _("Not found"));
                highlight = -1;
            }

            // Inspect deeper and probably try to auto-detect invalid compilers:
            if (compiler->GetParentID().IsEmpty()) // built-in compiler
            {
                // Try auto-detection (which is for built-in compilers only)
                bool detected = compiler->AutoDetectInstallationDir() == adrDetected;
                wxString pathDetected( compiler->GetMasterPath() );

                // In case auto-detection was successful:
                if (detected)
                {
                    // No path setup before OR path detected as it was setup before
                    if (path.IsEmpty() || path == pathDetected || path_no_macros == pathDetected)
                        list->SetItem(idx, 1, _("Detected")); // OK
                    else
                        list->SetItem(idx, 1, _("User-defined")); // OK
                    highlight = 0;
                }
                // In case auto-detection failed but a path was setup before:
                else if ( !path.IsEmpty() )
                {
                    // Check, if the master path is valid:
                    if ( wxFileName::DirExists(path_no_macros) && !(path == pathDetected || path_no_macros == pathDetected) )
                    {
                        list->SetItem(idx, 1, _("User-defined")); // OK
                        highlight = 0;
                    }

                    // Assume the user did the setup on purpose, so reset the old settings anyways:
                    compiler->SetMasterPath(path);
                }
            }
            else // no built-in, but user-defined (i.e. copied) compiler
            {
                // Check, if the master path is valid:
                if ( !path.IsEmpty() && wxFileName::DirExists(path_no_macros) )
                {
                    list->SetItem(idx, 1, _("User-defined")); // OK
                    highlight = 0;
                }
            }

            if (highlight == 1)
                list->SetItemBackgroundColour(idx, *wxRED);
            else if (highlight == -1)
                list->SetItemTextColour(idx, *wxLIGHT_GREY);
        }
        // Resize columns so one can read the whole stuff:
        list->SetColumnWidth(0, wxLIST_AUTOSIZE);
        list->SetColumnWidth(1, wxLIST_AUTOSIZE);
    }

    XRCCTRL(*this, "lblDefCompiler", wxStaticText)->SetLabel(CompilerFactory::GetDefaultCompiler()->GetName());
}
Beispiel #8
0
wxArrayString DirectCommands::GetCompileFileCommand(ProjectBuildTarget* target, ProjectFile* pf)
{
    wxArrayString ret;
    wxArrayString retGenerated;

    // is it compilable?
    if (!pf->compile || pf->compilerVar.IsEmpty())
        return ret;

    const pfDetails& pfd = pf->GetFileDetails(target);
    Compiler* compiler = target ? CompilerFactory::GetCompiler(target->GetCompilerID()) : m_pCompiler;
   // wxString Object = (compiler->GetSwitches().UseFlatObjects)?pfd.object_file_flat:pfd.object_file;
    wxString Object = (target->GetUseFlatObjects())?pfd.object_file_flat:pfd.object_file;



    // lookup file's type
    FileType ft = FileTypeOf(pf->relativeFilename);

    // create output dir
    if (!pfd.object_dir_native.IsEmpty() && !CreateDirRecursively(pfd.object_dir_native, 0755))
    {
        cbMessageBox(_("Can't create object output directory ") + pfd.object_dir_native);
    }

    bool isResource = ft == ftResource;
    bool isHeader = ft == ftHeader;



    // allowed resources under all platforms: makes sense when cross-compiling for
    // windows under linux.
    // and anyway, if the user is dumb enough to try to compile resources without
    // having a resource compiler, (s)he deserves the upcoming build error ;)

//#ifndef __WXMSW__
//    // not supported under non-win32 platforms
//    if (isResource)
//        return ret;
//#endif

    wxString compilerCmd,source_file,tempCompilerCmd(wxEmptyString);
    if (!isHeader || compiler->GetSwitches().supportsPCH)
    {
        const CompilerTool& tool = compiler->GetCompilerTool(isResource ? ctCompileResourceCmd : ctCompileObjectCmd, pf->file.GetExt());

        // does it generate other files to compile?
        for (size_t i = 0; i < pf->generatedFiles.size(); ++i)
        {
            AppendArray(GetCompileFileCommand(target, pf->generatedFiles[i]), retGenerated); // recurse
        }

        pfCustomBuild& pcfb = pf->customBuild[compiler->GetID()];
        compilerCmd = pcfb.useCustomBuildCommand
                        ? pcfb.buildCommand
                        : tool.command;

        if (target->GetUseFullSourcePaths())
        {
            source_file = UnixFilename(pfd.source_file_absolute_native);
            // for resource files, use short from if path because if windres bug with spaces-in-paths
            if (isResource)
                source_file = pf->file.GetShortPath();
        }
        else
            source_file = pfd.source_file;
        QuoteStringIfNeeded(source_file);
        compiler->GenerateCommandLine(compilerCmd,
                                         target,
                                         pf,
                                         source_file,
                                         Object,
                                         pfd.object_file_flat,
                                         pfd.dep_file);
    }



    if (!compilerCmd.IsEmpty()) // my lcy 1
    {
        switch (compiler->GetSwitches().logging)
        {
            case clogFull:
                ret.Add(wxString(COMPILER_SIMPLE_LOG) + compilerCmd);
                break;

            case clogSimple:
                if (isHeader)
                    ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Precompiling header: ") + pfd.source_file_native);
                else
                    ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Compiling: ") + pfd.source_file_native);
                break;

            default:
                break;
        }

        AddCommandsToArray(compilerCmd, ret);
        if(m_pCurrTarget->GetGenerateEachLit())
        AddCommandsToArray(GenerateLitForEachObj(Object,compiler->GetPrograms().OBJDUMP),ret);
        if (isHeader)
            ret.Add(wxString(COMPILER_WAIT));
        if (retGenerated.GetCount())
        {
            // not only append commands for (any) generated files to be compiled
            // but also insert a "pause" to allow this file to generate its files first
            if (!isHeader) // if isHeader, the "pause" has already been added
                ret.Add(wxString(COMPILER_WAIT));
            AppendArray(retGenerated, ret);
        }

        // if it's a PCH, delete the previously generated PCH to avoid problems
        // (it 'll be recreated anyway)
        if (FileTypeOf(pf->relativeFilename) == ftHeader && pf->compile)
        {
            wxString ObjectAbs = (m_pCurrTarget->GetUseFlatObjects())?pfd.object_file_flat_absolute_native:pfd.object_file_absolute_native;
            wxRemoveFile(ObjectAbs);
        }
    }
    else // lcy skip
    {

         ret.Add(wxString(COMPILER_SIMPLE_LOG) + _("Skipping file (no compiler program set): ") + pfd.source_file_native);
    }

    return ret;
}
wxArrayString DirectCommands::GetCompileFileCommand(ProjectBuildTarget* target, ProjectFile* pf) const
{
    wxArrayString ret;
    wxArrayString ret_generated;

    // is it compilable?
    if (!pf || !pf->compile)
        return ret;

    if (pf->compilerVar.IsEmpty())
    {
        Manager::Get()->GetLogManager()->DebugLog(_("Cannot resolve compiler var for project file."));
        return ret;
    }

    Compiler* compiler = target
                       ? CompilerFactory::GetCompiler(target->GetCompilerID())
                       : m_pCompiler;
    if (!compiler)
    {
        Manager::Get()->GetLogManager()->DebugLog(_("Can't access compiler for file."));
        return ret;
    }

    const pfDetails& pfd = pf->GetFileDetails(target);
    wxString object      = (compiler->GetSwitches().UseFlatObjects)
                         ? pfd.object_file_flat : pfd.object_file;
    wxString object_dir  = (compiler->GetSwitches().UseFlatObjects)
                         ? pfd.object_dir_flat_native : pfd.object_dir_native;
    // create output dir
    if (!object_dir.IsEmpty() && !CreateDirRecursively(object_dir, 0755))
        Manager::Get()->GetLogManager()->DebugLog(_("Can't create object output directory:\n") + object_dir);

    // lookup file's type
    const FileType ft = FileTypeOf(pf->relativeFilename);

    bool is_resource = ft == ftResource;
    bool is_header   = ft == ftHeader;

    // allowed resources under all platforms: makes sense when cross-compiling for
    // windows under linux.
    // and anyway, if the user is dumb enough to try to compile resources without
    // having a resource compiler, (s)he deserves the upcoming build error ;)

    wxString compiler_cmd;
    if (!is_header || compiler->GetSwitches().supportsPCH)
    {
        const CompilerTool* tool = compiler->GetCompilerTool(is_resource ? ctCompileResourceCmd : ctCompileObjectCmd, pf->file.GetExt());

        // does it generate other files to compile?
        for (size_t i = 0; i < pf->generatedFiles.size(); ++i)
            AppendArray(GetCompileFileCommand(target, pf->generatedFiles[i]), ret_generated); // recurse

        pfCustomBuild& pcfb = pf->customBuild[compiler->GetID()];
        if (pcfb.useCustomBuildCommand)
            compiler_cmd = pcfb.buildCommand;
        else if (tool)
            compiler_cmd = tool->command;
        else
            compiler_cmd = wxEmptyString;

        wxString source_file;
        if (compiler->GetSwitches().UseFullSourcePaths)
            source_file = UnixFilename(pfd.source_file_absolute_native);
        else
            source_file = pfd.source_file;

#ifdef command_line_generation
        Manager::Get()->GetLogManager()->DebugLog(F(_T("GetCompileFileCommand[1]: compiler_cmd='%s', source_file='%s', object='%s', object_dir='%s'."),
                                                    compiler_cmd.wx_str(), source_file.wx_str(), object.wx_str(), object_dir.wx_str()));
#endif

        // for resource files, use short from if path because if windres bug with spaces-in-paths
        if (is_resource && compiler->GetSwitches().UseFullSourcePaths)
            source_file = pf->file.GetShortPath();

        QuoteStringIfNeeded(source_file);

#ifdef command_line_generation
        Manager::Get()->GetLogManager()->DebugLog(F(_T("GetCompileFileCommand[2]: source_file='%s'."),
                                                    source_file.wx_str()));
#endif

        m_pGenerator->GenerateCommandLine(compiler_cmd,
                                          target,
                                          pf,
                                          source_file,
                                          object,
                                          pfd.object_file_flat,
                                          pfd.dep_file);
    }

    if (!is_header && compiler_cmd.IsEmpty())
    {
        ret.Add(COMPILER_SIMPLE_LOG + _("Skipping file (no compiler program set): ") + pfd.source_file_native );
        return ret;
    }

    switch (compiler->GetSwitches().logging)
    {
        case clogFull:
            ret.Add(COMPILER_SIMPLE_LOG + compiler_cmd);
            break;

        case clogSimple:
            if (is_header)
                ret.Add(COMPILER_SIMPLE_LOG + _("Pre-compiling header: ") + pfd.source_file_native );
            else
                ret.Add(COMPILER_SIMPLE_LOG + _("Compiling: ") + pfd.source_file_native );
            break;

        case clogNone: // fall-through
        default:
            break;
    }

    AddCommandsToArray(compiler_cmd, ret);

    if (is_header)
        ret.Add(COMPILER_WAIT);

    if (ret_generated.GetCount())
    {
        // not only append commands for (any) generated files to be compiled
        // but also insert a "pause" to allow this file to generate its files first
        if (!is_header) // if is_header, the "pause" has already been added
            ret.Add(COMPILER_WAIT);
        AppendArray(ret_generated, ret);
    }

    // if it's a PCH, delete the previously generated PCH to avoid problems
    // (it 'll be recreated anyway)
    if ( (ft == ftHeader) && pf->compile )
    {
        wxString object_abs = (compiler->GetSwitches().UseFlatObjects)
                            ? pfd.object_file_flat_absolute_native
                            : pfd.object_file_absolute_native;

        if ( wxFileExists(object_abs) && !wxRemoveFile(object_abs) )
            Manager::Get()->GetLogManager()->DebugLog(_("Cannot remove old PCH file:\n") + object_abs);
    }

    return ret;
}
Beispiel #10
0
void ClangPlugin::OnTimer(wxTimerEvent& event)
{
    if (!IsAttached())
        return;
    const int evId = event.GetId();
    if (evId == idEdOpenTimer)
    {
        cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
        if (!ed || !IsProviderFor(ed))
            return;
        else if (m_Proxy.GetTranslationUnitId(ed->GetFilename()) != wxNOT_FOUND)
        {
            m_DiagnosticTimer.Start(DIAGNOSTIC_DELAY, wxTIMER_ONE_SHOT);
            return;
        }
        wxString compileCommand;
        ProjectFile* pf = ed->GetProjectFile();
        ProjectBuildTarget* target = nullptr;
        Compiler* comp = nullptr;
        if (pf && pf->GetParentProject() && !pf->GetBuildTargets().IsEmpty() )
        {
            target = pf->GetParentProject()->GetBuildTarget(pf->GetBuildTargets()[0]);
            comp = CompilerFactory::GetCompiler(target->GetCompilerID());
            if (pf->GetUseCustomBuildCommand(target->GetCompilerID()))
            {
                compileCommand = pf->GetCustomBuildCommand(target->GetCompilerID()).AfterFirst(wxT(' '));
            }
        }
        if (compileCommand.IsEmpty())
            compileCommand = wxT("$options $includes");
        cbProject* proj = (pf ? pf->GetParentProject() : nullptr);
        if (!comp && proj)
            comp = CompilerFactory::GetCompiler(proj->GetCompilerID());
        if (!comp)
        {
            cbProject* tmpPrj = Manager::Get()->GetProjectManager()->GetActiveProject();
            if (tmpPrj)
                comp = CompilerFactory::GetCompiler(tmpPrj->GetCompilerID());
        }
        if (!comp)
            comp = CompilerFactory::GetDefaultCompiler();
        comp->GetCommandGenerator(proj)->GenerateCommandLine(compileCommand, target, pf, ed->GetFilename(),
                                                             g_InvalidStr, g_InvalidStr, g_InvalidStr );
        wxStringTokenizer tokenizer(compileCommand);
        compileCommand.Empty();
        wxString pathStr;
        while (tokenizer.HasMoreTokens())
        {
            wxString flag = tokenizer.GetNextToken();
            // make all include paths absolute, so clang does not choke if Code::Blocks switches directories
            if (flag.StartsWith(wxT("-I"), &pathStr))
            {
                wxFileName path(pathStr);
                if (path.Normalize(wxPATH_NORM_ALL & ~wxPATH_NORM_CASE))
                    flag = wxT("-I") + path.GetFullPath();
            }
            compileCommand += flag + wxT(" ");
        }
        compileCommand += GetCompilerInclDirs(comp->GetID());
        if (FileTypeOf(ed->GetFilename()) == ftHeader) // try to find the associated source
        {
            const wxString& source = GetSourceOf(ed);
            if (!source.IsEmpty())
            {
                m_Proxy.CreateTranslationUnit(source, compileCommand);
                if (m_Proxy.GetTranslationUnitId(ed->GetFilename()) != wxNOT_FOUND)
                    return; // got it
            }
        }
        m_Proxy.CreateTranslationUnit(ed->GetFilename(), compileCommand);
        m_DiagnosticTimer.Start(DIAGNOSTIC_DELAY, wxTIMER_ONE_SHOT);
    }
    else if (evId == idReparseTimer)
    {
        EditorManager* edMgr = Manager::Get()->GetEditorManager();
        cbEditor* ed = edMgr->GetBuiltinActiveEditor();
        if (!ed)
            return;
        if (ed != m_pLastEditor)
        {
            m_TranslUnitId = m_Proxy.GetTranslationUnitId(ed->GetFilename());
            m_pLastEditor = ed;
        }
        if (m_TranslUnitId == wxNOT_FOUND)
            return;
        std::map<wxString, wxString> unsavedFiles;
        for (int i = 0; i < edMgr->GetEditorsCount(); ++i)
        {
            ed = edMgr->GetBuiltinEditor(i);
            if (ed && ed->GetModified())
                unsavedFiles.insert(std::make_pair(ed->GetFilename(), ed->GetControl()->GetText()));
        }
        m_Proxy.Reparse(m_TranslUnitId, unsavedFiles);
        DiagnoseEd(m_pLastEditor, dlMinimal);
    }
    else if (evId == idDiagnosticTimer)
    {
        cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
        if (!ed)
            return;
        if (ed != m_pLastEditor)
        {
            m_TranslUnitId = m_Proxy.GetTranslationUnitId(ed->GetFilename());
            m_pLastEditor = ed;
        }
        if (m_TranslUnitId == wxNOT_FOUND)
            return;
        DiagnoseEd(ed, dlFull);
    }
    else
        event.Skip();
}