Только для заголовков и статическая сборка с QMake - PullRequest
1 голос
/ 21 июня 2019

Я пытаюсь настроить простой класс, который можно использовать как в качестве только заголовка, так и статический с qmake.Я контролирую, если сборка статическая с использованием макроса "STATIC_BUILD", определенного в файле .pro.

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;
}

Комментирование строки "CONFIG + = STATIC_BUILD" в foo.pro и использование класса в качестве заголовка работает только так, как ожидается.Если я скомпилирую этот проект как статический (со строкой выше без комментариев), я получу «неопределенную ссылку» для членов «Foo».

Я заметил, что с "CONFIG + = STATIC_BUILD" без комментариев и комментариями вместо строки

#include "foo.cpp"

в foo.h все работает правильно (конечно, только для статической сборки).Это не имеет никакого смысла для меня, потому что "ifndef" имеет прямую цель не "компилировать" #include в статической сборке.

Что я делаю не так?

Я использую Qt 5.11 с gcc в среде linux.

Ответы [ 2 ]

3 голосов
/ 21 июня 2019

Это известная ошибка QMake, о которой сообщалось несколько раз:

(предупреждение: ненужные оскорбительные выражения в третьем сообщении об ошибке)

КорочеМеханизм, который пропускает сборку для «исходного файла», который упоминается в директиве #include, недостаточно умен, чтобы определить, будет ли директива #include действительно выполняться (то есть он не знает об условных выражениях препроцессора).).

2 голосов
/ 21 июня 2019

Это известная функция qmake.Когда он видит:

#include "foo.cpp"

в заголовке (независимо от того, будет ли он «оценен» или нет), он просто не генерирует правила сборки для foo.cpp, поэтому он не собирается.К сожалению, похоже, что разработчики Qt рассматривают это не как ошибку, а как функцию.

Обходной путь - создать третий файл (например, foo_incsrc.h), в котором есть только одна строка:

#include "foo.cpp"

и измените foo.h соответственно:

#ifndef STATIC_BUILD
#include "foo_incsrc.h"
#endif
...