Author Topic: C::B's dependency rule issue?  (Read 4494 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
C::B's dependency rule issue?
« 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?




If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6077
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: C::B's dependency rule issue?
« Reply #1 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;")

If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.