0. 개요
현재 Embedded Linux기반에서 GUI를 구현하기 위해서 많은 고민들을 하는 개발자들이
많을 것입니다. 또한 자기에게 적합한 GUI Framework를 선정하였더라도 어떻게 그러한
Framework을 적용해서 개발해야하는지에 대한 개발절차를 알지 못 해 처음 시작시 막막해하는 그러한 분

들을 위해 필자가 그동안 개발해온 방법을 통해 알려드리고자 합니다.
(이 말은 Qt/E나 기존 다른분의 강좌내용과 다소 다를 수 있다는것을 의미합니다.)
여러가지 많은 GUI Platform중 필자가 다루어본 Qt에 대한 내용만 다루어보고
그중 Qt의 가장최신 버전인 Qtopia core 4버전을 기준으로 작성됩니다.
Qtopia core 4는
기존 Qt/Embedded 2.x --> Qt/Embedded 3.x를 통해 넘어온 Qt에서 이름만 변경된것입니다.
기존 Qtopia가 Phone, PDA를 뜻하는것이라 용어에 혼동을 느끼지 않으셨으면 합니다.


1. 개발환경 설정하기
Embedded Linux개발환경은 이미 잘 알려진데로 Host PC에서 크로스컴파일러로 컴파일하고
그 결과물을 Target 보드에 NFS등을 통해 실행하는 형태입니다.
Qt역시 마찬가지이므로 Host PC에서 크로스 컴파일하기 위한 환경을 구성해 놓아야 합니다.
이에관련된 여러가지 문서가 많겠지만 필자의 경우 다음과 같은 절차를 통해 준비합니다.

1.1 Host PC에 Qt크로스 컴파일 하기
대부분 크로스 컴파일과정은 굉장히 복잡했었는데 Qtopia core 4에서는 아주 간단하게 끝납니다.
기존의 모든 Qt크로스 컴파일 문서는 그냥 잊으시고
Trolltech 사이트에서 그냥 Qtopia core 4에 관련된 소스를 받으셔서 크로스 컴파일 하시면 됩니다.
Qt를 X11용으로 컴파일 할 필요도 없고 단지 이것만 하시면 됩니다.

1.2 Host PC에 qt-4용 designer를 설치하기
이것은 host PC에서 qt용 GUI를 만들기 위해서 designer를 활용하기 위해서 인데
필자의 ubuntu system에서는 아래와 같이 설치만 하면 됩니다.
$ sudo apt-get install libqt4-core
$ sudo apt-get install libqt4-debug
$ sudo apt-get install libqt4-dev
$ sudo apt-get install libqt4-gui
$ sudo apt-get install qt4-designer
$ sudo apt-get install qt4-dev-tools

1.3 이제 모든 준비가 완료되었습니다.
기존 Qt포팅문서가 복잡한 이유는 qvfb등을 활용하기 위해서 였는데, 필자의 경험상 이것은 전혀
불필요한 작업이었습니다.
qvfb를 통해 host pc에서 미리 그 결과를 검증해볼 수 있다는 장점은 실제 개발에 있어서
실제 target 기기에만 존재하는 device장치나 속도문제로 인해 오히려 아무의미가 없었기 때문에
이걸 깨달은 시점이후부터는 반드시 실제기기에서만 작업을 합니다.
물론 qvfb가 유용할때가 가끔 있을 수도 있는데, 이런경우에는
ubuntu등의 배포판에는 이미 들어있어서 그걸 그냥 설치해서 이용해도 무관합니다.

2. 개발과정
이제 실제 Qt용 프로그램 제작과정을 살펴보도록 하겠습니다.
MS Windows플랫폼에서 Visual Studio를 써보거나 보신분들은 이와 비슷한 리눅스 GUI개발환경인
KDevelop을 떠올리며 이를 이용해서 개발에 검토하시는 분들이 있습니다.
하지만 필자의 경우에는 KDevelop이나 여타 다른 도구의 도움없이 Qt의 디자이너 + 커맨드라인 + VIM만
이용해서 개발을 합니다.
필자 역시 초기에 Kdevelop등을 이용해서 편하게 개발해보려고 노력을 많이 하였으나
Embedded Linux머신이 x86용이 아닐경우 KDevelop등의 편리한 디버거는 아무런 의미가 없었고
모든 업무가 윈도우즈 중심으로 이루어지는 현실에 있어서 X-windows와 windows를 번갈아 가면서
사용하는것 역시(KVM을 써도 마찬가지) 문제가 많았습니다.
하지만 윈도우에서 리눅스 터미날로 여러가지를 연결해서 개발통합환경의 여러개의 소스코드 띄우기와
Qt designer를 이용하면 Kdevelop부럽지 않게 모든것을 해결 할 수가 있었습니다.
(물론 Qt Designer를 이용하려면 리눅스화면으로 돌아가서 처리해야 하긴 하지만요...)

이제부터 실제 제가 작성하는 과정을 통해서 한번 살펴보도록 하겠습니다.
아래의 그림은 필자가 만들어 볼 화면입니다.


