воскресенье, 27 февраля 2011 г.

Сказ о том, как я пробовал собирать Ocaml'ом нативные виндовые экзешники

Итак. Имеется машина под управлением MS Windows XP SP3. Есть желание собирать native executables под эту платформу с помощью системы функционального программирования Ocaml.

Как следует из информации на сайте, существуют 2 базовых порта Окамла под Windows: один на основе MS Visual C++, другой - MinGW/Cygwin. Я поначалу использовал первый.
До тех пор, пока не заинтересовался генерацией нативных exe-файлов. А тут-то и выясняется, что для этого в первом случае требуется установить сам MS Visual C++ и какой-то MASM. Официально рекомендуется скачивать с сайта Майкрософта версию Visual C++ 2005 Express. Полазив же по сайту MS нашел только какой-то веб-инсталлятор под Visual C++ 2010 Express. Вроде бы как Express-версии бесплатны в использовании (хотя, может, я просто чего-то не понял:). Но в любом случае, тянуть много чего, да еще и сильно проприетарного, не очень хотелось. Так что наш выбор - порт на основе MinGW/CygWin, версию 3.11 которого в виде виндового инсталлятора можно скачать по ссылке: http://caml.inria.fr/pub/distrib/ocaml-3.11/ocaml-3.11.0-win-mgw.exe. Размер инсталлятора - чуть более 40 мегабайт.

После установки Окамла уже можно генерить вполне рабочие экзешники на основе байткода (что, в общем, характерно и для MS-порта). Но для генерации нативных exe-файлов требуется MinGW/CygWin. Как сказано в идущем с окамлом Readme.windows.txt, не следует использовать MinGW с этого сайта http://www.mingw.org, а лучше установить CygWin вот отсюда: http://www.cygwin.com/.
Кроме того, требуется установить FlexDLL, выкачиваемый по этой ссылке: http://alain.frisch.fr/flexdll.html.

Ну что ж, приступим. Качаем цигвиновский setup.exe версии 1.7.7.1 (чуть более 500 килобайт). Этот сетап, как я понял, может работать в нескольких режимах: просто закачивать пакеты без установки, закачивать и тут же устанавливать и - последний - устанавливать из локальной директории. Для установленных пакетов я выбрал каталог C:\CygWin, для закачанных пакетов - D:\CygWin (своеобразный локальный репозиторий, если можно так сказать). Далее, запускаем Setup и выбираем из большого количества пакетов тот минимум, который требуется в окамловой документации, а именно: binutils, gcc-core, gcc-mingw-core, mingw-runtime, w32-api. Причем, какие-то из них входят в список зависимостей других. В общем, устанавливаем требуемые пакеты (я выбирал сразу закачку и установку, но вы можете выбрать тот вариант, который вам более удобен). Проверить текущее состояние CygWin'а можно при помощи его же утилиты CygCheck.exe.

После установки в папке C:\CygWin можно наблюдать древовидную структуру каталогов, которая напоминает структуру каталогов в *Nix-подобных осях. Нам более важно,
что в папке C:\CygWin\Bin теперь находятся exe-шники, которые и составляют ядро команд, эмулирующих поведение *Nix-а под Windows.

Следующим шагом качаем FlexDLL (я выбирал Binary release 0.26 (self-extracting installer)). Размер инсталлятора чуть менее 300 килобайт. В процессе установки запрашивается каталог, куда именно устанавливать. Я выбрал C:\Program Files\FlexDLL.

Последним шагом я добавил в переменную Path 2 каталога: C:\CygWin\Bin и C:\Program Files\FlexDLL. Там же у меня находится и путь к окамловым бинарникам (C:\Ocaml\Bin) (проверьте, на всякий случай, есть ли он у вас в переменной Path).

Теперь, если мы попробуем сделать нативный exe-шник следующего окамлового исходника

== hw.ml ===
let _ = Printf.printf "Hello, world!\n";;
============

командной строкой вида

ocamlopt -o hw.exe hw.ml

мы обнаружим, что сборка не выполняется, и на экран выводится следующее сообщение об ошибке:

===
Отказано в доступе.
** Fatal error: Cannot run gcc -mno-cygwin -print-libgcc-file-name
File "caml_startup", line 1, characters 0-1:
Error: Error during linking
===

