How to compile simple Qt 5.2 project in C4Droid
This answer can be seen as a
mini-tutorial to compile and export Qt projects in C4droid.
how to build and compile a simple Qt project in C4Droid, an C++ compiler for Android?
I've created a simple project in Qt Creator for Qt 4.8, compiled the .ui form, and adapted the code from Qt 4.8 to Qt 5.2. The project itself is very simple: A form with a QButton and a QLineEdit. When QButton is pressed, "Hello world" appears in QLineEdit.
These are the files I've posted in my C4droid test folder:
ButtonHelloWorld.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = ButtonHelloWorld
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
main.cpp:
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_ButtonSayHello_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_ButtonSayHello_clicked()
{
ui->LeditSayHello->setText(tr("Hello world"));
}
mainwindow.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>198</width>
<height>103</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="ButtonSayHello">
<property name="text">
<string>Say Hello</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="LeditSayHello">
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
Now, open ButtonHelloWorld.pro or main.cpp from C4Droid. Long-tap Compile, selected "Makefile" compilation mode and "Qt application" run mode, and "libButtonHelloWorld.so" as executable file.
This is important: In Android Qt executables are always named libXXX.so. The executable name must be lib[NameOf.proFileWithoutExtension].so, and it's folder-name independant.
Once compiled and tested it runs OK, to export it to an .APK is so easy as Menu->Export.
I've tried it and... it's amazing!!
PS: If you wonder where are the moc, qmake, rcc and uic executables, they are in /data/data/com.n0n3m4.droidc/files/gcc/qt/bin/ folder (at least, in my android).
Bull
Worked recently with C++, Qt, OpenCV, PointCloud and several Time of Flight cameras under Linux (Ubuntu). Currently involved in C++ and Wt (Web Toolkit, AKA "Witty") developing, under Linux and Windows. Active developer in Microsoft Dynamics Ax and related technologies. Very interested in cross-developing between platforms and operative systems.
Updated on June 09, 2022Comments
-
Bull almost 2 years
I'm trying to figure how to build and compile a simple Qt project in C4Droid, an C++ compiler for Android.
The program comes with 2 simple examples: An "Hello world" Label (one file), and a example Notepad. The second one, seems interesting, but it deals with forms creating them entirely from code.
I'm investigating if doing this with forms generated from .ui files is possible. I've created a simple project in Qt Creator for Qt 4.8, compiled the .ui form, and adapted the code from Qt 4.8 to Qt 5.2. The project itself is very simple: A form with a QButton and a QLineEdit. When QButton is pressed, "Hello world" appears in QLineEdit.
AS far as I've seen, C4Droid doesn't parse .pro files. To compile project, I must open main.cpp and long-tap "compile", select "Compile multiple source code files (simple)", and then run. C4droid uses it's own "makefile" file, in a .c4droid text file.
These are the files I've posted in my C4droid test folder:
ButtonHelloWorld.pro:
QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = ButtonHelloWorld TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += mainwindow.h FORMS += mainwindow.ui
main.cpp:
#include <QApplication> #include "mainwindow.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_ButtonSayHello_clicked(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
mainwindow.cpp:
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_ButtonSayHello_clicked() { ui->LeditSayHello->setText(tr("Hello world")); }
ui_mainwindow.h:
#ifndef UI_MAINWINDOW_H #define UI_MAINWINDOW_H #include <QtCore/QVariant> #include <QAction> #include <QApplication> #include <QButtonGroup> #include <QHeaderView> #include <QLineEdit> #include <QMainWindow> #include <QPushButton> #include <QVBoxLayout> #include <QWidget> QT_BEGIN_NAMESPACE class Ui_MainWindow { public: QWidget *centralWidget; QVBoxLayout *verticalLayout; QPushButton *ButtonSayHello; QLineEdit *LeditSayHello; void setupUi(QMainWindow *MainWindow) { if (MainWindow->objectName().isEmpty()) MainWindow->setObjectName(QString::fromUtf8("MainWindow")); MainWindow->resize(198, 103); centralWidget = new QWidget(MainWindow); centralWidget->setObjectName(QString::fromUtf8("centralWidget")); verticalLayout = new QVBoxLayout(centralWidget); verticalLayout->setSpacing(6); verticalLayout->setContentsMargins(11, 11, 11, 11); verticalLayout->setObjectName(QString::fromUtf8("verticalLayout")); ButtonSayHello = new QPushButton(centralWidget); ButtonSayHello->setObjectName(QString::fromUtf8("ButtonSayHello")); verticalLayout->addWidget(ButtonSayHello); LeditSayHello = new QLineEdit(centralWidget); LeditSayHello->setObjectName(QString::fromUtf8("LeditSayHello")); LeditSayHello->setAlignment(Qt::AlignCenter); verticalLayout->addWidget(LeditSayHello); MainWindow->setCentralWidget(centralWidget); retranslateUi(MainWindow); QMetaObject::connectSlotsByName(MainWindow); } // setupUi void retranslateUi(QMainWindow *MainWindow) { MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0)); ButtonSayHello->setText(QApplication::translate("MainWindow", "Say Hello", 0)); } // retranslateUi }; namespace Ui { class MainWindow: public Ui_MainWindow {}; } // namespace Ui QT_END_NAMESPACE #endif // UI_MAINWINDOW_H
I put here the original mainwindow.ui for reference (c4droid does not use it):
<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>198</width> <height>103</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralWidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QPushButton" name="ButtonSayHello"> <property name="text"> <string>Say Hello</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="LeditSayHello"> <property name="alignment"> <set>Qt::AlignCenter</set> </property> </widget> </item> </layout> </widget> </widget> <layoutdefault spacing="6" margin="11"/> <resources/> <connections/> </ui>
When I try to compile this project from main.cpp in C4droid, the output is:
/storage/emulated/0/Bull/C4Droid/ButtonHelloWorld/main.cpp:0: Note: No relevant classes found. No output generated. /data/data/com.n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o: In function
MainWindow::MainWindow(QWidget*)': mainwindow.cpp:(.text+0xc4): undefined reference to
vtable for MainWindow' /data/data/com.n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o: In functionMainWindow::~MainWindow()': mainwindow.cpp:(.text+0x14c): undefined reference to
vtable for MainWindow' /data/data/com.n0n3m4.droidc/files/gcc/tmpdir/ccyCC2RV.o: In functionMainWindow::tr(char const*, char const*, int)': mainwindow.cpp:(.text._ZN10MainWindow2trEPKcS1_i[_ZN10MainWindow2trEPKcS1_i]+0x5c): undefined reference to
MainWindow::staticMetaObject' collect2: error: ld returned 1 exit statusWhat can I do to compile successfully this project?
Of course, I've googled a lot, and tried to include .moc files everywere with no luck.
(By the way, I just tried now to create the tag "C4Droid", but I haven't enough reputation to do that :-/)
Update 1 --- Looking carefully the multiple files Qt example shipped with C4droid, I've noticed that it uses Makefile. Reading Makefile, I've noticed that this file was generated using the command:
/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/qmake -spec android-g++ -o Makefile application.pro
(This also made me to know that moc, qmake, rcc and uic executables are in /data/data/com.n0n3m4.droidc/files/gcc/qt/bin/ folder in my android)
This should create a Makefile according to file .pro, that automatically tells the system to use uic, moc, etc before compiling, and doing the proper linkings after that. So I entered in Terminal in my android and typed:
/data/data/com.n0n3m4.droidc/files/gcc/qt/bin/qmake -spec android-g++ -o Makefile ButtonHelloWorld.pro
All I get is:
sh: arm-linux-androideabi-gcc: not found
Update 2
The C4droid developer responsed me:
"C4droid can parse .pro files, look at the examples carefully. The description on Google Play is the only tutorial available, but it is enough."
So I decided to go to my .pro file in C4droid. After looking the example compile options, I decided to long-press compile, selected "Makefile" compilation mode and "Qt application" run mode, and "ButtonHelloWorld.qexe" as executable file.
I now compiles and all appears to go much better, but at end this message pops:
Failed to copy file
Any hints?
Update 3
OK, I tested and played (a lot) with the example Qt appl bundled I emailed again the developer, and it now has been absolutly handy.
Me:
I've decided to do a test with your example. I've copied to a new folder (/storage/emulated/0/Bull/C4Droid/application)
images folder application.pro application.qrc main.cpp mainwindow.cpp mainwindow.h
Then, in C4droid, I open application.pro, long-tap "Compile". Select "Makefile" compilation mode and "Qt application" run mode, and put an executable file "pplication.so". It compiles OK, but fails with "Failed to copy file".
But if I put "libapplication.so" as executable file, it compiles and finishes OK.
¿Why?
He:
Because on Android Qt executables are always named libXXX.so
Me:
Well, I tried "libappli.so" and got same error.
But, Investigating this, I've seen that executable name must be lib[NameOf.proFileWithoutExtension].so, and it's folder-name independant. Now your copied example and mine work!!
And also, he told me that once compiled, export it to an .APK is so easy as Menu->Export. I've tried it and... it's amazing!!
Conclusion
Solved. Answering my own Question in order to help others in my same situation.
-
László Papp almost 10 yearsSo, you have to create the moc file by running 'moc -o mainwindow.moc inputfile` and then compile the generated moc file as usual, e.g.
g++ ... mainwindow.moc
. -
Bull almost 10 yearsAccording to your suggestion, I entered in Terminal, went to my project folder, and typed: /data/data/com.n0n3m4.droidc/files/gcc/qt/bin/moc mainwindow.h -o mainwindow.h.moc After that, no luck in compiling. What more should I do?
-
László Papp almost 10 yearsI do not know what no luck means, but like I said before you have to do two steps, where you only did one.
-
László Papp almost 10 yearsHave you read this part of my comment?
and then compile the generated moc file as usual, e.g. g++ ... mainwindow.moc.
-
Bull almost 10 yearsI've ask the C4droid developer about this, and his answer was (just now): "C4droid can parse .pro files, look at the examples carefully. The description on Google Play is the only tutorial available, but it is enough." Will review both again (one more time)
-
Bull almost 10 yearsLaszlo, you're right, compiling the moc just generates a normal cpp file that can be compiled and linked as usual. Thanks for your suggestions.
-
Bull almost 10 yearsWell, your suggestion was a good point, but wasn't the solution at all
-
László Papp almost 10 yearsThere is an official tutorial already, basically... It is amazing you have not linked that. ;)
-
Bull almost 10 yearsI googled a lot but found anything. Only app description in Google Play was available, ant it was too concise and unclear for me. Tell me the link you're referring, and I will gladly include it in my post.