# 3.2. Первый запуск

После того, как наш проект сгенерирован, первое, что необходимо сделать, - просмотреть структуру кода, чтобы получить общее понимание того, как работает приложение. Это не только поможет нам начать разработку, а и в дальнейшем мы будем ориентироваться, где необходимо вносить изменения.

Когда мы откроем страничку LFV (Logical File Viewer) в левой части окна KDevelop, мы увидим несколько папок, в которых уже размещены файлы проекта в соответствии с их назначением. Первые две папки - "Headers" и "Sources". Папка заголовков логически содержит все файлы заголовков проекта, папка "Sources" - все исходники. Остальные папки сейчас для нас не интересны, их назначение мы рассмотрим позднее.

Две папки содержат следующие файлы:

Headers:

- kscribble.h : содержит объявление класса KScribbleApp.

- kscribbledoc.h : содержит объявление класса KScribbleDoc.

- kscribbleview.h : содержит объявление класса KScribbleView.

- resource.h : содержит коллекцию макросов идентификаторов пунктов меню.

Sources:

- kscribble.cpp : содержит реализацию класса KScribbleApp.

- kscribbledoc.cpp : содержит реализацию класса KScribbleDoc.

- kscribbleview.cpp : содержит реализацию класса KScribbleView.

- main.cpp : содержит реализацию функции main().

Перед тем, как углубиться в исходный код, позволим KDevelop откомпилировать и запустить наше новое приложение. Чтобы сделать это, выберем "Make" из меню "Build". или нажмем соответствующую кнопку на панели инструментов. В нижней части KDevelop откроется окно вывода, и мы увидим сообщения, выдаваемые `make` при работе. Они могут несколько отличаться от приводимых ниже, в зависимости от используемых настроек.

     1   Making all in docs
     2   make[1]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
     3   Making all in en
     4   make[2]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs/en'
     5   make[2]: Nothing to be done for `all'.
     6   make[2]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs/en'
     7   make[2]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
     8   make[2]: Nothing to be done for `all-am'.
     9   make[2]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
     10  make[1]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
     11  make[1]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble'
     12  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribbleview.cpp
     13  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribbledoc.cpp
     14  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribble.cpp
     15  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         main.cpp
     16  /usr/bin/moc ./kscribble.h -o kscribble.moc.cpp
     17  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribble.moc.cpp
     18  /usr/bin/moc ./kscribbledoc.h -o kscribbledoc.moc.cpp
     19  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribbledoc.moc.cpp
     20  /usr/bin/moc ./kscribbleview.h -o kscribbleview.moc.cpp
     21  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
         kscribbleview.moc.cpp

     22  /bin/sh ../libtool --silent --mode=link g++  -O0 -g -Wall   -o kscribble -L/opt/kde/lib  -L/usr/X11R6/lib -rpath /opt/kde/lib
         -rpath /usr/X11R6/lib kscribbleview.o kscribbledoc.o kscribble.o main.o kscribble.moc.o kscribbledoc.moc.o kscribbleview.moc.o
         -lkfile -lkfm -lkdeui -lkdecore -lqt -lXext -lX11

     23  make[1]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble'

Мы проставили номера строк напротив каждой строки, которых нет в выводе KDevelop. Это сделано для облегчения дальнейшего обсуждения того, что происходит при компиляции. Во-первых, `make` работает рекурсивно. Это значит, что она начинает с каталога, откуда была вызвана, и затем в первую очередь заходит в подкаталог, возвращается и заходит в следующий подкаталог. Наконец, обрабатывается стартовый каталог и `make` завершается. `make` вызывается из главного каталога проекта, содержащего исходники. В строках 1 и 2 мы видим, как `make` входит в каталог `docs`, затем в подкаталог `en`. Так как там нечего делать, она выходит из этих каталогов, пока не вернется в каталог исходников `kscribble` в строке 11. Теперь начинается настоящая работа: `make` вызывает компилятор, `g++`, для компиляции файла-исходника `kscribbleview.cpp`. Макрос `-DHAVE&_;CONFIG&_;H` говорит о том, что должен быть использован файл `config.h`. Этот файл содержит макросы для определения платформы и приложения, и расположен в корневом каталоге проекта. Следующие `-I` команды добавляют пути для поиска файлов, указанных в команде `"&#;include"`. Это текущий каталог, корневой каталог проекта (`-I..`), и пути к файлам KDE, Qt и заголовкам библиотек X11. Эти пути определяются при выполнении скрипта `configure` и устанавливаются в файлах Makefile; таким образом, компилятор знает, где файлы расположены. Наконец, `-O0` устанавливает оптимизацию в ноль (без оптимизации), `-g` разрешает отладку, `-Wall` устанавливает предупреждения компилятора в значение `all`, и `-c` говорит компилятору, что необходимо генерировать только файлы obj, то есть надо только откомпилировать файлы.

Это делается и для других файлов-исходников нашего проекта в строках 13-15. Очевидно, наш исходный код откомпилирован, но вместо того, чтобы линковать объектные файлы исходников в конечный бинарный файл, мы видим несколько иные команды. В строке 16 программа "moc" вызывается для обработки файла-заголовка `kscribble.h`, выводя результат в `kscribble.moc.cpp`. Затем, в строке 17, этот исходный файл компилируется. Аналогичные операции проделываются с другими файлами заголовков проекта до строки 21. Это необходимо, поскольку Qt поддерживает механизм сигнал/слот, но базируется на C++ реализации, и мы используем определенные ключевые слова, не поддерживаемые языком C++, такие как `signals:` и `slots:`, в наших классах. Это дает нам возможность легко организовать межобъектное взаимодействие для всех экземпляров классов, порожденных от `QObject`, и избежать использования традиционного механизма callback указателей на функции. Таким образом, приложению необходим исходный код, который обеспечивает данную функциональность, и вот для чего вызывается `moc`. `Moc` - Meta Object Compiler набора инструментов Qt . Он реализует механизм сигнал/слот, обрабатывая файл заголовка и генерируя код, который должен быть откомпилирован для получения бинарного файла. Поскольку проекты KDevelop используют `automoc` для определения того, какие файлы заголовков должны быть обработаны, мы не должны следить за вызовами `moc` и C++ компилятора для обработки сгенерированных `moc` файлов. Только запомните правило, что для использования механизма сигнал/слот класс должен быть порожден от `QObject`, или от любого другого класса, порожденного от `QObject`; кроме того, этот класс должен содержать макрос `Q&_;OBJECT` (без ";"!) в начале своего объявления, и объявления сигналов и слотов.

Наконец, генерируется бинарный файл. Выходной бинарный файл называется `kscribble`, линкер использует пути к библиотекам KDE и X11, и линкует исходники с библиотеками `kfile, kfm, kdeui, kdecore, qt, Xext` и `X11`. На этом make завершает свою работу.