Программирование на С/C++

From KolibriOS wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Здесь описывается, как использовать разные компиляторы 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 по умолчанию и так не генерирует релокейшенов).


Hll vc1.gif

Hll vc2.gif

Осталось настроить вызов 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

Hll vc3.gif

В 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

Hll vc4.gif

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++. Двоичные файлы как специальный формат не поддерживает, однако, линковщик понимает специальные скрипты, с помощью которых можно ему сказать довольно много.

Для кросс-компиляции программ на C и C++ для KolibriOS был создан специальный тулчейн.

Ниже приведены руководства по установке данного тулчейна на Linux и Windows.

Установка на Linux

Подробное руководство по установке тулчейна http://board.kolibrios.org/viewtopic.php?f=33&t=3540 Чтобы сделать установку более удобной, turbocat'ом был написан специальный скрипт, которые сделает все за вас). Скачать скрипт-установщик можно на этой странице http://board.kolibrios.org/viewtopic.php?f=33&t=3540&p=76381#p76381

Пример с компиляцией Hello world здесь https://habr.com/ru/post/527144/

ВАЖНО: замечание от автора скрипта:

 Вот написал небольшой скрипт на BASH. Выполняет все действия по установке kos32-gcc и библиотек для Линукса автоматически.
 Не рекомендую запускать от рута(предоставляйте рут только когда скрипт сам потребует).
 Иначе тулчейн будет установлен в папку /root а не ваш домашний каталог!

Установка на Windows

Инструкция по установке тулчейна под Windows: https://habr.com/ru/post/229231/

Для удобства Boppan собрал тулчейн в один архив, скачать его можно тут:

http://board.kolibrios.org/viewtopic.php?f=33&t=1218&p=74401&hilit=kossdk#p74401

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. Собственно код (window.cpp) bcc32:

#include <kolibri.h>
#include <kos_heap.h>
#include <kos_file.h>

using namespace Kolibri;

const char header[] = "Colors";

bool KolibriOnStart(TStartData &kos_start, TThreadData th)
{
       kos_start.Left = 10;
       kos_start.Top = 40;
       kos_start.Width = 135;
       kos_start.Height = 80;
       kos_start.WinData.WindowColor = 0xFFFFFF;
       kos_start.WinData.WindowType = 0x34; // 0x34 - fixed, 0x33 - not fixed
       kos_start.WinData.Title = header;
       return true;
}

void KolibriOnPaint(void)
{
       // If button have ID 1, this is close button
       DrawButton(2,0xff0000, 10,40,50,20);
       DrawButton(3,0x00ff00, 70,10,50,20);
       DrawButton(4,0x0000ff, 70,40,50,20);
       DrawButton(5,0xFFFE00, 10,10,50,20);
}

void KolibriOnButton(long id, TThreadData th)
{
       switch(id){
       case 2:
               SetWindowCaption("Red");
               break;
       case 3:
               SetWindowCaption("Green");
               break;
       case 4:
               SetWindowCaption("Blue");
               break;
       case 5:
               SetWindowCaption("Yellow");
               //break;
       };
}
/*
int KolibriOnIdle(TThreadData th)
{
       return -1;
}
void KolibriOnSize(int window_rect[], TThreadData th) {}
void KolibriOnKeyPress(TThreadData th)
{
       GetKey();
}
void KolibriOnMouse(TThreadData th) {}
*/

Что-бы компилировать FASM версией выше 1.64 нужно пропатчить компилятор. Пример файла window_cpp.bat:

Set NAME=window
Set BCC_DIR=..\..\..\bcc32
kos32-bcc -S -v- -R- -6 -a4 -O2 -Og -Oi -Ov -OS -k- -D__KOLIBRI__ -I..\..\..\bcc32\include %NAME%.cpp

echo STACKSIZE equ 102400> kos_make.inc
echo HEAPSIZE equ 102400>> kos_make.inc
echo include "%BCC_DIR%\include\kos_start.inc">> kos_make.inc
echo include "%BCC_DIR%\include\kos_func.inc">> kos_make.inc
echo include "%BCC_DIR%\include\kos_heap.inc">> kos_make.inc

echo include "kos_make.inc" > f_%NAME%.asm
t2fasm < %NAME%.asm >> f_%NAME%.asm
fasm f_%NAME%.asm %NAME%.kex
if exist %NAME%.kex kpack %NAME%.kex
if exist %NAME%.kex del kos_make.inc
pause


Hll bc1.gif

Tiny C Compiler

  • Лицензия: бесплатный, OpenSource
  • Доступные библиотеки для Колибри: солидная часть RTL (Run-Time Library, стандартная Си-библиотека)
  • Программы: TinyTextEditor, TinyHashView, PasswordGen, Whois, UnIMG, Weather, SHELL
  • Генерируемые форматы: 32-bit COFF, ELF, PE, Kolibri
  • Средства разработки: командная строка в Windows/Linux , консоль Kolibri OS

Компилятор TCC был доработан для генерации Колибри-бинарников. Также написана некоторая часть C RTL на базе функций Колибри. Исходники как самого компилятора, так и RTL доступны на svn-сервере Колибри: svn://kolibrios.org/programs/develop/ktcc/trunk. В отличии от остальных представленных выше компиляторов языка С, он портирован для Kolibri OS.

Примеры программ находятся в дистрибутиве по адресу "/kolibrios/develop/tcc/samples". Так же они доступны на SVN[1]

Пример базовой оконной программы (hello.c):

#include <sys/ksys.h>

enum BUTTONS {
    BTN_QUIT  = 1,
    BTN_CLICK = 2,
};

int count = 0;
ksys_colors_table_t sys_colors;

void redraw_window(void) {
    _ksys_start_draw();
    _ksys_create_window(10, 40, 400, 200, "My window", sys_colors.work_area, 0x14);
    _ksys_draw_text("TCC example", 15, 34, 0, 0x91000000 | sys_colors.work_text);
    _ksys_define_button(150, 100 , 100, 50, BTN_CLICK, sys_colors.work_button);
    _ksys_draw_text("Click!", 155, 115, 0, 0x91000000 | sys_colors.work_button_text);
    _ksys_draw_number(count, 15, 100, 0, 0x92000000 | sys_colors.work_text);
    _ksys_end_draw();
}

int main() {
    _ksys_get_system_colors(&sys_colors);
    while (1) {
        switch (_ksys_get_event()) {
        case KSYS_EVENT_REDRAW:
            redraw_window();
            break;
        case KSYS_EVENT_BUTTON:
            switch (_ksys_get_button()) {
            case BTN_CLICK:
                count++;
                redraw_window();
                break;
            case BTN_QUIT:
                return 0;
            }
            break;
         }
     }
}

Компиляция:

tcc hello.c -o hello