Howto

Armadillo-440でQt! 第2回

Armadillo上で動作するQtアプリの作成方法をご紹介するHowtoシリーズ2回目の本Howtoでは、ごく簡単なQtアプリを作成してみて、組み込み向けQtアプリ作成の勘所を押さえていきます。

(前回) Howto : Armadillo-440でQt! 第1回

開発環境の準備

Qtアプリを作成するにあたり、Armadillo用の開発環境であるATDEにQt/Embedded用のライブラリ等をセットアップした環境を用意しました。この開発環境を使うと、すぐにQtアプリの開発を開始できます。

ATDEの使用方法については、既存マニュアル等を参照してください。

この開発環境には、2012年11月05日現在の最新版である Qt 4.8.3が、ホスト環境用(ATDE上で実行するため)とクロス開発用(Armadilloで実行するため)の二種類インストールされています。それぞれのインストールパスは下記の通りです。

  • ホスト環境用: /usr/local/Trolltech/Qt-4.8.3-x11-amd64/
  • クロス開発用: /usr/local/Trolltech/Qt-4.8.3-qws-armel/

Qtアプリの作り方には2種類ある

一口にQtアプリと言っても、実はその作り方には大きく分けて二つあります。一つ目は、C++で記述する方法です。これまでは、この方法が標準の方法でした。2010年9月にリリースされたQt 4.7.0からは、QML(Qt Metaobject Language)と呼ばれるスクリプト言語でUIを記述することができるようになりました。前者はQt Widget、後者はQt Quickとも呼ばれます。( Introduction to Qt Quick によると、Qt Quickとは"現代的なUIを作成するための技術の総称"であり、QMLはその要素技術の一つという位置づけです。)

本Howtoでは、基本となるC++で記述する方法で「Hello World」を作成してみたいと思います。(Qtらしく表示する文字列は「Hello Qt!」になっています。)

C++ Qtアプリ(Qt Widget)でHello!

ソースコード

まず、hello_qtという名前でディレクトリを作成し、そのディレクトリ直下にmain.cppという名前で下記内容のファイルを作成してください。

#include <qapplication>
#include <qlabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QLabel *label = new QLabel("Hello Qt!");

    label-&gt;show();
    return app.exec();
}

意味も分からないコードを実行するのは気持ちが悪いので、少しだけコードの内容を説明します。より詳細な説明は「入門Qt4プログラミング(オライリー・ジャパン)」の1章で解説されています。ぜひそちらもご参照ください。

まず、一行目と二行目で、Qtのクラス(QApplication、QLabel)の宣言をインクルードしています。Qtのクラスは全て大文字のQで始まります。

QApplicationクラスは、アプリケーション全体のリソースを管理するクラスです、コンストラクタでコマンドライン引数(argc, argv)を受け取りその処理をしたり、exec()メソッドを実行することでイベント待ちのループに入ったりします。

QLabelクラスは、文字列を表示するユーザーインターフェース要素です。Qtでは、このようなユーザーが操作するためのユーザーインターフェース要素のことを「ウィジェット(Widget、Window Gadgetの略)」と呼びます。ラベルの他に、ボタン、メニュー、スクロールバー、フレームなど様々なウィジェットが標準で用意されています。

qmakeから始まる

Qtアプリも通常のLinuxアプリケーションと同様に、gcc/g++でコンパイル、リンクするという流れは変わりません。そのため、頑張れば自前でMakefileを記述することも可能です。しかしながら、Qtでは複雑なMakefileの作成を自動化してくれるqmakeというツールが用意されていますので、それを使います。qmakeは*.proという名前のプロジェクトファイルを入力とし、適切なMakefileを生成します。

hello_qtディレクトリの直下に、hello_qt.proという名前で下記内容のプロジェクトファイルを作成してください。

TEMPLATE = app
TARGET = hello_qt
SOURCES += main.cpp

"TEMPLATE = app"で、Qtアプリケーションを作成することを示します。ライブラリを作成する場合は"TEMPLATE = lib"とします。

"TARGET"には、実行ファイル名を指定します。今回の場合、実行ファイル名はhello_qtになります。

"SOURCES"には、TARGETを生成するための入力となるソースコードを指定します。今回の場合、main.cppだけですが、ファイルが複数ある場合はそれぞれ指定します。

Qtでは、これらのソースコード(main.cpp)とプロジェクトファイル(hello_qt.pro)は同じままで、複数の環境で動作する実行ファイルを生成することができます。

ホスト用にビルドして実行

まずは、ホスト環境で動作させてみます。qmakeはそれぞれのQtインストールパスのbinディレクトリにあるものを使用します。qmakeを実行すると、hello_qtディレクトリにMakefileが生成されます。

