Results 1 to 16 of 16

Thread: Avoid full recompilation

  1. #1
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Avoid full recompilation

    Hi,

    I have an application that contains multiple files defining classes. Some classes contain other classes and this ones contain other classes, ...

    When I modify one of the class that other icludes it, all this classes are also recompiled.
    Is there anyway to only link the new object class whitout recompiling it?

    I'm inserting "class classB" inide classA header and so on, but I don't really know if this forward declarations are doing something.

    Thanks,
    Òscar Llarch i Galán

  2. #2
    Join Date
    Jul 2006
    Location
    Catalunya - Spain
    Posts
    117
    Thanks
    16
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    I'm not sure if I this is your case, but to avoid full recompiling, I use this schema :

    In file "A.h" :

    class A
    {
    public :

    A();
    virtual ~A();
    ....
    };

    In file "B.h" :

    class A;

    class B
    {
    A* m_PrivateA; ( or a PIMPL pointer )

    public :

    B();
    virtual ~B();
    };

    and in file "B.cpp" :

    #include "A.h"
    #include "B.h"

    B::B{}
    {
    m_PrivateA = new A;
    }

    B::~B{}
    {
    delete m_PrivateA;
    }

    This is a simple approach, I use much more a PIMPL mechanism, like Qt does, so I don't need to worry about resource leaks ( aka forgetting to delete the private class members )

    Obviously, this schema will recompile B.cpp every time you change "A.h", but if you derive B class like this ( file "C.h" )

    #include "B.h"

    class C : public class B
    {
    public :

    C() : B() {};
    ....
    }

    In file "C.cpp" :

    #include "B.h"

    If you change "A.h", "C.cpp" doesn't have to recompile ( if you don't need to include "A.h", of course... )

  3. #3
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Avoid full recompilation

    If you only use pointers or references to a class (or struct), or if the class is just used as a function return value, then you do not need the class's full declaration.
    A forward declaration is then enough: you may remove the #include and add a line of "class X;" instead.
    (The compiler will tell you if you were wrong.)

    After removal of the #include, you won't have the compile dependency any more.

    (Side note: if class B contains an object of class A (not just a pointer or reference to it), or if it inherits from class A then you always need the full declaration and it is not possible to avoid the compile dependency.)

    HTH

  4. The following user says thank you to caduel for this useful post:

    ^NyAw^ (26th September 2008)

  5. #4
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    Hi,

    Thanks,

    Will try and tell you if it is going well.
    Òscar Llarch i Galán

  6. #5
    Join Date
    Jan 2006
    Location
    Sta. Eugènia de Berga (Vic - Barcelona - Spain)
    Posts
    869
    Thanks
    70
    Thanked 59 Times in 57 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    Hi,

    Just one question: I'm looking "qstring.h" and "qstring.cpp" from Qt sources. Why they use "#include" statments into cpp file? What is the diference on including a header on the h file or in the cpp file? I knew that the include statment must be on the header files only.

    Thanks,
    Òscar Llarch i Galán

  7. #6
    Join Date
    Jul 2006
    Location
    Catalunya - Spain
    Posts
    117
    Thanks
    16
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    Quote Originally Posted by ^NyAw^ View Post
    What is the diference on including a header on the h file or in the cpp file?
    Basically, (re)compilation time. If you include "A.h" file on "B.h" file, every time you change "A.h" ALL the files depending on it ( B.h, B.cpp and others ) MUST be recompiled.

    But if you include only in B.cpp, all files depending on B.h MUST not be recompiled.

    I knew that the include statment must be on the header files only.
    No, it must be only if absolutely necessary ( avoid it if possible ) !!. As a good practice, You usually have to put the declaration of classe's interface in h files and the implementation in cpp files.

    And if you can do "tricks" like the ones I've said before, you will save time and dependencies between files.

  8. #7
    Join Date
    May 2006
    Location
    Germany
    Posts
    108
    Thanks
    2
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    And if you could not strip out more #include statements, then you might want to resort to a hacky approach called unity builds. We use this in our company for a project with several thousand source/header files.
    "If you lie to the compiler, it will get its revenge." - Henry Spencer

  9. The following user says thank you to Methedrine for this useful post:

    jpujolf (3rd October 2008)

  10. #8
    Join Date
    Jul 2006
    Location
    Catalunya - Spain
    Posts
    117
    Thanks
    16
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    I've never heard about Unity Builds but, wow !! It's a great ( and simple ) idea !!

    I'm dealing with a very big project with more than 300 modules and a complete build from scratch takes about 20 minutes on my machine.

    I'll try that aproach and give you the results, but I'm sure will improve compilation speed.

  11. #9
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Avoid full recompilation

    I think that the improvement of build times is only partially due to i/o issues. I would guess that the bigger save stems from the fact that stuff like STL (string, vector, ...) has to be compiled only once, templates only instanciated once...
    Basically with something like UB the code base to be compiled is way smaller.

  12. #10
    Join Date
    May 2006
    Location
    Germany
    Posts
    108
    Thanks
    2
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    Quote Originally Posted by caduel View Post
    I think that the improvement of build times is only partially due to i/o issues. I would guess that the bigger save stems from the fact that stuff like STL (string, vector, ...) has to be compiled only once, templates only instanciated once...
    Basically with something like UB the code base to be compiled is way smaller.
    Actually you can avoid the whole recompilation using header guards / #pragma once already. So the real improvement of unity builds really is the file i/o operations.
    "If you lie to the compiler, it will get its revenge." - Henry Spencer

  13. #11
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Avoid full recompilation

    no.

    If two different translation units (i.e. .cpp files) both include vector then the templates will be (included, i.e.) read twice, instanciated twice, and also compiled twice.
    Include guards or #pragma once do not help here, as we are talking about separate translation units.

  14. #12
    Join Date
    May 2006
    Location
    Germany
    Posts
    108
    Thanks
    2
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    Quote Originally Posted by caduel View Post
    no.

    If two different translation units (i.e. .cpp files) both include vector then the templates will be (included, i.e.) read twice, instanciated twice, and also compiled twice.
    Include guards or #pragma once do not help here, as we are talking about separate translation units.
    Hmmm... iirc I thought that header guards prevented exactly that behaviour? Of course, all the files will certainly be opened again (=> read twice) but they should not be compiled twice (because, for example, the preprocessor got told by a header guard to not include the following stuff any further).

    BTW, if you want to use unity builds with incredibuild, I suggest creating 5-6 unity files. That's what we did at work and we managed to reduce a full recompile from 45 minutes to 6 minutes (of which ~50% is spent with linking).
    "If you lie to the compiler, it will get its revenge." - Henry Spencer

  15. #13
    Join Date
    Dec 2006
    Posts
    849
    Thanks
    6
    Thanked 163 Times in 151 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: Avoid full recompilation

    the compiler compiles file a.cpp and b.cpp separately.
    A header x.hpp will not be included twice in a.cpp or b.cpp - that is prevented by the guards.
    The header will, however, be included (and read, parsed, compiled) in both a.cpp and b.cpp if included there. The compiler is invoked twice after all: for each file separately. Therefore it can not know anymore whatever it did in a.cpp once working on b.cpp, so it has to do the work again. And that work (including io) can be quit a bit to do, esp. if templates and template metaprogramming (like in Boost) is used a lot. (C++ unlike C headers contain nontrivial stuff...)

  16. #14
    Join Date
    Mar 2006
    Location
    The Netherlands
    Posts
    300
    Thanks
    9
    Thanked 29 Times in 29 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Question Re: Avoid full recompilation

    I don't understand how UB could be faster for large projects.

    I imagine those projects for which it works must be very tightly connected indeed. A well-designed piece of software should have as little interdependency as possible, so when a change is made in one or two files only (especially if they're implementation files), there's no need to recompile the entire project. Only those files and their reverse dependencies.

    Of course there are some files that are used in a large portion of the project. But they should be the exception rather than the rule. Is this not true?
    "The strength of a civilization is not measured by its ability to wage wars, but rather by its ability to prevent them." - Gene Roddenberry

  17. #15
    Join Date
    Jul 2006
    Location
    Catalunya - Spain
    Posts
    117
    Thanks
    16
    Thanked 8 Times in 8 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    This morning I've tested to compile my "framework" with Unit Builds. It has 3 parts ( without taking in consideration specific business logic code ) :

    - App launcher ( main executable, thats loads business logic as plugins )
    - Admin business logic ( 2 lightweigth plugins )
    - Main "Core" shared Library ( by now, 93 cpp files => Passed to a single UB )

    The test has been very unsatisfactory to me. Compile time is the same : no gain ( some seconds but not a REAL gain ), and if i touch ANY module, forces to recompile ALL modules => 3 minutes in my library.

    So IMO if you are careful with #including in .h files, only when you make major changes you will have a complete recompilation. And in your usual work if you're careful the traditional approach is better...

    I'm using other "hacking" to avoid full recompiling and I can contain compile time to acceptable ranges :

    - XX_p.h files & private implementations => also makes interface look better , improves library stability & version maintenance / compatibility is simpler.

    - "class XX" in .h files, using references or pointers as parameters / return values and including XX.h in Cpp files.

    So, that's my opinion : if you need to use UB, perhaps you haven't been too much careful creating your code...

  18. #16
    Join Date
    May 2006
    Location
    Germany
    Posts
    108
    Thanks
    2
    Thanked 14 Times in 12 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: Avoid full recompilation

    @caduel: Yeah, correct. It's interesting how ones memory about some things fades when it is rarely required. :-)

    @Michiel and jpujolf:

    Very good guess. That large project I am working is not very well designed. So in this company's tradition a hack was used to solve the issues other hacks created. I am glad I am not working there for much longer anymore ;-)
    Basically there are 4 or 5 files which are included about everywhere, and which get changed just about ... everytime some other little tweak is needed (very, very bad design).
    "If you lie to the compiler, it will get its revenge." - Henry Spencer

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.