Программирование на С/C++
Здесь описывается, как использовать разные компиляторы C/C++, чтобы скомпилировать программу под KolibriOS
Visual C++ 6/.NET/2005
- Лицензия: команднострочная версия (Visual C++ Toolkit, компилятор/линковщик, стандартные включаемые файлы и RTL-библиотеки) бесплатна (http://microsoft.com, поиск по сайту), полная версия (IDE, исходники RTL) коммерческая
- Доступные библиотеки для Колибри: библиотека LZMA-упаковки lzmapack.lib; можно использовать любой код, не использующий вызовов ОС и компилирующийся в объектные файлы, которые понимает линковщик от Microsoft (в частности, огромное количество Сишных библиотек). К сожалению, к стандартной RTL (Run-Time Library) это не относится, так что все недостающие функции придётся реализовывать "ручками". Реализация некоторых, впрочем, уже есть.
- Примеры программирования для Колибри: ac97snd, fara, xonix
- Генерируемые форматы: 32-bit PE и 64-bit PE64
- Средства разработки: командная строка в Windows; IDE для Windows
Visual C++ - один из лучших оптимизирующих компиляторов C++. Команднострочный компилятор распространяется Microsoft бесплатно, за IDE нужно платить, поэтому здесь рассматриваются оба варианта. Версия VC6, хоть и довольно давно выпущенная, всё ещё популярна, версии VS.NET и VS2005 имеют свойство тормозить.
Пакет VC (точнее, линковщик link.exe) генерирует исключительно PE-файлы, так что с 32-битностью проблем нет, а вот с генерацией двоичного файла придётся повозиться.
При работе в IDE сначала создадим проект: (для VC6) File->New->Projects->Win32 Application, Project name: hello, (для VS) File->New->Project->Visual C++,General->Empty Project, Name: hello, для VC6 появится мастер, ему указываем "An empty project", подтвердим серьёзность намерений нажатием OK в последнем диалоговом окне и получим в полном соответствии с пожеланиями пустой проект с двумя конфигурациями. Конфигурацию Debug рекомендуется сразу удалить (для VC6 Build->Configurations->кнопка Remove, для VS Build->Configuration Manager->(в выпадающем списке)Edit->кнопка Remove), поскольку отладчик VC в данном контексте заведомо бесполезен. Теперь добавляем в проект (для VC6 Project->Add to Project->Files, для VS Project->Add Existing Item) включаемые файлы kosSyst.h, KosFile.h, mcsmemm.h и файлы с исходным кодом kosSyst.cpp, KosFile.cpp, mcsmemm.cpp (входят в прилагаемые к статье примеры - немного модифицированный вариант из исходников дистрибутива для возможности компиляции с VC6). Кстати, возникающий диалог поддерживает выбор нескольких файлов (если удерживать Ctrl). Далее, создаём основной файл hello.cpp (можно и main.cpp, можно взять любое другое имя) (для VC6 File->New->Files->C++ Source File, File name: hello, для VS File->New->File->Visual C++,C++ File, потом File->Save source1.cpp As, потом File->Move hello.cpp into->hello) и далее начинаем писать сам код. Рекомендуется изучить kosSyst.h, там указаны прототипы функций-обёрток системных вызовов.
#include "kosSyst.h" #include "kosFile.h" const char header[] = "HelloWorld test"; const char string[] = "Hello, World!"; void draw_window(void) { // start redraw kos_WindowRedrawStatus(1); // define&draw window kos_DefineAndDrawWindow(10,40,150,50, 0x33,0xFFFFFF,0,0,(Dword)header); // display string kos_WriteTextToWindow(30,10,8,0,(char*)string,0); // end redraw kos_WindowRedrawStatus(2); } void kos_Main() { draw_window(); for (;;) { switch (kos_WaitForEvent()) { case 1: draw_window(); break; case 2: // key pressed, read it and ignore Byte keyCode; kos_GetKey(keyCode); break; case 3: // button pressed; we have only one button, close kos_ExitApp(); } } }
Теперь настраиваем компиляцию. RTL-библиотеку использовать нельзя, она потянет за собой линковку к Windows-библиотекам, так что для VC6 на вкладке Project->Settings->Link в Category: Input очищаем поле Object/library modules и устанавливаем флажок Ignore all default libraries. Выполнение начинается с функции crtStartUp, так что устанавливаем в Category: Output устанавливаем Entry-point symbol:crtStartUp. Кроме того, в поле Project Options рекомендуется добавить опцию /align:16 (это необязательно, но сильно уменьшает размер бинарника). Для VS соответствующий диалог вызывается по Project->hello Properties и вместо вкладок там treeview, те же действия выполняются так: Configuration Properties->Linker->Input-> Ignore All Default Libraries: Yes, Linker->Advanced->Entry Point: crtStartUp, Linker->Command Line->Additional options: /align:16. Кроме того, для VS нужно явно установить подсистему: Linker->System->SubSystem (возьмите любую, она ни на что не влияет) и отключить при компиляции проверки переполнения стековых буферов и RTTI (они ссылаются на RTL): C/C++ ->Code Generation->Buffer Security Check: No, C/C++ ->Language->Enable Run-Time Type Info: No. Также манифест, вставляемый VS, нам ни к чему, так что Linker->Manifest File->Generate Manifest: No. Теперь компилятор уже способен сгенерировать код, но он окажется в формате PE. Основная идея заключается в том, чтобы получаемый PE-файл пропустить через программу pe2kos.exe, которая сменит его формат на используемый в Колибри. pe2kos.exe включена с исходниками в исходники дистрибутива (папка develop\pe2kos), а также без исходников в прилагаемые к статье примеры. (Есть и альтернативный подход, про который можно прочитать в разделе по MASM, описание линковки.) Колибри-бинарники требуется загружать по нулевому адресу, Колибри-заголовок окажется в начале файла вместо PE-заголовка, так что требуется установить базовый адрес (на той же самой вкладке - Output для VC6, Linker->Advanced для VS - поле Base address) в 0, для VS нужно ещё установить Fixed Base Address в "Image must be loaded at a fixed address (/FIXED)" (VC6 по умолчанию и так не генерирует релокейшенов).
Осталось настроить вызов pe2kos. Для VC6: Project->Settings->Custom Build, для VS: Project->hello Properties->Custom Build Step. В поле Commands/Command Line пишем
pe2kos Release\hello.exe hello
(предполагается, что pe2kos либо лежит в одном из PATH-каталогов, либо в каталоге проекта), в поле Outputs записываем имя бинарника - hello, он сгенерируется в каталоге проекта. Ах да, собственно компиляция теперь как обычно - либо F7, либо Build->Build hello.exe(VC)/Build->Build Solution(VS), либо соответствующая кнопка на панели инструментов. Теперь поработаем с командной строкой. Для начала установим необходимые переменные окружения. При установке VC Toolkit, VC6 или VS в соответствующем разделе главного меню появляется пункт "... Command Prompt", который вызывает консоль, устанавливает нужное окружение и ждёт действий пользователя. Можно самостоятельно запустить консоль и выполнить файл vcvars32.bat. После этого требуется перейти в рабочую папку (диск меняется командой X:, папка на диске - командой cd \folder1\folder2). Предполагается, что в эту папку уже скопированы kosFile.cpp,kosSyst.cpp,mcsmemm.cpp,kosFile.h,kosSyst.h,mcsmemm.h и набран hello.cpp. Необходимые опции компиляции точно такие же, как и в IDE, только теперь они задаются не через GUI, а в командной строке. Компиляция до VS2005:
cl /c /O2 /nologo hello.cpp kosFile.cpp kosSyst.cpp mcsmemm.cpp link /nologo /entry:crtStartUp /subsystem:native /base:0 /fixed /align:16 /nodefaultlib hello.obj kosFile.obj kosSyst.obj mcsmemm.obj pe2kos hello.exe hello
В VS2005 добавляются новые ключи:
cl /c /O2 /nologo /GS- /GR- hello.cpp kosFile.cpp kosSyst.cpp mcsmemm.cpp link /nologo /manifest:no /entry:crtStartUp /subsystem:native /base:0 /fixed /align:16 /nodefaultlib hello.obj kosFile.obj kosSyst.obj mcsmemm.obj pe2kos hello.exe hello
GCC/G++
- Лицензия: бесплатные, OpenSource
- Доступные библиотеки для Колибри: портированные RTL (Run-Time Library, стандартная Си-библиотека), SDL (Simple DirectMedia Layer, на ней основаны куча программ); можно использовать любой код, не использующий вызовов ОС и компилирующийся в объектные файлы, которые понимает ld (GNU линковщик).
- Примеры программирования для Колибри: dosbox, sdlfire, sdlquake, pig
- Генерируемые форматы: 32-bit, probably, 16-bit
- Средства разработки: MinGW - командная строка в Windows (http://www.mingw.org); GCC/G++ - стандартные компиляторы, входящие во все пакеты Linux и cygwin (http://www.cygwin.com)
GCC/G++ - один из лучших оптимизирующих компиляторов C/C++. Двоичные файлы как специальный формат не поддерживает, однако, линковщик понимает специальные скрипты, с помощью которых можно ему сказать довольно много.
Надо установить toolchain:
Теперь пишем обещанный "helloworld". Здесь прототипы функций-обёрток системных вызовов находятся в kos32sys.h. Код (hello.c):
#include <kos32sys.h> static char * title="Window"; void _draw_window(){ BeginDraw(); DrawWindow(100,100,400,200,title,0x80ffffff,0x13); EndDraw(); } int main() { _draw_window(); for (;;) { switch(get_os_event()) { case 1: _draw_window(); continue; case 2: // key pressed, read it and ignore get_key(); continue; case 3: // button pressed; we have only one button, close if(get_os_button() == 1) return 0; continue; } } }
Как компилировать, написано в инструкции выше.
Borland C++
- Лицензия: утилиты командной строки бесплатны ( www.borland.com/bcppbuilder/freecompiler или поиск "Command-Line tools" по сайту), IDE коммерческая
- Доступные библиотеки для Колибри: базовая, необходимая для работы (включает работу с многопоточностью, обёртки системных вызовов, работу с кучей, работу с файлами, но RTL нет).
- Примеры программирования для Колибри: life2 (programs\demos\life2)
- Генерируемые форматы: 32-bit PE
- Средства разработки: командная строка в Windows; IDE для Windows
Компилятор не позволяет генерировать двоичные файлы. Здесь используется интересный подход: раз создавать Колибри-бинарники с помощью компилятора не получается, не будем его использовать! Будем использовать FASM, он позволяет генерировать всё, что нужно. Вопрос: а причём же здесь тогда C++? Ответ: будем писать на C++, но компилировать в ассемблерный текст! "Мелкие" проблемы с несоответствием TASM-синтаксиса выходных файлов от Borland C++ FASM-синтаксису решаются несложной программой t2fasm.exe. Для компиляции потребуется библиотека базовых функций, она входит в вышеупомянутые исходники life2. Собственно код (hello.cpp):
#include <menuet.h> #include <me_heap.h> #include <me_file.h> using namespace Menuet; const char header[] = "HelloWorld test"; const char string[] = "Hello, World!"; bool MenuetOnStart(TStartData &me_start, TThreadData /*th*/) { me_start.Left = 10; me_start.Top = 40; me_start.Width = 150; me_start.Height = 30; me_start.WinData.Title = header; return true; } void MenuetOnDraw(void) { DrawString(30,10,0,string); } bool MenuetOnClose(TThreadData /*th*/) {return true;} int MenuetOnIdle(TThreadData /*th*/) {return -1;} void MenuetOnSize(int /*window_rect*/[], TThreadData /*th*/) {} void MenuetOnKeyPress(TThreadData /*th*/) {GetKey();} void MenuetOnMouse(TThreadData /*th*/) {}
Компиляция требует FASM версии не выше 1.64:
bcc32 -S -v- -R- -6 -a4 -O2 -Og -Oi -Ov -OS -k- -D__MENUET__ -Iinclude hello.cpp echo include "me_make.inc" > f_hello.asm t2fasm < hello.asm >> f_hello.asm fasm f_hello.asm hello
Tiny C Compiler
- Лицензия: бесплатный, OpenSource
- Доступные библиотеки для Колибри: солидная часть RTL (Run-Time Library, стандартная Си-библиотека)
- Программы: TinyTextEditor, TinyHashView
- Генерируемые форматы: 32-bit COFF, ELF, PE, Kolibri
- Средства разработки: командная строка в Windows, Kolibri
Компилятор TCC был доработан для генерации Колибри-бинарников. Также написана некоторая часть C RTL на базе функций Колибри. Исходники как самого компилятора, так и RTL доступны на svn-сервере Колибри: svn://kolibrios.org/programs/develop/ktcc/trunk.
Код (hello.c):
#include <kos32sys1.h> #include <stdlib.h> #define WIN_W 640 #define WIN_H 563 char* title = "TinyC Compiler"; int win_bg_color = 0x858585; void draw_window(){ begin_draw(); sys_create_window(215,100,WIN_W,WIN_H,title,win_bg_color,0x34); end_draw(); } int main() { while(1) { switch(get_os_event()) { case 3: if (get_os_button() == 1) exit(0); break; case 2: get_key(); break; case 1: draw_window(); break; } } }
Компиляция:
tcc hello.c -lck -o hello.kex