QBS: qbs не может запустить moc, когда класс объявлен через макрос в другом файле - PullRequest
0 голосов
/ 07 ноября 2018

В моем проекте мне нужно создать производные классы QObject (с Q_OBJECT и сигналами), используя макрос. Макрос находится в отдельном файле. Вот упрощенный пример:

Макрос объявлен в файле CreateQtClass.h:

#ifndef __CREATEQTCLASS_H__
#define __CREATEQTCLASS_H__

#define CREATE_QT_CLASS( ClassName ) \
class ClassName : public QObject \
{ \
  Q_OBJECT \
\
 signals: \
  Q_SIGNAL void mySignal( void ); \
}; 

#endif //__CREATEQTCLASS_H__

Я использую макрос для создания своего класса в файле MyQtClass.h

#ifndef __MYQTCLASS_H__
#define __MYQTCLASS_H__

#include <QObject>
#include "CreateQtClass.h"

CREATE_QT_CLASS( MyQtClass );

#endif //__MYQTCLASS_H__

В своем файле .qbs я добавляю MyQtClass.h к свойству files, например:

import qbs

QtApplication {
    name: "HelloWorld-Qt"
    files: [ "main.cpp", "MyQtClass.h" ]
}

Теперь, когда запускается qbs build, qbs не запускает 'moc' на MyQtClass.h. Похоже, что он не выполняет сканирование правильно и не обнаруживает Q_OBJECT внутри макроса.

(Могу заметить, что если объявление и использование макроса находятся в одном файле, все работает нормально).

Мой вопрос:

Есть ли способ для пользователя вручную заставить qbs запускать 'moc' для файла?

Может быть, нам нужно что-то вроде fileTag «force_moc» (противоположность «unmocable»), который я могу применить к группе, содержащей MyQtClass.h.

Дополнительно:

Я добавляю простой Makefile и main.cpp, чтобы продемонстрировать, что moc хорошо работает с вышеуказанным подходом:

Файл main.cpp:

#include <QDebug>
#include "MyQtClass.h"

static void mySlot( void )
{
  qDebug() << "Hello slot";
}

int main( void )
{
  MyQtClass c;
  QObject::connect( &c, &MyQtClass::mySignal, &mySlot );
  emit c.mySignal();
  return 0;
}

Makefile:

CXX = /usr/bin/g++
MOC = /home/user/programs/Qt5.11.2/5.11.2/gcc_64/bin/moc

INCLUDES = \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include/QtCore \
    -I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/mkspecs/linux-g++ \
    -I/usr/include

LINK_FLAGS = \
    -Wl,-m,elf_x86_64,-rpath,/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
    -L/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
    -m64 /home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib/libQt5Core.so.5.11.2 \
    -lpthread

C_FLAGS = \
    -g \
    -O0 \
    -Wall \
    -Wextra \
    -m64 \
    -pipe \
    -fexceptions \
    -fvisibility=default \
    -fPIC \
    -DQT_CORE_LIB \
    $(INCLUDES) \
    -std=c++11

SOURCES = main.cpp
OBJS = $(SOURCES:%.cpp=%.cpp.o)

HEADERS_THAT_NEED_MOC = MyQtClass.h
MOC_OBJS = $(HEADERS_THAT_NEED_MOC:%.h=moc_%.cpp.o)

all: HelloWorld-Qt

HelloWorld-Qt: $(OBJS) $(MOC_OBJS)
    $(CXX) $^ $(LINK_FLAGS) -o $@

%.cpp.o : %.cpp
    $(CXX) $(C_FLAGS) -c $^ -o $@

moc_%.cpp: %.h
    $(MOC) -DQT_CORE_LIB $(INCLUDES) $^ -o $@

clean:
    rm -f *.cpp.o HelloWorld-Qt moc_*.cpp

1 Ответ

0 голосов
/ 07 ноября 2018

Я не думаю, что ваш подход может работать независимо от того, какой инструмент сборки вы используете. Имейте в виду, что moc ищет макрос Q_OBJECT. Такой макрос никогда не может быть найден в MyQtClass.h, потому что ни moc, ни поддерживающий его инструмент сборки не будут расширять макрос CREATE_QT_CLASS, потому что расширение макроса также будет расширять Q_OBJECT. Обратите внимание, что если вы добавите CreateQtClass.h в ваш файл qbs, вы заметите, что qbs запускает moc - но для файла CreateQtClass. Это правильное поведение, потому что именно здесь происходит макрос Q_OBJECT. Я дважды проверил с qmake и cmake, и все они ведут себя одинаково: если вы не перечислите CreateQtClass в файле проекта, они не будут запускать moc. Если вы перечислите его, moc будет запущен для этого файла. Если вы хотите продолжать использовать свой макрос, вам нужно обязательно сослаться на Q_OBJECT на вызывающем сайте, например, в качестве параметра макроса. Но даже тогда, я не уверен, что moc сам будет любить эту конструкцию.

...