[ATDE4 ~/hello_qt]$ ls
[ATDE4 ~/hello_qt]$ hello_qt.pro  main.cpp
[ATDE4 ~/hello_qt]$ /usr/local/Trolltech/Qt-4.8.3-x11-amd64/bin/qmake
[ATDE4 ~/hello_qt]$ ls
[ATDE4 ~/hello_qt]$ Makefile  hello_qt.pro  main.cpp

あとはmakeコマンドを実行すれば、実行ファイルが生成されます。

[ATDE4 ~/hello_qt]$ make
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.3-x11-amd64/mkspecs/default -I. -I/usr/local/Trolltech/Qt-4.8.3-x11-amd64/include/QtCore -I/usr/local/Trolltech/Qt-4.8.3-x11-amd64/include/QtGui -I/usr/local/Trolltech/Qt-4.8.3-x11-amd64/include -I. -o main.o main.cpp
g++ -m64 -Wl,-O1 -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.3-x11-amd64/lib -o hello_qt main.o    -L/usr/local/Trolltech/Qt-4.8.3-x11-amd64//lib -lQtGui -L/usr/local/Trolltech/Qt-4.8.3-x11-amd64//lib -L/usr/X11R6/lib64 -lQtCore -lpthread 
[ATDE4 ~/hello_qt]$ ls
[ATDE4 ~/hello_qt]$ Makefile  hello_qt  hello_qt.pro  main.cpp  main.o

hello_qtを実行して、結果を確認してください。

[ATDE4 ~/hello_qt]$ ./hello_qt

ターゲット用にクロスビルドして実行

続いて、同じソースコードをターゲット(Armadillo)用にクロスビルドして、Armadillo上で実行してみます。

ホスト用に生成したMakefileを破棄するために、一度make distcleanを実行しておいてください。

[ATDE4 ~/hello_qt]$ make distclean
[ATDE4 ~/hello_qt]$ ls
hello_qt.pro  main.cpp

クロス開発用Qtのインストールパスは /usr/local/Trolltech/Qt-4.8.3-qws-armel/ ですので、qmakeのパスは /usr/local/Trolltech/Qt-4.8.3-qws-armel/bin/qmake です。

[ATDE4 ~/hello_qt]$ /usr/local/Trolltech/Qt-4.8.3-qws-armel/bin/qmake 
[ATDE4 ~/hello_qt]$ make
arm-linux-gnueabi-g++ -c -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/local/Trolltech/Qt-4.8.3-qws-armel/mkspecs/default -I. -I/usr/local/Trolltech/Qt-4.8.3-qws-armel/include/QtCore -I/usr/local/Trolltech/Qt-4.8.3-qws-armel/include/QtNetwork -I/usr/local/Trolltech/Qt-4.8.3-qws-armel/include/QtGui -I/usr/local/Trolltech/Qt-4.8.3-qws-armel/include -I. -o main.o main.cpp
arm-linux-gnueabi-g++ -Wl,-O1 -Wl,-rpath,/usr/local/Trolltech/Qt-4.8.3-qws-armel/lib -o hello_qt main.o    -L/usr/local/Trolltech/Qt-4.8.3-qws-armel//lib -lQtGui -L/usr/local/Trolltech/Qt-4.8.3-qws-armel//lib -lQtNetwork -lQtCore -lpthread 
[ATDE4 ~/hello_qt]$ ls
Makefile  hello_qt  hello_qt.pro  main.cpp  main.o

ホスト用にビルドしたときはコンパイラとしてg++が使われていましたが、クロスビルドした場合はarm-linux-gnueabi-g++が使われていることに注目してください。arm-linux-gnueabi-g++でコンパイルしたバイナリはARM用バイナリとなるため、ホスト(amd64)では動作しません。

[ATDE4 ~/hello_qt]$ file hello_qt
hello_qt: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped

作成されたARM用バイナリhello_qtをArmadilloに転送します。 Armadillo-440でQt! 第1回 で使用したユーザーランドではSFTPサーバーが起動しているので、sftpコマンドでファイルを転送できます。ユーザー名root/パスワードrootでログインしてください。ArmadilloのIPアドレスが192.168.0.10だった場合の実行例を下記に示します。IPアドレスの部分は適宜読み替えてください。

[ATDE4 ~/hello_qt]$ echo "put hello_qt" | sftp root@192.168.0.10
root@192.168.0.10's password: 
Connected to 172.16.1.65.
sftp&gt; put hello_qt
Uploading hello_qt to /root/hello_qt
hello_qt                                      100% 7974     7.8KB/s   00:00    

以下は、Armadilloのコンソール(シリアル通信ソフトウェア)での操作となります。下記のようにコマンドを実行して、LCDに「Hello Qt!」という文字が書かれたウィンドウが表示されることを確認してください。

[armadillo ~/hello_qt]# /root/hello_qt -qws

