Публикации FreePascal

Free Pascal Compiler FAQ

20.05.2005
Иван Шихалев

Ответы на часто возникающие вопросы по компилятору Free Pascal, языку и стандартным библиотекам.

Вопросы

Компилятор:
Динамические библиотеки:
Совместимость:

Ответы

Версии и ветки: что означает нумерация 1.0.x, 1.1.x, 1.9.x, 2.0.x, 2.1.x?

Free Pascal как и всякий живой открытый проект непрерывно развивается. Постоянно добавляются новые возможности и исправляются ошибки. Соответственно версий становится все больше и больше. Благодаря продуманной нумерации ориентироваться в них достаточно просто.

1.0.x
Версия 1.0, стабильная ветвь: после выхода 1.0.0 добавление новых возможностей в данную ветвь было заморожено, дальнейшая работа велась исключительно в плане отладки, исправления недочетов, оптимизации и переноса на новые платформы.
1.1.x
Версия 1.1, нестабильная ветвь: в то же время, когда окончательно отлаживалась версия 1.0, продолжалась работа и на перспективу: добавлялись новые возможности языка, такие как интерфейсы, widestrings и т.д. Эта работа велась в ветви 1.1 (development branch). Вместе с новыми возможностями добавлялись и новые баги, так что в целом ветка 1.1 была крайне нестабильной. Использовать ее в практичеких целях разработчики не рекомендовали.
1.9.x
Версия 1.9, release candidates: фактически — версия 2.0, недостаточно отлаженная и с пробелами в реализации. Закончено добавление новых возможностей, но уже добавленные еще работают недостаточно хорошо. Хотя думается, что существенные сдвиги в развитии проекта Lazarus пришлись на эту ветвь компилятора не случайно…
2.0.x и 2.1.x
Релиз 2.0 вышел и ситуация повторяется: в стабильной ветви 2.0.x производится доводка и отладка, а все расширения добавляются в нестабильную 2.1.x.

Вывод можно сделать следующий: если вы используете Free Pascal в своих проектах и не желаете самостоятельно вылавливать баги в исходниках, то следует качать версии с нулем во второй позиции (точнее — с четной цифрой, поскольку не исключено, что следующий релиз таки будет 2.2, а не 3.0), если очень не терпится, то с девяткой на свой страх и риск. Если же есть желание поучаствовать в развитии Free Pascal, то берем текущую версию с единичкой (другой нечетной цифрой) во второй позиции, качаем исходники и вперед.

Чем отличаются четные и нечетные в последней цифре версии?

Общий смысл примерно тот же: четная версия стабильная, нечетная — нет. Но в данном случае четная означает, что компилятор собран и проверен авторами, тогда как нечетная — автоматическая сборка из текущих исходников и может вообще отказаться работать. Кроме того, если третья цифра нечетная, то одна и та же версия, скачанная в разные дни — на самом деле две разных версии: последняя цифра не меняется, пока авторы не решат собрать «четный» дистрибутив.

Что такое snapshot?

Snapshot в переводе с английского — снимок. В разработке ПО данный термин означает текущее (с точностью до дня) состояние проекта. На сайте freepascal.org можно встретить упоминания о «source snapshot» и «binary snapshot»: первое — исходники на текущий момент, а второе — автоматическая сборка, сделанная из этих исходников. С одной стороны, использование таких снимков — самый быстрый способ получить исправление какой-то ошибки (на следующий день после того, как она исправлена), но с другой — «binary snapshot» может вообще отказаться работать, а «source» даже и компилироваться. В общем, третья цифра версии в данном случае — нечетная.

Где найти старые версии?

Старые версии доступны на FTP сервере Free Pascal и на его зеркалах. Адрес на главном сервере — ftp://ftp.freepascal.org/pub/fpc/olddist/, на зеркалах — аналогично, т.е. следует искать директорию 'olddist'.

Почему у простой программы такой большой размер? Как его уменьшить?

