Mirakurun Mirakurun - 3 months ago 47
C++ Question

qmake with Jenkins

I am trying to make Jenkins do the compile and build for me whenever I push commit to Git. I have a helloworld app created in Qt Creator. It does compile and build in Qt Creator, it does show on my phone, but it doesn't want to compile and build with Jenkins.

I am using the same shell commands which QtC used:

qmake helloworld.pro -r -spec android-g++;
make;


The console output is:

+ qmake helloworld.pro -r -spec android-g++
+ make
/home/ndk/toolchains/arm-linux-androideabi-4.9-/prebuilt/bin/arm-linux-androideabi-g++ -c -pipe -std=c++11 -O2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -mthumb -Wall -Wno-psabi -W -I/usr/share/qt4/mkspecs/android-g++ -I. -I. -I/home/ndk/sources/cxx-stl/gnu-libstdc++//include -I/home/ndk/sources/cxx-stl/gnu-libstdc++//libs//include -I/home/ndk/platforms//arch-arm//usr/include -o main.o main.cpp
In file included from main.cpp:1:0:
mainwindow.h:4:23: fatal error: QMainWindow: No such file or directory
#include <QMainWindow>
^
compilation terminated.
Makefile:187: recipe for target 'main.o' failed
make: *** [main.o] Error 1


My helloworld.pro:

QT += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = helloworld
TEMPLATE = app


SOURCES += main.cpp\
mainwindow.cpp

HEADERS += mainwindow.h

FORMS += mainwindow.ui

CONFIG += mobility
MOBILITY =


main.cpp

#include "mainwindow.h"
#include <QMainWindow>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}


EDIT/UPDATE:

So far, I have tried to specify the full path to qmake, to be sure that I use Qt's qmake.

/home/qt/5.7/android_armv7/bin/qmake helloworld.pro -r -spec android-g++;
make;


The output is:

/home/qt/5.7/android_armv7/bin/uic mainwindow.ui -o ui_mainwindow.h
/home/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -c -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -DANDROID -Wa,--noexecstack -fno-builtin-memmove -std=c++11 -O2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -mthumb -Wall -Wno-psabi -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I../../qt/5.7/android_armv7/include -I../../qt/5.7/android_armv7/include/QtWidgets -I../../qt/5.7/android_armv7/include/QtGui -I../../qt/5.7/android_armv7/include/QtCore -I. -I. -I../../ndk/sources/cxx-stl/gnu-libstdc++/4.9/include -I../../ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -I../../ndk/platforms/android-9/arch-arm/usr/include -I../../qt/5.7/android_armv7/mkspecs/android-g++ -o main.o main.cpp
/home/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-g++ -c -Wno-psabi -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums -DANDROID -Wa,--noexecstack -fno-builtin-memmove -std=c++11 -O2 -Os -fomit-frame-pointer -fno-strict-aliasing -finline-limit=64 -mthumb -Wall -Wno-psabi -W -D_REENTRANT -fPIC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -I../../qt/5.7/android_armv7/include -I../../qt/5.7/android_armv7/include/QtWidgets -I../../qt/5.7/android_armv7/include/QtGui -I../../qt/5.7/android_armv7/include/QtCore -I. -I. -I../../ndk/sources/cxx-stl/gnu-libstdc++/4.9/include -I../../ndk/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -I../../ndk/platforms/android-9/arch-arm/usr/include -I../../qt/5.7/android_armv7/mkspecs/android-g++ -o mainwindow.o mainwindow.cpp
mainwindow.cpp:3:25: fatal error: QtGui/QAction: No such file or directory
#include <QtGui/QAction>
^
compilation terminated.
Makefile:1780: recipe for target 'mainwindow.o' failed
make: *** [mainwindow.o] Error 1

Answer

Most likely your jenkins setup uses the wrong qmake. There's a 1:1 mapping between a Qt installation and its qmake. So, your install of Qt for android will have its own qmake that you must refer to by full path! Qt Creator sets up the path so that this happens automatically, Jenkins doesn't - and it shouldn't anyway.

When building for any particular Qt version, you only need to invoke its qmake explicitly. From then onwards, as long as the proper compiler is in the path, things will happen as they should and you don't ever need to refer to that Qt version manually again. The makefiles will all refer to Qt libraries, headers and tools from that Qt install.

You also don't need the -spec argument. Each Qt installation is compiled for a particular mkspec, so qmake itself knows exactly what the spec is. I have no idea why QtCreator gives that argument, it doesn't make much sense.