まとめ

  • Qtアプリの作り方にはQt Widget(C++)とQt Quick(QML)の2種類ある
  • qmakeでMakefileを自動生成する
  • qmakeはターゲットごとに別々のものを使用する

次は「IDEを使ってみる」

QtでのGUIアプリ開発を簡単にしている要素の一つとして、専用IDE「Qt Creator」の存在があります。Qt Creatorを使うと、下記のようなことが可能になります。

  • UIの設計をグラフィカルなGUIデザイナーで行う
  • ホスト用/ターゲット用の開発を一つのプロジェクトで管理
  • ターゲット用に作成した実行ファイルをボタン一つでターゲットに配置(デプロイ)する
  • ターゲット上でアプリを動作させながらGDBで実機デバッグする

次のHowtoでは、そんなQt Creatorの使い方をご紹介します。

(次回) ArmadilloでQt! 第3回


Appendix1. AtmarkDistとの統合

Armadillo-440でQt! 第1回 で使用したユーザーランドには、hello_qt、hello_qml、samegameという3種類のサンプルアプリが含まれています。hello_qtはQt Widgetアプリ、hello_qmlとsamegameはQt Quickアプリです。

ユーザーランドイメージを作成するには、下記のようにコマンドを実行してください。(カーネルのソースコードは標準のものを使います。)

[ATDE4 ~]$ wget https://download.atmark-techno.com/sample/a440-qt-howto/atmark-dist-qt-20121105.tar.gz
[ATDE4 ~]$ wget https://download.atmark-techno.com/armadillo-440/source/kernel/linux-2.6.26-at16.tar.gz
[ATDE4 ~]$ tar xzvf atmark-dist-qt-20121105.tar.gz
[ATDE4 ~]$ tar xzvf linux-2.6.26-at16.tar.gz
[ATDE4 ~]$ cd atmark-dist-qt-20121105
[ATDE4 ~/atmark-dist-qt-20121105]$ ln -s ../linux-2.6.26-at16 linux-2.6.x
[ATDE4 ~/atmark-dist-qt-20121105]$ make menuconfig
Main Menu
  Vendor/Product Selection
    Vendor: AtmarkTechno
    Products: Armadillo-440.Qt
を選択
[ATDE4 ~/atmark-dist-qt-20121105]$ make

atmark-dist-qt-20121105/images/romfs.img.gzにQtサンプルアプリを含むユーザーランドイメージが生成されます。

サンプルアプリのソースコードは、atmark-dist-qt-20121105/vendors/AtmarkTechno/Armadillo-440.Qt/ にあります。AtmarkDistにQtアプリを組み込む際の参考にしてください。

Appendix2. Qtライブラリビルド時の設定

本Howtoで紹介したATDE4には、ホスト環境用とクロス開発用2種類のQtがインストールされています。ビルド時の設定は、下記の通りです。どの機能が使えるかの確認や、自前でビルドする際の参考にしてください。

ホスト環境用

export PKG_CONFIG_PATH=/usr/lib/pkgconfig
qt-everywhere-opensource-src-4.8.3/configure \
-platform linux-g++-64 -force-pkg-config -release -opensource -confirm-license \
-shared -prefix /usr/local/Trolltech/Qt-4.8.3-x11-amd64/ \
-largefile -no-exceptions -no-accessibility -stl -plugin-sql-sqlite -no-qt3support \
-no-xmlpatterns -multimedia -audio-backend -no-phonon -no-phonon-backend -no-svg \
-no-webkit -javascript-jit -script -scripttools -declarative \
-system-zlib -system-libtiff -system-libpng -system-libmng -system-libjpeg \
-openssl -no-nis -cups -iconv -dbus -glib \
-nomake tests -nomake examples -nomake docs -nomake demos -make tools

クロス開発用

export PKG_CONFIG_PATH=/usr/arm-linux-gnueabi/lib/pkgconfig
qt-everywhere-opensource-src-4.8.3/configure -embedded arm \
-xplatform qws/linux-arm-gnueabi-g++ -force-pkg-config -release -opensource -confirm-license \
-shared -prefix /usr/local/Trolltech/Qt-4.8.3-qws-armel/ \
-largefile -no-exceptions -no-accessibility -stl -plugin-sql-sqlite -no-qt3support \
-no-xmlpatterns -multimedia -audio-backend -no-phonon -no-phonon-backend -no-svg \
-no-webkit -no-javascript-jit -script -scripttools -declarative \
-system-zlib -system-libtiff -system-libpng -system-libmng -system-libjpeg \
-openssl -no-nis -cups -iconv -dbus  -glib \
-plugin-kbd-linuxinput -plugin-mouse-tslib -qt-mouse-linuxinput \
-nomake tests -nomake examples -nomake docs -nomake demos -make tools