Details
-
Bug
-
Resolution: Done
-
P4: Low
-
1.12.1
-
None
-
gcc 7.3, Qt-5.11.2, Qbs 1.12.1 (Linux)
-
-
5c84373d8d60a8b13df1fcdcd77480736952c095 (qbs/qbs/master)
Description
In my project I need to create QObject derived classes (with Q_OBJECT and signals) using a macro. The macro resides in a separate file. Here is a simplified example:
The macro is declared in the file 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__
I use the macro to create my class in the file MyQtClass.h
#ifndef __MYQTCLASS_H__ #define __MYQTCLASS_H__ #include <QObject> #include "CreateQtClass.h" CREATE_QT_CLASS( MyQtClass ); #endif //__MYQTCLASS_H__
In my .qbs file, I add MyQtClass.h to the files property, like this:
import qbs QtApplication { name: "HelloWorld-Qt" files: [ "main.cpp", "MyQtClass.h" ] }
The file 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; }
When running
qbs build
qbs doesn't run 'moc' on MyQtClass.h. It looks like it doesn't do the scanning correctly, and doesn't detect the Q_OBJECT inside the macro.
I have created a simple Makefile to shows that when manually forcing moc to run on MyQtClass.h, everything works well. This is the Makefile:
CXX = /usr/bin/g++
QT_VERSION = 5.11.2
QT_PATH = /home/user/programs/Qt$(QT_VERSION)/$(QT_VERSION)/gcc_64
MOC = $(QT_PATH)/bin/moc
INCLUDES = \
-I$(QT_PATH)/include \
-I$(QT_PATH)/include/QtCore \
-I$(QT_PATH)/mkspecs/linux-g++ \
-I/usr/include
LINK_FLAGS = \
-Wl,-m,elf_x86_64,-rpath,$(QT_PATH)/lib \
-L$(QT_PATH)/lib \
-m64 $(QT_PATH)/lib/libQt5Core.so.$(QT_VERSION) \
-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
I think that the problem is that qbs and moc do not scan the files in the same manner. Qbs tries to detect whether the file MyQtClass.h needs to be moc'ed but fails where moc itself succeeds.
The lack of consistency between the two tools (qbs, moc) can lead to situations where files are not detected correctly.
For this reason I think that we need some kind of way to manually tell Qbs that a file (MyQtClass.h, in my case) needs to be moc'ed.
What I suggest is that we add new a fileTag such as "force_moc" which we can attached to files such as MyQtClass.h and force qbs to run moc on them.
Attached all the files to reproduce the problem + the Makefile