Code::Blocks Forums

User forums => Using Code::Blocks => Topic started by: ollydbg on October 12, 2013, 02:37:55 pm

Title: C::B's dependency rule issue?
Post by: ollydbg on October 12, 2013, 02:37:55 pm
I have a simple console project, which have "main.h" and "main.cpp".

main.h is an empty file, select the option "Compile file", and use custom build command: cmd /c copy $file main1.h, select the priority weight to 0.


main.cpp's content:
Code
#include "main1.h"
#include <iostream>

using namespace std;

int main()
{
    cout << "Hello world!" << endl;
    return 0;
}



First press build button the log is below:

Code
-------------- Build: Debug in depend (compiler: GNU GCC Compiler)---------------

[ 33.3%] cmd /c copy  E:\code\cb\test_code\depend\main.h main1.h
        1 file(s) copied.
[ 66.7%] g++.exe -Wall -fexceptions -g  -c E:\code\cb\test_code\depend\main.cpp -o obj\Debug\main.o
[100.0%] g++.exe  -o bin\Debug\depend.exe obj\Debug\main.o  
Output file is bin\Debug\depend.exe with size 52.54 KB
Process terminated with status 0 (0 minute(s), 1 second(s))
0 error(s), 0 warning(s) (0 minute(s), 1 second(s))
Now, press build again, I have the custom build command run again, then link again.

Code
-------------- Build: Debug in depend (compiler: GNU GCC Compiler)---------------

[ 50.0%] cmd /c copy  E:\code\cb\test_code\depend\main.h main1.h
        1 file(s) copied.
[100.0%] g++.exe  -o bin\Debug\depend.exe obj\Debug\main.o  
Output file is bin\Debug\depend.exe with size 52.54 KB
Process terminated with status 0 (0 minute(s), 0 second(s))
0 error(s), 0 warning(s) (0 minute(s), 0 second(s))
press build again, I get the same result as before, so my questions are:
1, I don't change main.h, why the custom command run again?
2, why the linker run again and again?
3, if the dependency checker know main1.h changed, why not compile main.cpp?




Title: Re: C::B's dependency rule issue?
Post by: ollydbg on October 12, 2013, 04:21:27 pm
Debugged a little, I found the build command was generated in the below code:

Code
wxArrayString DirectCommands::GetTargetCompileCommands(ProjectBuildTarget* target, bool force) const
{
    wxArrayString ret;

    // set list of #include directories
    DepsSearchStart(target);

    // iterate all files of the project/target and add them to the build process
    size_t counter = ret.GetCount();
    MyFilesArray files = GetProjectFilesSortedByWeight(target, true, false);
    size_t fcount = files.GetCount();
    bool hasWeight = false;
    unsigned short int lastWeight = 0;
    for (unsigned int i = 0; i < fcount; ++i)
    {
        ProjectFile* pf = files[i];
        // auto-generated files are handled automatically in GetCompileFileCommand()
        if (pf->AutoGeneratedBy())
            continue;

        const pfDetails& pfd = pf->GetFileDetails(target);
        wxString err;
        if (force || IsObjectOutdated(target, pfd, &err))
        {
            // Add a wait command if the weight of the current file is different from the previous one
            // Because GetCompileFileCommand() already adds a wait command if it compiled a PCH we
            // check the last command to prevent two consecutive wait commands
            if (hasWeight && lastWeight != pf->weight && (ret.IsEmpty() || ret.Last() != COMPILER_WAIT))
                ret.Add(wxString(COMPILER_WAIT));

            // compile file
            wxArrayString filecmd = GetCompileFileCommand(target, pf);
            AppendArray(filecmd, ret);

            // Update the weight
            if (!hasWeight)
                hasWeight = true;
            lastWeight = pf->weight;
        }
        else
        {
            if (!err.IsEmpty())
                ret.Add(wxString(COMPILER_WARNING_LOG) + err);
        }
        if (m_doYield)
            Manager::Yield();
    }

    // add link command
    wxArrayString link = GetLinkCommands(target, ret.GetCount() != counter);
    AppendArray(link, ret);

    return ret;
}

First, it looks like when checking for the status of "main.h", the function "IsObjectOutdated" always return true, so bad, this means why the custom command was always added, this result the command:
Code
[ 50.0%] cmd /c copy  E:\code\cb\test_code\depend\main.h main1.h
        1 file(s) copied.

Second, look at the code: "ret.GetCount() != counter", so the linker command is added then, this result the command:
Code
[100.0%] g++.exe  -o bin\Debug\depend.exe obj\Debug\main.o 

Third, do you think it is better to write "ret.GetCount()>0", the counter variable is always 0, but I think here we use 0 is much better, any ideas? ("size_t counter = ret.GetCount();" is the only place to set the counter value, which is after "wxArrayString ret;")