Действительно, если в командной строке просто набрать gcc, то мы получим сообщение "Отказано в доступе". Чуть загуглив на эту тему, на неком англоязычном форуме нашел сообщение, в котором человек советует установить на все файлы в каталога CygWin\Bin
атрибут "Системный" (такая ошибка, якобы, появляется, когда у файла слетают атрибуты).
Я у себя посмотрел - атрибут "Системный" у файла на месте. На всякий случай дал attrib +S *.exe, но толку от этого никакого. В итоге что я сделал: gcc.exe в каталоге Цигвина представляет собой символическую ссылку, ведущую на gcc-3.exe, который суть и является полноценным экзешником. Тупо переименовав gcc-3.exe в gcc.exe, мы избавляемся от этой проблемы. Теперь если выполнить команду выше, мы получим файл hw.exe размером 274,930 байт, который является уже нативным для Windows исполняемым файлом.

Для полной уверенности попробуем решить задачу чуть посложнее. Например, соберем нативный экзешник для тестового примера, идущего с lablgtk2 (биндинг gtk+ под ocaml, кто не в курсе).
Для начала скачиваем сам архив lablgtk2 отсюда http://www.math.nagoya-u.ac.jp/~garrigue/soft/olabl/lablgtk.html. Я качал файл lablgtk-2.14.0-win32.zip.
Затем, следуя инструкции, расположенной в архиве, скопировал содержимое каталога \Bin в каталог C:\Ocaml\Bin, а содержимое каталога \Lib (там 2 каталога: LablGtk2
и StudLibs) прямо так с подкаталогами в каталог C:\Ocaml\Lib.
Затем распаковал содержимое каталога Examples\LablGtk2 в произвольный каталог D:\LablGtk2.
Сначала скомпилируем окамловую часть библиотеки. Для чего зайдем в каталог C:\Ocaml\Lib\lablgtk2 и запустим в командной строке "ocaml build.ml". Когда всё выполнится успешно, можно продолжать дальше.

Для сборки exe-шника под Gtk+ необходимы библиотечные файлы самого Gtk+. Рекомендуется качать полный bundle ветки 2.16 вот отсюда ftp://ftp.gnome.org/pub/gnome/binaries/win32/gtk+/2.16/. Я выкачал файл gtk+-bundle_2.16.6-20100912_win32.zip.
После скачивания распаковываем содержимое папки \Lib в каталог D:\LibGtk, например.
Теперь можно приступать непосредственно к сборке тестового примера LablGtk2. Заходим в каталог D:\lablgtk2 и запускаем в командной строке:

ocamlopt -ccopt "-LD:/LibGtk" -I +lablgtk2 lablgtk.cmxa gtkInit.cmx testgtk.ml -o testgtk.exe

В результате получаем в этом же каталоге файл testgtk.exe размером 2,407,211 байт. То есть, как видим, нативные exe-файлы собираются успешно.

Хочется надеяться, эта заметка окажется полезной кому-нибудь из вас.

7 комментариев:

  1. спасибо друг )))

    ОтветитьУдалить
  2. Не за что ) Рад, что кому-то это пригодилось )

    ОтветитьУдалить
  3. Присоединяюсь со своими благодарностями. Я в свою очередь разворачивал цыгвин для тестирования программ написанных на си для микроконтроллеров на ПК.

    Александр.

    ОтветитьУдалить
  4. Опять же, очень доволен, что материал принес некоторую пользу людям )

    ОтветитьУдалить
  5. Да, и кроме того, что решилась такая локальная проблема, я приобрел такой эвристический алгоритм: если что-то не работает, нужно посмотреть, а что именно ты запускаешь (в моём случае до "настоящего" екзешника было 2 символические ссылки).

    А остальные статьи в блоге тоже интересные.

    ОтветитьУдалить
  6. Вообще странно, почему под виндой символические ссылки ведут себя таким необъяснимым (для меня) образом.
    Ну и спасибо еще раз за добрые слова по поводу статей. Хотелось бы писать почаще, но то занят бываю, то тем нет никаких (что чаще).

    ОтветитьУдалить
  7. Присоединяюсь ко многочисленным "Спасибо!"

    ОтветитьУдалить