Reputation: 836
I am trying to set up a simple class that can be used both as a header only and static with qmake. I am contolling if the build is static using a macro "STATIC_BUILD" defined in the .pro file.
foo.pro:
TEMPLATE = app
CONFIG += c++11
CONFIG += STATIC_BUILD
STATIC_BUILD {
DEFINES += STATIC_BUILD
}
SOURCES += \
main.cpp
HEADERS += \
foo.h
STATIC_BUILD {
SOURCES += \
foo.cpp
}
foo.h
#ifndef FOO_H
#define FOO_H
#ifndef STATIC_BUILD
#define MY_INLINE inline
#else
#define MY_INLINE
#endif
class Foo {
public:
Foo();
int getI() const;
void setI(int value);
private:
int i;
};
#ifndef STATIC_BUILD
#include "foo.cpp"
#endif
#endif // FOO_H
foo.cpp
#include "foo.h"
MY_INLINE Foo::Foo(){}
MY_INLINE int Foo::getI() const {
return i;
}
MY_INLINE void Foo::setI(int value) {
i = value;
}
main.cpp
#include <iostream>
#include "foo.h"
int main() {
Foo f;
f.setI(3);
std::cout << f.getI() << "\n";
return 0;
}
Commenting the line "CONFIG += STATIC_BUILD" in foo.pro and using the class as header only works as expected. If I compile this project as static (with the line above not commented) I get "undefined reference" for members of "Foo".
I noticed that, with "CONFIG += STATIC_BUILD" not commented and commenting instead the line
#include "foo.cpp"
in foo.h, everything works correctly (only for the static build, of course). This does not make any sense to me because the "ifndef" has excactly the purpose to do not "compile" the #include in the static build.
What am I doing wrong?
I am using Qt 5.11 with gcc in a linux environment.
Upvotes: 2
Views: 188
Reputation: 385274
This is a known QMake bug, reported a few times:
(warning: unnecessary offensive language in the third bug report)
In short, the mechanism that skips build for a "source file" found to be mentioned in an #include
directive is not smart enough to consider whether the #include
directive will actually be executed (that is, it doesn't know about preprocessor conditionals).
Upvotes: 3
Reputation: 51890
This is a known qmake "feature." When it sees:
#include "foo.cpp"
in the header (regardless of whether it would be "evaluated" or not), it simply doesn't generate build rules for foo.cpp
, so it's not getting built. Unfortunately, it seems the Qt developers don't view this as a bug, but as a feature.
The workaround is to create a third file (like foo_incsrc.h
) that only has a single line in it:
#include "foo.cpp"
and change your foo.h
accordingly:
#ifndef STATIC_BUILD
#include "foo_incsrc.h"
#endif
Upvotes: 2