...but then precisely it is the correct thing to do. As targets can be assigned to different compilers and therefore different debuggers, virtual targets have no specified value.
The only thing you could do is to record when the active target has changes and issue the RecalcVars then.
I review the code a little, and I see that if the active target name is "All", which is not a valid build target, the debugger will open a dialog to let the user select one, see the code:
int DebuggerGDB::DoDebug(bool breakOnEntry)
{
// set this to true before every error exit point in this function
m_Canceled = false;
ProjectManager* prjMan = Manager::Get()->GetProjectManager();
// select the build target to debug
ProjectBuildTarget* target = 0;
Compiler* actualCompiler = 0;
if (m_PidToAttach == 0)
{
Log(_("Selecting target: "));
if (!m_pProject->BuildTargetValid(m_ActiveBuildTarget, false))
{
int tgtIdx = m_pProject->SelectTarget();
if (tgtIdx == -1)
{
Log(_("canceled"));
m_Canceled = true;
return 3;
}
target = m_pProject->GetBuildTarget(tgtIdx);
m_ActiveBuildTarget = target->GetTitle();
}
else
target = m_pProject->GetBuildTarget(m_ActiveBuildTarget);
So, the debugger plugin know which target it will going to debug.
But what about Macromanager? it was just blind. E.g.:
wxString DebuggerConfiguration::GetDebuggerExecutable(bool expandMacro)
{
wxString result = m_config.Read(wxT("executable_path"), wxEmptyString);
if (expandMacro)
Manager::Get()->GetMacrosManager()->ReplaceEnvVars(result);
return !result.empty() ? result : cbDetectDebuggerExecutable(wxT("gdb"));
}
This code, the debugger plugin try to prepare the full path of gdb.exe, it directly call ReplaceEnvVars(result), which is:
void ReplaceEnvVars(wxString& buffer) { ReplaceMacros(buffer); }
Then:
void MacrosManager::ReplaceMacros(wxString& buffer, ProjectBuildTarget* target, bool subrequest)
{
if (buffer.IsEmpty())
return;
static const wxString delim(_T("$%["));
if ( buffer.find_first_of(delim) == wxString::npos )
return;
cbProject* project = target
? target->GetParentProject()
: Manager::Get()->GetProjectManager()->GetActiveProject();
EditorBase* editor = Manager::Get()->GetEditorManager()->GetActiveEditor();
if (!target)
{
if (project)
{
// use the currently compiling target
target = project->GetCurrentlyCompilingTarget();
// if none,
if (!target)
// use the last known active target
target = project->GetBuildTarget(project->GetActiveBuildTarget());
}
}
if (project != m_LastProject || target != m_LastTarget || (editor && (editor->GetFilename() != m_ActiveEditorFilename)) )
RecalcVars(project, editor, target);
NOTE: when call the function: ReplaceMacros(), the default argument target = 0 is used, which try to use the "GetActiveBuildTarget()", but as we know, currently, the activeTarget name is "All", which is not a valid build target, so the variable "target" is still ZERO.
Thus, even the function RecalcVars() is called, the piece of code in the function body still has no chance to run.
if (target)
{
const StringHash& v = target->GetAllVars();
for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
m_Macros[it->first.Upper()] = it->second;
if (Compiler* c = CompilerFactory::GetCompiler(target->GetCompilerID()))
{
m_Macros[_T("TARGET_CC")] = c->GetPrograms().C;
m_Macros[_T("TARGET_CPP")] = c->GetPrograms().CPP;
m_Macros[_T("TARGET_LD")] = c->GetPrograms().LD;
m_Macros[_T("TARGET_LIB")] = c->GetPrograms().LIB;
wxFileName MasterPath;
MasterPath.SetPath(c->GetMasterPath(), wxPATH_NATIVE);
m_Macros[_T("TARGET_COMPILER_DIR")] = MasterPath.GetPathWithSep(wxPATH_NATIVE);
}
m_Macros[_T("TARGET_OBJECT_DIR")] = target->GetObjectOutput();
}
So: ("TARGET_OBJECT_DIR") is still empty string.
The simple solution I thought is:
1, when the debugger plugin started debugging, it can temporary switch the target to a real valid target name, e.g. Switch "All" to "src".
2, when it finish debugging, do switching back.
This way, the ReplaceMacros() function can get the real valid target, and it should solve the bug.
What's you comments about this?
EDIT:Maybe, we can let the debugger plugin to temporary to select this one, and select to none after debugging......
void cbProject::SetCurrentlyCompilingTarget(ProjectBuildTarget* bt)
{
m_CurrentlyCompilingTarget = bt;
}
In the case that I open a workspace, and I don't want to build anything, and just start debugging.