2.1 designer로 ui화면 작성
아래와 같이 실행해서 qt designer를 실행해 보도록 합니다.
$ designer-qt4

위와같이 실행을 하면 아래와 같은 화면이 나옵니다.
만약 안나온다면 앞서 1.2에서 이야기 한데로 시스템에 설치가 제대로 안된것입니다.


위의 화면에서 Dialog with Buttons Bottom이라고 선택된 상태에서 Create버튼을 누릅니다.
Create버튼을 누르면 아래와 같은 화면이 생성이 됩니다.


이제 생성된 화면에 Label, LineEdit를 차례대로 붙여넣겠습니다.
먼저 아래의 그림이 보이는 도구박스에서 Label아이콘을 선택하여 드래그해서 폼에다가 올립니다.



위와 같이 모두 배치가 되었다면 TextLabel이라는 글자 위에서 마우스 오른쪽 버튼을 눌러서
Change Text를 선택합니다. 아래와 같은 화면에서 ID라고 바꾸어 씁니다.

마찬가지로 처음 보여진 그대로 Login화면을 완성해 봅니다.



위와같이 완성이 되었나요?
이제 위에서 바꾼것과 비슷하게 콘트롤의 이름을 바꾸어 봅니다.
바꾸고자 하는 콘트롤 위해서 Change Object Name을 이용해서 바꾸어 봅니다.


모두 바꾸었다면 메뉴에서 LoginFrm.ui이름으로 저장을 하고 빠져나갑니다.
모두 완성되었습니다.

2.2 소스코드 작성하기
2.2.1 main.cpp 작성
아래와 같이 소스코드를 입력합니다.
#include <QApplication>
#include "LoginFrm.h"

int main(int argc, char** argv)
{
   QApplication app(argc, argv);

   LoginFrm frm;
   frm.exec();

   return app.exec();
}

2.2.2 LoginFrm.h 작성
#ifndef [u]LOGINFRM_H[/u]
#define [u]LOGINFRM_H[/u]

#include "ui_LoginFrm.h"

class LoginFrm : public QDialog
{
   Q_OBJECT
private:
   Ui::LoginFrm ui;

public:
   LoginFrm(QWidget* parent = NULL);

protected slots:
   void ok();
   void cancel();
};

#endif

2.2.3 LoginFrm.cpp 작성
#include "LoginFrm.h"
#include <QMessageBox>

LoginFrm::LoginFrm(QWidget* parent/*=NULL*/) : QDialog(parent)
{
   ui.setupUi(this);
   connect( ui.ok, SIGNAL(clicked()), this, SLOT(ok()) );
   connect( ui.cancel, SIGNAL(clicked()), this, SLOT(cancel()) );
}

void LoginFrm::ok()
{
   QMessageBox::information(this, "Login", "ok");
}

void LoginFrm::cancel()
{
   QMessageBox::information(this, "Login", "cancel");
}

2.3 컴파일하기
2.2와 같이 모든 소스코드를 저장하고 나서 이제 프로젝트 파일을 생성해봅니다.
리눅스에서는 Makefile을 이용해서 컴파일 하도록 되어 있는데, 이 Makefile이라는것이 작성하는
방법이 복잡해서 Qt에서는 Qt용 프로젝트를 위한 자동생성도구를 갖추고 있습니다.
이 자동생성도구 qmake를 이용하면 다음과같이 프로젝트 파일과 Makefile을 생성할 수 있습니다.

(아래부터 실제 qmake를 이용해서 결과를 살펴볼때 qmake-qt4처럼 -qt4가 붙은것을 보실 수 있습니다.
이것은 ubuntu이기때문에 그런것인데, ubuntu에서는 qt3와 qt4의 qmake파일명이 같기때문에
구분하기 위해서 이렇게 binary이름을 바꾸어 넣고 qmake라는 명령은 단순히 qmake-qt3나 qmake-qt4라는
파일의 symblolic link형태로 존재합니다.)

2.3.1 프로젝트 생성
다음과 같이 qmake-qt4 -project를 입력하게 되면 자동으로 해당 디렉토리명.pro라는 파일이 생성됩니다

.
만약 프로젝트를 하다가 중간에 소스가 추가/삭제가 되면 다시 -project옵션을 통해 자동으로
갱신할 수 있고, 직접 pro파일을 수정해서 쓰셔도 됩니다.
$ qmake-qt4 -project
$ cat ex.pro
######################################################################
# Automatically generated by qmake (2.01a) ? 8? 24 17:43:07 2007
######################################################################

TEMPLATE = app
TARGET =
DEPENDPATH += .
INCLUDEPATH += .

# Input
HEADERS += LoginFrm.h
FORMS += LoginFrm.ui
SOURCES += LoginFrm.cc main.cpp

2.3.2 프로젝트 파일을 통해 Makefile을 생성
2.3.1에서 생성된 pro파일을 근거로 Makefile을 생성하는것은 qmake-qt4라고 그냥 입력하시면 됩니다.
$ qmake-qt4
$ ls -al Makefile
-rw-r--r-- 1 korone korone 6552 2007-08-24 17:43 Makefile