Большой размер возникает по нескольким причинам:

В некоторых версиях библиотека времени выполнения собрана без smartlink.
Smartlink — это технология, когда к проекту подключается только то, что действительно необходимо, а не модули целиком. Чтобы это работало, сами модули должны быть скомпилированы с директивой {$smartlink on} или ключом командной строки -CX. Иногда, особенно в нестабильных версиях, стандартные модули скомпилированы иначе. Так это или нет, можно узнать поискав файлы вида libp<имя модуля>.a — если такой файл существует, то модуль скомпилирован правильно. Кроме того, следует проверить опции компилятора в командной строке и файле fpc.cfg: чтобы компилятор старался использовать smartlink везде, где это возможно, должна использоваться опция -XX.
Что делать, если соответствующий файл не найден? Лучший способ — скачать и перекомпилировать с нужными опциями RTL, что, однако, требует некоторого понимания структуры исходников FPC и принципов его работы… Более простой способ — поместить в каталог проекта нужный модуль (например sysutils.pp), а так же .inc-файлы, которые он использует, и выставить в нем соответствующую директиву. Главный недостаток этого способа — с модулем System такое не пройдет, а он «весит» более 100 килобайт.
В файл включена отладочная информация.
Следует проверить конфигурационный файл на отсутствие ключа -g…, и на наличие -Xs. Первый указывает включать отладочную информацию, второй — исключить из исполняемого файла информацию о символах, используемую компоновщиком. Если конфигурационный файл стандартный, то можно использовать ключ -dRELEASE в командной строке, который указывает, как обращаться с вышеупомянутыми ключами.
Небольшой нюанс наблюдается под Win32 — компоновщик убирает не всю лишнюю информацию, даже если ему так велено (ключ -Xs в командной строке компилятора). Если размер важен, под Win32 следует пользоваться утилитой strip.

Кроме того, по умолчанию FPC оптимизирует код в сторону ускорения, а не уменьшения. Если размер более критичен, то можно использовать ключ -Og, и оптимизация пойдет на размер.

Дополнительно можно сжать результирующий бинарник утилитой типа UPX.

На каких системах работает FPC?

В настоящий момент (версия 2.0) для скачивания предлагаются варианты для следующих платформ (процессор/OS):

  • ARM
    • Linux
  • i386+
    • FreeBSD (FreeBSD 4.x и, возможно, на 5.x тоже будет работать)
    • Linux
    • Netware
    • OS/2
    • Win32 (Windows 95, 98, ME, NT, 2000, XP, 2003)
  • PowerPC
    • Linux
    • Mac OS
    • Mac OS X
    • MorphOS
  • Sparc
    • Linux
  • AMD64/x86 64
    • Linux

Однако надо заметить, что работы по портированию продолжаются, и что более старые версии поддерживали и другие платформы, такие как DOS, Solaris, OpenBSD и т.д. По всей видимости в ближайшее время для них выйдет и версия 2.0. Так что данный список будет обновляться, следите.

Как создать динамическую библиотеку на FPC?

Динамические библиотеки создаются точно так же, как в Delphi — основной исходный файл начинается с ключевого слова library вместо program; затем идет секция uses; затем, возможно, объявления переменных, функций и т.д.; и наконец — секция exports.

В секции exports через запятую перечисляются имена экспортируемых функций и процедур, при необходимости — с явным указанием имени. Пример секции exports:

exports
  MyFunc, MyOtherFunc,
  MyProc name 'myProc';

Важно: имена экспортируемых функций и процедур зависят от регистра, т.е. — MyFunc и myFunc будут разными именами.

Как использовать в своей программе функции из динамических библиотек?

В целом, использование внешних функций так же аналогично Delphi. Существует два способа загрузки:

