0

For some time I struggle with problem and work performance loss because of way how Qmake is working with expansive code base. Consider this minimal project structure which shares *class.h with other, possibly non-Qt projects:

THe Qt-unaffiliated header (can have some .cpp associated as well), moc utility ignores it because no QObjects exist here.

//Aclass.h:
struct A {
   // some definitions that sometimes change for external reasons
   int first;
   // float new_field; // - possible change pulled from repository
   double old_field;
};

Bclass.h might be Qt-controlled (moc-ed), might be not.

//Bclass.h:
#include "Aclass.h"
struct B : A {
   // some definitions that sometimes change for external reasons
};

Qt controlled code:

//app.h
#include "Bclass.h"
#include <QApplication> 

class QApp : public QApplication
{
   Q_OBJECT
public:
   QApp();
   // some methods working with BClass instance 
   foo();

   BClass b;
};

Implementation:

//app.cpp
#include "app.h"
QApp:::QApp (int & argc, char ** argv ) : QApplication (argc, argv ) {}
QApp::foo() { b.old_field = 0.0; } 

Some external code that changes along with change in struct A:

#include "app.h"
int main(int argc, char** argv)  {
     QApp app( argc, argv );
     app.foo();
     // app.b.new_field = 0.0f; // also update from repository
}

All .h files are included into .pro file, into HEADERS variable.

If project was already compiled and then struct A would be changed, e.g. by checkout from repository of main.cpp and Aclass.h, the compilation of app.cpp would not happen again. An old app.o would be linked to new main.o. Which leads to UB - usually a heap corruption or values being written to wrong memory locations.

It happens because Qmake generates makefile in such way that targets for .o files are dependent only on their own header and of list of files processed by moc, i.e app.o is dependant on app.cpp, app.h and, maybe, Bclass.h.

Project's team avoid it by fully updating whole build tree, deleting makefile and recompiling whole project every time. Which get tedious with source code base grown to size around 1 GB and compile time measured in hours. That's especially bad when changes are introduced for debugging purposes, rebuild being skipped and a bug gets masked or exposed as false positive because of ODR breach.

It's an ODR breach, because main.o would use new definitions of struct A and of QApp types, while app.o would be compiled with old ones.

Is there an obscure way to instruct Qmake to include all files like Aclass.h as dependencies, which doesn't involve a script to delete\update manually for each .o file?

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • dupe/related? https://stackoverflow.com/questions/10637762/make-doesnt-rebuild-headers-when-changed – alagner Sep 08 '22 at 10:07
  • @alagner mm, partially related, it's a similar issue. That issue exist even in fully Qt source base/ Only in my case re-run does nothing, if list of files doesn't actually change. Even removal of makefile manual and rebuilding doesn't because make _finds_ existing file - or it's a newer version of qmake\ gnu make is the culprit. QMake updates makefile but not its generated includes. And full rebuild is what I want to avoid, it have to rebuild only affected modules (consider that there is about 16k .o files), – Swift - Friday Pie Sep 08 '22 at 10:27

0 Answers0