2.4 이제 컴파일을 해봅니다.
$ make
g++ -c -pipe -O2 -Wall -W -D_REENTRANT  -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -

I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -

I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o LoginFrm.o

LoginFrm.cc
g++ -c -pipe -O2 -Wall -W -D_REENTRANT  -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -

I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -

I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o main.o

main.cpp
/usr/bin/moc-qt4 -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I.

-I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -

I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. LoginFrm.h -o moc_LoginFrm.cpp
g++ -c -pipe -O2 -Wall -W -D_REENTRANT  -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -

I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -

I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o moc_LoginFrm.o

moc_LoginFrm.cpp
g++  -o ex LoginFrm.o main.o moc_LoginFrm.o    -L/usr/lib -lQtGui -lQtCore -lpthread

위 과정이 끝나면 실제파일명이 생성되는데, 필자의 경우 ex라는 디렉토리내에서 생성해서
ex라는 실행결과를 얻었습니다.

$ ./ex

라고 입력하여 아래와 같이 처음의 화면과 같이 실행이 되는지 확인해보세요.


3. Embedded Linux에서 실행하기
2번까지의 과정은 모두 X86에서 직접 컴파일 실행하는것이었지만
Embedded Linux에서 실행하는것은 조금 다른 크로스 컴파일을 해야 합니다.
위의 결과에서 생성된 ex라는 실행파일을 얻기위해서는 컴파일할때 크로스컴파일러와 크로스컴파일된
Qt가 필요합니다.
크로스 컴파일된 Qt는 다음과 같은 과정을 통해 얻고 컴파일 할 수 있습니다.
(이 문서의 핵심은 Qt포팅이 아니므로 자세한 것은 생략합니다. 하지만 그렇다고 해서 아래의
내용이 틀린내용이 아닙니다. 필자의 경우 아래의 형태로만 해서 모든 준비가 끝났으니까요.)

3.1 Qt컴파일 설치
3.1.1 http://trolltech.com/developer/downloads/qtopia/coregpl 사이트에서 qtopia를 다운로드
4.3.1.tar.gz

3.1.2 다운로드 받은 파일을 /opt/qt-4.3.1에다가 압축해제
root@korone-desktop:# cd /opt/qt-4.3.1

3.1.3 컴파일을 위한 환경변수 설정
root@korone-desktop:/opt/qt-4.3.1# export QTDIR=`pwd`
root@korone-desktop:/opt/qt-4.3.1# export LD_LIBRARY_PATH=$QTDIR/lib

3.1.4 컴파일 환경설정
아래의 경우에는 -embedded x86 -little-endian에서 볼 수 있듯이 x86용으로 컴파일 하는 것입니다.
만약 arm, mips등으로 컴파일 하기 위해서는 이 부분을 수정해 주서야 합니다.
root@korone-desktop:/opt/qt-4.2.2# ./configure -prefix /opt/qt-4.2.2 -embedded x86 -little-endian -release -no-largefile -no-accessibility -no-qt3support -qt-zlib -qt-gif -qt-libpng -no-libmng -qt-libjpeg -no-nis -no-cups -qt-freetype -depths 16,24,32

3.1.5 컴파일
root@korone-desktop:/opt/qt-4.3.1# make sub-src

3.1.6 컴파일이 끝나면
target보드에 /opt/qt-4.3.1디렉토리를 생성하고 lib디렉토리를 통째로 복사해 놓음
(이때 strip을 하시는것을 잊으시면 안됩니다. 안하시면 아마도 NAND또는 NOR를 쓸경우 메모리가
부족해 질 수도 있습니다.
복사외에도 실행할때마다 그냥 Host PC에 있는것을 NFS링크로 하면 복사를 하지 않아도 편하게
사용할 수 있습니다.)

3.2 위오같이 Qt에대한 크로스 컴파일 설정이 모두 완료되었다면
2.2에서 살펴본 소스코드를 크로스 컴파일 용으로 컴파일하는것은 굉장히 쉽습니다.

3.2.1 먼저 기존 컴파일된 내용을 초기화 시킴
$ make clean

3.2.2 크로스컴파일용 makefiile생성
아래를 주의할것은 아래의 디렉토리는 조금전 Qt를 크로스 컴파일한 결과가 있는 디렉토리입니다.
$ /opt/qt-4.2.2/bin/qmake
$ make

3.3.3 이제 컴파일을 해보시면 해당 target용으로 생성된 binary를 확인할 수 있습니다.
이것을 실제 target으로 옮기거나 nfs를 통해 실행해 보시면 됩니다.


간단히 생각했던 문서가 막상정리하려니 꽤 복잡합니다.
혹시 부족한 부분이나 틀린부분에 대해서 제게 알려주시면 감사하겠습니다.
감사합니다.

korone.net
조병완( korone a t g mail. co m)
Posted by 블루아레나