CB20.03, Win10/mingw64.
Do the followings steps.
- [Settings|Global variables] to open [Global Variable Editor] dialog. For the currently selected set add a new variable named "testdir" by [Current variable|New]. For the variable define its [Build-in fields|base] as "XXX". Hit [Close].
- [File|New|Project] to open [New from template] dialog. Select [Console application] and hit [Go] to run the console application wizard. By the wizard create a new project of which name is "ObjDirTest".
- [Project|Properties] to open [Project/targets options] dialog and select [Build targets] page. For the currently selected target set [Output filename] as "bin\$(#testdir)\ObjDirTest.exe" and [Objects output dir] as "obj\$(#testdir)\". Hit [OK].
- [Build|Rebuild] to build the project and see [Logs & others] window [Build log] page to check the excuted commands.
g++.exe -Wall -fexceptions -g -c D:\Users\Takeshi\MinGW\CB_Work\ObjDirTest\main.cpp -o obj\XXX\main.o
g++.exe -o bin\XXX\ObjDirTest.exe obj\XXX\main.o
Normally all "$(#testdir)"s have been replaced with "XXX"s. Continue with the following steps.
- [Settings|Global variables] to open [Global Variable Editor] dialog. Select "testdir" in [Current variable] and change its [Built-in fields|base] as "YYY". Hit [Close].
- [Build|Rebuild].
g++.exe -Wall -fexceptions -g -c D:\Users\Takeshi\MinGW\CB_Work\ObjDirTest\main.cpp -o obj\XXX\main.o
g++.exe -o bin\YYY\ObjDirTest.exe obj\XXX\main.o
Oddly only "$(#testdir)" in the execution output filename has changed to "YYY" but that in the objects output remains "XXX". Continue with the following steps.
- [File|Close project] to close the project.
- [File|Recent projects|...\ObjDirTest\ObjDirTest.cbp] to reopen the project.
- [Build|Rebuild].
g++.exe -Wall -fexceptions -g -c D:\Users\Takeshi\MinGW\CB_Work\ObjDirTest\main.cpp -o obj\YYY\main.o
g++.exe -o bin\YYY\ObjDirTest.exe obj\YYY\main.o
Eventually all "$(#testdir)"s have been replaced with "YYY"s.
Not only global variables show the sympton but environment variables and custom variables. MacrosManager::ReplaceMacros() replaces such variables. The function is called so many times from everywhere that it's hard to make complete analysis. The following is my wild guess.
Almost all variables are replaced just before a build is executed, except for those regarding object files including their output directories. Those are stored in pfDetails class instances after the variable replacements. A project file calls ProjectFile::GetFileDetails() to get a pfDetails instance for a specific target. The function creates the instance if it does not exist, otherwise returns previously created one. Because a build gets the pfDetails instance by the function, the first build uses a new instance and the following builds uses the same instance without any change. Therefore the following builds never changes the output directory.
[sdk\projectfile.cpp:275]
// map target to pfDetails
void ProjectFile::UpdateFileDetails(ProjectBuildTarget* target)
{
if (!project)
return;
if (!compile && !link)
return;
// update PCH output name (in case project PCH mode was changed)
if (FileTypeOf(relativeFilename) == ftHeader)
SetObjName(relativeToCommonTopLevelPath);
if (!target) // update all targets
{
int tcount = project->GetBuildTargetsCount();
for (int x = 0; x < tcount; ++x)
{
ProjectBuildTarget* bt = project->GetBuildTarget(x);
DoUpdateFileDetails(bt);
}
}
else
DoUpdateFileDetails(target);
}
void ProjectFile::DoUpdateFileDetails(ProjectBuildTarget* target)
{
// if we don't belong in this target, abort
if (!target || buildTargets.Index(target->GetTitle()) == wxNOT_FOUND)
return;
// delete old PFD
pfDetails* pfd = m_PFDMap[target];
if (pfd)
pfd->Update(target, this);
else
{
pfd = new pfDetails(target, this);
m_PFDMap[target] = pfd;
}
}
const pfDetails& ProjectFile::GetFileDetails(ProjectBuildTarget* target)
{
pfDetails* pfd = m_PFDMap[target];
if (!pfd)
{
DoUpdateFileDetails(target);
pfd = m_PFDMap[target];
}
return *pfd;
}
Actually ProjectFile::UpdateFileDetails() could be used for updating the pfDetails instance, that looks never used for such the purpose.
Is my guess right? Is this already known? Is this a defect or intentional? Thank you.