Статический
Привязка к библиотеке выполняется на этапе компиляции. Для этого используется ключевое слово external 'libname'. Например:
function MyFunc (Param : Integer) : Integer; external 'mylib';
В этом случае, как и при создании библиотеки можно явно указать имя загружаемой функции:
function MyFunc (Param : Integer) : Integer; external 'mylib' name 'myFunc';
Следует отметить отличие от Delphi — в последней возможно объявить в разделе Interface просто функцию как таковую, а директиву external указать уже в Implementation. FPC же требует сразу указать данную директиву — в Implementation такая функция уже вовсе не фигурирует.
Динамический:
Вся привязка к библиотеке производится на этапе выполнения, для чего используются функции LoadLibrary, GetProcedureAddress и FreeLibrary из модуля dynlibs. В принципе, можно воспользоваться, например, соответствующими функциями из модуля windows, однако такое решение будет привязано к одной платформе. Рекомендуется все-таки использовать кроссплатформенный модуль dynlibs.
Последовательность действий такова:
  1. Объявляем переменную процедурного типа с соответствующими параметрами и типом вызова;
  2. Загружаем библиотеку — LoadLibrary;
  3. Находим адрес нужной функции — GetProcedureAddress — и присваиваем его нашей переменной;
  4. Вызываем функцию через переменную, когда это нам нужно;
  5. Когда функции данной библиотеки больше не нужны, освобождаем ее — FreeLibrary.

Важно: разные системы программирования, и даже разные версии Free Pascal, используют по умолчанию различные соглашения о вызове функций (FPC 1.0 — stdcall, а FPC 2.0 — register). Поэтому, настоятельно рекомендуется при экспорте/импорте функций указывать тип вызова явно.

Можно ли использовать в параметрах функций динамической библиотеки длинные строки, динамические массивы и т.д.?

Вообще говоря, нельзя. Длинные строки и динамические массивы используют динамическую память, причем перераспределение ее происходит неявно и программистом не контролируется. Тем не менее это ограничение можно снять. Подробности см. в материале «Разделяемая память в FPC»

Модуль прекрасно компилируется в Delphi (Turbo Pascal), но не компилируется в FPC?

Скорее всего — не установлен режим совместимости. Для Delphi это — {$MODE DELPHI} или -Mdelphi в командной строке, а для Turbo Pascal — {$MODE TP} или -Mtp. Если хочется частичной совместимости с Delphi и в то же время расширений типа перегрузки операторов, можно попробовать режим OBJFPC, который, однако несколько отличается от Delphi в тонкостях...

Кроме того, надо помнить, что во Free Pascal реализованы не все возможности Delphi — в частности, нет dispinterface, implements и автоматизированного вызова методов интерфейса через variant. О расширениях языка, появившихся в Dephi после 5 версии, пока и речи нет.

Что касается проблем с модулями и программами Turbo Pascal, как правило они связаны с низкоуровневыми вызовами. Надо помнить, что Free Pascal — 32-х разрядный компилятор, кроме того, некоторые вещи, нормальные для DOS, никак не допустимы в Win32 (например).

Если используются ассемблерные вставки, следует помнить, что Free Pascal понимает два синтаксиса ассемблера: Intel (как в Delphi и Turbo Pascal) и AT&T (совсем иначе). Причем по умолчанию используется AT&T-синтаксис. Синтаксис Intel выбирается директивой {$ASMMODE INTEL} или ключом командной строки -Rintel.

Рекомендуется прочитать статьи «Режимы компиляции» по поводу совместимости с Delphi и TP, а также «Использование ассемблера с Free Pascal».

Проблемы со строками.

В отличие от Delphi, Free Pascal по умолчанию трактует тип string как короткую (shortstring или string[255]), а не как длинную (ansistring) строку. Чтобы это исправить, следует использовать директиву {$LONGSTRINGS ON} или ключ командной строки -Sh.

Актуальные версии
FPC3.0.0release
Lazarus1.6release
MSE4.2release
fpGUI1.4.1release
наши спонсоры ;)