Author Topic: Object output dir cannot reflect global variable change  (Read 1218 times)

Offline KodamaDeveloped

  • Multiple posting newcomer
  • *
  • Posts: 16
Object output dir cannot reflect global variable change
« on: December 05, 2020, 07:41:38 am »
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.
Code
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].
Code
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].
Code
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]
Code
// 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.

Offline stahta01

  • Lives here!
  • ****
  • Posts: 7149
    • My Best Post
Re: Object output dir cannot reflect global variable change
« Reply #1 on: December 05, 2020, 03:10:54 pm »
I have had related but different problems on Windows.
The Linux users seem to never have this type of problem; so, it might be caused by a difference in OS handling of something.

Tim S.
C Programmer working to learn more about C++ and Git.
On Windows 7 64 bit and Windows 10 32 bit.
On Debian Stretch, compiling CB Trunk against wxWidgets 3.0.
--
When in doubt, read the CB WiKi FAQ. http://wiki.codeblocks.org

Offline KodamaDeveloped

  • Multiple posting newcomer
  • *
  • Posts: 16
Re: Object output dir cannot reflect global variable change
« Reply #2 on: December 06, 2020, 03:11:35 am »
Thank you for your comment.

I believe the problem I show is not Windows specific because the place causes problem looks being in the generic codes, which relates ProjectFile::GetFileDetails().  Of course I can't make it sure without the Linux test run, unfortunately I don't have such an environment.