Copyright (C) А.Гавва V-0.4w май 2004

3. От исходного текста к загружаемому файлу программы

3.1 Соглашения GNAT по наименованиям файлов

3.1.1 Общие правила наименования файлов

Не зависимо от используемой операционной системы (Microsoft Windows или Linux) компилятор GNAT достаточно активно использует суффиксы имен файлов (иначе, расширения имен файлов). Ниже перечисляются общие соглашения GNAT по использованию суффиксов имен файлов:

Суффикс   Пояснения
.ads  -  файл с исходным текстом спецификации пакета Ады
.adb  -  файл с исходным текстом тела пакета Ады или Ада-программы
.adc  -  файл конфигурации GNAT
.adt  -  файл дерева зависимостей
.ali  -  файл содержащий информацию для связывания и отладки, который генерируется GNAT в процессе компиляции
.xrb  -  файл перекрестных ссылок генерируемый утилитой gnatf

По умолчанию, имя файла определяется именем модуля, который содержится в этом файле. Имя файла формируется путем взятия полного расширенного имени модуля и замене разделительных точек символами дефиса ('-'). Следует заметить, что при формировании имени файла используются буквы только нижнего регистра.

Исключение из этого правила касается файлов чьи имена начинаются символами a, g, i или s, а следующим символом является символ дефиса. В этом случае вместо символа дефиса ('-') используется символ тильды ('~'). Смысл таких специальных правил заключается в том, что это позволяет избежать конфликта имен с файлами стандартной библиотеки, которые содержат дочерние модули пакетов System, Ada, Interfaces и GNAT, использующих для имен файлов префиксы s-, a-, i- или g-, соответственно.

Следующий список демонстрирует некоторые примеры использования этих правил именования файлов:

Имя файла   Пояснения
main.ads  -  Спецификация главной программы
main.adb  -  Тело главной программы
arith_functions.ads  -  Спецификация пакета Arith_Functions
arith_functions.adb  -  Тело пакета Arith_Functions
func-spec.ads  -  Спецификация дочернего пакета Func.Spec
func-spec.adb  -  Тело дочернего пакета Func.Spec
main-sub.adb  -  Тело Sub субмодуля Main
a~bad.adb  -  Тело дочернего пакета A.Bad

Соблюдение этих правил при наличии длинных имен модулей (например, в случае глубокой вложенности модулей) может привести к чрезмерно длинным именам файлов. Для усечения длин имен файлов можно использовать "уплотнение" имен файлов. В частности, это может быть полезно когда в используемой операционной системе действуют ограничения на длину имени файла.

Естественно, алгоритм "уплотнения" имен файлов не может полностью гарантировать уникальность для всех возможных имен файлов. Это означает, что при использовании "уплотнения" имен файлов окончательная ответственность за уникальность имен файлов возлагается на разработчика приложения. В качестве альтернативы может быть использовано явное указание имен файлов (рассматривается далее).

При переносе Ада-программы из среды компилятора который поддерживает другие соглашения по наименованию файлов для создания файлов с исходными текстами, имена которых будут соответствовать соглашениям GNAT, может быть использована утилита gnatchop.

3.1.2 Использование других имен файлов

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

Однако в некоторых случаях, в частности, при импортировании программы из окружения другого Ада-компилятора, для программиста может оказаться более удобной возможность непосредственного указания имен файлов в которых находятся определенные модули. GNAT позволяет указывать "случайные" имена файлов с помощью директивы компилятора Source_File_Name, которая имеет следующий вид:


pragma Source_File_Name (My_Utilities.Stacks,
  Spec_File_Name => "myutilst_a.ada");
pragma Source_File_name (My_Utilities.Stacks,
  Body_File_Name => "myutilst.ada");

Первый аргумент директивы указывает имя модуля (в случае показанного примера - имя дочернего модуля). Второй аргумент использует форму именной ассоциации, которая указывает, что имя файла используется для спецификации или тела модуля. Непосредственное имя файла указывается строковым литералом.

Следует заметить, что директива указания имени файла с исходным текстом является конфигурационной директивой GNAT. Это подразумевает, что она обычно располагается в файле gnat.adc, который используется для сохранения директив конфигурации применяемых для среды компиляции.

Таким образом, использование директивы указания имени файла с исходным текстом позволяет указывать абсолютно "случайные" имена файлов. Однако если указанное имя файла имеет расширение имени файла, которое отличается от .ads или .adb, то при выполнении компиляции файла необходимо применять специальную опцию командной строки gcc, которая указывает язык программирования используемый в файле. Такой опцией командной строки gcc является опция -x. Для указания языка программирования она должна сопровождаться пробелом и именем используемого языка программирования, в данном случае - ada:


$ gnatgcc -c -x ada peculiar_file_name.sim

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

3.1.3 Альтернативные схемы именования

Ранее мы рассмотрели использование директивы компилятора Source_File_Name, которая позволяет использовать произвольные имена для отдельных файлов с исходными текстами. Этот подход требует наличия директивы для каждого файла именуемого произвольным образом. Таким образом, в случае разработки большой системы, это ведет к значительному увеличению размеров файла gnat.adc и, как следствие, может осложнить сопровождение проекта.

Начиная с версии 3.15, GNAT предусматривает возможность указания общей схемы именования файлов с исходными текстами, которая отличается от используемой по умолчанию стандартной схемы именования файлов. Для этого используются показанные ниже формы директивы компилятора Source_File_Name:


pragma Source_File_Name (
   Spec_File_Name  => FILE_NAME_PATTERN
 [,Casing          => CASING_SPEC]
 [,Dot_Replacement => STRING_LITERAL]);

pragma Source_File_Name (
   Body_File_Name  => FILE_NAME_PATTERN
 [,Casing          => CASING_SPEC]
 [,Dot_Replacement => STRING_LITERAL]);

pragma Source_File_Name (
   Subunit_File_Name  => FILE_NAME_PATTERN
 [,Casing             => CASING_SPEC]
 [,Dot_Replacement    => STRING_LITERAL]);

FILE_NAME_PATTERN ::= STRING_LITERAL
CASING_SPEC ::= Lowercase | Uppercase | Mixedcase

Строка FILE_NAME_PATTERN является шаблоном имен файлов. Она содержит один символ звездочки, вместо которого подставляется имя модуля. Необязательный параметр Casing указывает используемый в имени файла регистр символов: Lowercase - нижний регистр (маленькие буквы), Uppercase - верхний регистр (большие буквы), Mixedcase - смешанное использование регистра символов. При отсутствии параметра Casing, по умолчанию, используется Lowercase.

Необязательный параметр, строка Dot_Replacement, используется для подстановки вместо точек, которые присутствуют в именах субмодулей. Когда строка Dot_Replacement не указывается, разделяющие точки неизменно присутствуют в имени файла. Хотя показанный выше синтаксис демонстрирует, что параметр Casing указывается перед параметром Dot_Replacement, допускается запись этих параметров в противоположной последовательности.

Из показанной выше формы директивы Source_File_Name видно, что возможно указание различных схем именования для тел, спецификаций и субмодулей. Достаточно часто для именования субмодулей желательно использовать такое же правило как и для тел модулей. В таком случае можно не указывать правило Subunit_File_Name, и для именования субмодулей будет использоваться правило Body_File_name.

Указание отдельного правила для именования субмодулей может быть использовано в случае реализации необычного окружения компиляции (например, при компиляции в одном каталоге), которое содержит субмодули и дочерние модули с одинаковыми именами. Хотя оба модуля не могут одновременно присутствовать в одном разделе программы, стандарт допускает (но не требует) возможность сосуществования двух таких модулей в одном окружении.

Трансляция имен файлов включает следующие шаги:

Как пример использования этого механизма рассмотрим распространенную схему именования, когда для имен файлов используется нижний регистр, разделительная точка неизменно копируется в результирующее имя файла, имена файлов спецификаций заканчиваются как ".1.ada", а имена файлов тел заканчиваются как ".2.ada". GNAT будет следовать этой схеме при наличии двух директив:


pragma Source_File_Name
  (Spec_File_Name => "*.1.ada");
pragma Source_File_Name
  (Body_File_Name => "*.2.ada");

Стандартная, используемая по умолчанию схема именования фактически реализуется следующими диективами, которые устанавливаются по умолчанию внутренне:


pragma Source_File_Name
  (Spec_File_Name => "*.ads", Dot_Replacement => "-");
pragma Source_File_Name
  (Body_File_Name => "*.adb", Dot_Replacement => "-");

В качестве заключительного примера, рассмотрим реализацию схемы именования, которую использует один из компиляторов Ada83: как символ-разделитель для субмодулей используется "__" (два символа подчеркивания); файлы спецификаций идентифицируются добавлением "_.ADA"; файлы тел идентифицируются добавлением ".ADA"; файлы субмодулей идентифицируются добавлением ".SEP". Для всех имен файлов используется верхний регистр символов. Естественно, что дочерние модули - не представлены, поскольку это компилятор Ada83, однако, будет логично расширить эту схему указанием использовать двойное подчеркивание в качестве разделителя для дочерних модулей.


pragma Source_File_Name
  (Spec_File_Name => "*_.ADA",
   Dot_Replacement => "__",
   Casing = Uppercase);
pragma Source_File_Name
  (Body_File_Name => "*.ADA",
   Dot_Replacement => "__",
   Casing = Uppercase);
pragma Source_File_Name
  (Subunit_File_Name => "*.SEP",
   Dot_Replacement => "__",
   Casing = Uppercase);

3.2 Сборка первой программы

Используя любой текстовый редактор вашей системы создайте файл hello.adb, который содержит следующую программу на языке Ада:


with Ada.Text_IO;
use  Ada.Text_IO;
procedure Hello is
begin
    Put_Line( "Hello World!" );
end Hello;

Эта программа будет печатать на экране простое сообщение приветствия. После сохранения файла, для построения выполняемого файла программы необходимо выполнить команду gnatmake:


gnatmake hello.adb

Если при написании файла с исходным текстом были допущены ошибки, gnatmake покажет вам номер строки, номер символа в строке и сообщение об ошибке, описывающее суть возникшей проблемы. Если текст программы был написан без ошибок, то вы получите исполняемый файл hello.exe, если вы используете Windows, или hello, если вы используете Linux. Запустить полученную программу на выполнение можно командой:


hello

или, в некоторых дистрибутивах Linux:


./hello

В результате, на экране дисплея появится сообщение:


Hello World!

После построения этого проекта, каталог будет содержать следующие файлы:

Файл   Пояснения
hello.adb  -  файл с исходным текстом программы на языке Ада
hello.o  -  двоичный файл созданный компилятором, который содержит объектный код
hello.ali  -  дополнительный информационный файл созданный компилятором (Ada Library Information file)
hello.exe или hello  -  исполнимый файл программы

Мы можем спокойно удалить файлы hello.o и hello.ali, которые в данном случае являются дополнительными информационными файлами. Однако, при разработке больших проектов, содержащих большое количество файлов, сохранение подобных файлов в последствии может ускорить процесс построения проекта.

3.3 Три этапа сборки проекта

Весь процесс построения проекта осуществляется в три этапа, которые утилита gnatmake выполняет автоматически:

  1. Компиляция (compiling): утилита gnatmake осуществляет проверку вашего файла на наличие в нем каких-либо ошибок. Если ошибки не обнаружены, то выполняется создание объектного файла, содержащего двоичную версию программы. При обнаружении ошибок, работа утилиты gnatmake завершается.
  2. Связывание (binding): утилита gnatmake проверяет согласованность обновления версий всех файлов проекта. Если при этом обнаруживаются файлы которые нуждаются в перекомпиляции, gnatmake осуществит компиляцию таких файлов.
  3. Компоновка (linking): утилита gnatmake осуществляет комбинирование всех объектных файлов проекта для создания результирующего исполняемого файла программы.

Любой из этих этапов построения проекта может быть выполнен "вручную". Например, для полностью "ручной" сборки программы hello.adb можно выполнить следующее:

  1. Компиляция программы с помощью команды:

    
    gcc -c hello.adb
    

    Примечание: при использовании в операционной системе Linux дистрибутива GNAT от ALT вместо команды gcc применяется команда gnatgcc.

  2. Связывание с помощью команды:

    
    gnatbind hello.ali
    

  3. Компоновка программы с помощью команды:

    
    gnatlink hello.ali
    

В случаях простых проектов проще и удобнее использовать автоматическое управление сборкой проекта. Необходимость сборки "вручную" возникает в случаях когда какой-либо этап сборки нуждается в настройках, которые должны соответствовать определенным требованиям или условиям сборки проекта.

3.3.1 Опции компилятора

Программа gcc (или gnatgcc, для дистрибутива ALT) принимает следующие опции командной строки, которые позволяют непосредственно управлять процессом компиляции:

-b target  -  Компиляция программы которая предназначена для запуска на платформе target. Здесь target подразумевает имя конфигурации системы. Если target не является той же самой системой на которой выполняется компиляция, то система компилятора GNAT должна быть построена и сконфигурирована так, чтобы обеспечивать кросс-компиляцию для платформы target.
-Bdir  -  Загрузить компилятор (например, Ада-компилятор gnat1) из каталога dir вместо того, который определен соглашениями по умолчанию. Использование этой опции имеет смысл только в случае доступности различных версий компилятора GNAT. За более подробными сведениями следует обратиться к руководству по gcc. Вместо этой опции обычно используются опции -b или -V.
-c  -  Выполнить компиляцию. Эта опция всегда используется при выполнении компиляции Ада-программы. Примечательно, что можно использовать gcc (или gnatgcc) без опции -c для выполнения компиляции и компоновки за один шаг. Это вызвано необходимостью вызова редактора связей, но в текущий момент gnatgcc не может быть использован для запуска редактора связей GNAT.
-g  -  Выполнить генерацию отладочной информации. Эта информация сохраняется в объектном файле и, затем, копируется из него в результирующий выполняемый файл компоновщиком, после чего, отладочная информация может быть прочитана и использована отладчиком. Опцию -g необходимо использовать если планируется последующее использование отладчика (как правило gdb).
-Idir  -  Указывает компилятору каталог dir для поиска файлов с исходными текстами необходимыми для текущей компиляции.
-I-  -  Указывает компилятору, что не нужно искать файлы с исходными текстами в каталогах указанных в командной строке.
-o file  -  Эта опция используется для перенаправления вывода генерируемого компилятором объектного файла и ассоциируемого с ним ALI-файла. Данная опция нуждается в аккуратном использовании поскольку это может привести к тому, что объектный файл и ALI-файл будут иметь различные имена, что в результате может "запутать" редактор связей gnatbind и компоновщик gnatlink.
-O[n]  -  Здесь, значение n определяет уровень оптимизации:
n = 0  -  Оптимизация отсутствует, установлено по умолчанию если не указана опция -O
n = 1  -  Нормальная оптимизация, установлено по умолчанию если указана опция -O без операнда
n = 2  -  Экстенсивная оптимизация
n = 3  -  Экстенсивная оптимизация с автоматической встроенной подстановкой (inline). Это применяется только для встроенной подстановки внутри модулей.
-S  -  Используется совместно с опцией -c для генерации файла с исходным текстом на языке ассемблера (расширение имени файла .s) вместо файла с объектным кодом. Это может быть полезно когда необходима проверка генерируемого кода для ассемблера.
-v  -  Установить "многословный" режим, который показывает все команды, генерируемые gcc (gnatgcc). Обычно используется только в целях отладки или когда необходимо убедиться в правильности используемой/запускаемой версии компилятора.
-V ver  -  Запустить на выполнение версию компилятора ver. Подразумевается версия gcc (gnatgcc), а не версия GNAT.
-funwind-tables  -  Эта опция производит генерацию объектного файла с unwind table information. Это требуется для обработки исключений с нулевыми затратами производительности, которая использует трассировочные способности библиотеки GNAT.
-gnata  -  Активирует использование контрольных инструкций (assertion) устанавливаемых директивами компилятора "pragma Assert" и "pragma Debug".
-gnatb  -  Генерировать краткие сообщения на stderr даже при установленном опцией -v "многословном" режиме.
-gnatc  -  Выполнить проверку синтаксиса и семантики (без генерации какого-либо выходного кода).
-gnatD  -  Выводить расширенные исходные тексты для отладки на уровне исходных текстов. Эта опция подавляет генерацию информации о перекрестных ссылках (см. опцию -gnatx).
-gnate  -  Принудительная генерация сообщений об ошибках (используется в случае разрушения компилятора при компиляции).
-gnatE  -  Выполнить полную проверку динамической элаборации.
-gnatf  -  Полные ошибки. Множественные ошибки в одной строке, все неописанные ссылки.
-gnatF  -  Все внешние имена приводить к верхнему регистру.
-gnatg  -  Активация проверки стиля написания исходного текста.
-gnatG  -  Отобразить генерируемый расширенный код в виде исходного текста.
-gnatic  -  Установить кодировку символов для идентификаторов в исходном тексте (c=1/2/3/4/8/p/f/n/w).
-gnath  -  Выдать информацию об использовании. Вывод осуществляется на stdout.
-gnatkn  -  Ограничить длину имен файлов длиной n (1-999) символов (k = krunch).
-gnatl  -  Выводить полный листинг исходных текстов, включая встроенные сообщения об ошибках.
-gnatmn  -  Ограничить число детектируемых ошибок величиной n (1-999).
-gnatn  -  Активировать встроенную подстановку (inline) в пределах модуля для подпрограмм, которые указаны в директивах компилятора Inline.
-fno-inline  -  Подавить любые встроенные подстановки (inline), даже если активированы другие опции оптимизации и встроенная подстановка.
-fstack-check  -  Активировать проверку состояния стека.
-gnato  -  Активация прочих проверок, которые обычно не используются по умолчанию, включая проверку численного переполнения и проверку доступа до проверки элаборации.
-gnatp  -  Подавить все проверки.
-gnatq  -  При обнаружении ошибки синтаксического разбора, попытаться осуществить семантическую проверку.
-gnatP  -  Включение опроса. Это требуется на некоторых системах (в частности, для Windows NT) для осуществления асинхронного принудительного прекращения и способности асинхронной передачи управления.
-gnatR  -  Вывести информацию о представлении описанных типов массивов и записей.
-gnats  -  Выполнить синтаксическую проверку.
-gnatt  -  Сгенерировать выходной файл дерева.
-gnatT nnn  -  Установить квант времени (time slice) в указанное число миллисекунд.
-gnatu  -  Вывести список модулей текущей компиляции.
-gnatU  -  Обозначить все сообщения об ошибках уникальной строкой "error:".
-gnatv  -  Установить "многословный" режим. Выполняется полный вывод сообщений об ошибках с выводом строк исходного текста на stdout.
-gnatwm  -  Установить режим выдачи предупредительных сообщений. Где m=s,e,l соответственно означает: подавление сообщений (suppress), трактовать как ошибку (treat as error), предупреждения элаборации (elaboration warnings).
-gnatWe  -  Установить кодировку для wide character (e=n/h/u/s/e/8).
-gnatx  -  Подавление генерации информации о перекрестных ссылках.
-gnatwm  -  Режим предупреждающих сообщений.
-gnaty  -  Включение встроенной проверки стиля.
-gnatzm  -  Генерация и компиляция распределенных "заглушек". Где, m=r/c "заглушка" приемника (receiver)/вызова (caller).
-gnat83  -  Установить принудительные ограничения Ada 83.
-gnat95  -  Установить стандартный режим Ada 95.

3.3.1.1 Проверка ошибок во время выполнения программы

Ада предоставляет обширные возможности для проверки ошибок во время выполнения программы. По умолчанию, GNAT отключает некоторые проверки для повышения скорости выполнения программы. Для включения всех проверок, необходимо использовать опции -gnato -gnatE. Для того чтобы отключить все проверки, необходимо использовать опцию -gnatp.

3.3.1.2 Проверка ошибок в исходном тексте без компиляции

Если вы используете версию GNAT 3.10p, то для проверки ошибок в исходном тексте программы, без выполнения фактической компиляции исходных текстов, можно использовать утилиту gnatf. Для более новых версий GNAT, начиная с версии 3.11p, для проверки ошибок в исходном тексте программы без компиляции, можно использовать команду gcc с опцией -gnatc.

3.3.1.3 Обнаружение большого количества ошибок при компиляции

В случае обнаружения очень большого количества ошибок компиляции в исходном тексте, может оказаться полезным перенаправление вывода сообщений об ошибках в отдельный файл (например, путем использования gcc ... 2> temp.out). После этого, содержимое такого файла с сообщениями об ошибках может быть исследовано с помощью соответствующих средств системы.

3.3.2 Связывание Ада-программы

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

Правила Ады не позволяют скомпоновать подобную программу. Например, если два каких-либо клиентских модуля используют различные версии одного и того же пакета, то выполнить построение программы, которая одновременно включает в себя оба этих модуля, не возможно. Такие правила принудительно навязываются редактором связей GNAT (gnatbind), который также осуществляет определение последовательности элаборации в соответствии с требованиями языка Ада.

Запуск редактора связей GNAT выполняется после того как созданы все объектные файлы, которые необходимы для компоновки результирующей программы. При запуске, редактор связей gnatbind получает имя головного модуля программы и путем чтения соответствующих ALI-файлов определяет перечень требуемых для компоновки этой программы модулей. При обнаружении попытки скомпоновать программу из несогласованных версий объектных файлов или при отсутствии допустимой последовательности элаборации редактор связей gnatbind выдает соответствующие сообщения об ошибках.

В случае отсутствия ошибок, редактор связей gnatbind осуществляет генерацию главного файла программы (по умолчанию, генерируется исходный текст на языке Ада), который содержит вызовы процедур элаборации для компилируемых модулей, которые нуждаются в элаборации, с последующим вызовом головной программы. В результате компиляции этого файла с исходным текстом генерируется объектный файл главной программы. Имя главного файла программы, который генерируется редактором связей gnatbind, имеет следующий вид: b~xxx.adb, а соответствующий ему файл спецификации - b~xxx.ads, - где xxx является именем головного модуля программы.

В заключение, для компоновки результирующей исполняемой программы, используется компоновщик gnatlink, которому предоставляется объектный файл главной программы, полученный на этапе связывания, а также все объектные файлы модулей Ады, которые необходимы для компоновки результирующей исполняемой программы.

3.3.2.1 Опции редактора связей gnatbind

Программа gnatbind является редактором связей (binder) системы компилятора GNAT. Она принимает следующие опции командной строки, которые позволяют непосредственно управлять процессом связывания:

-aO  -  Определяет каталог в котором будет производиться поиск *.ALI-файлов.
-aI  -  Определяет каталог в котором будет производиться поиск файлов с исходными текстами.
-A  -  Генерировать программу редактора связей на Аде (установлено по умолчанию).
-b  -  Генерировать краткие сообщения в stderr даже когда установлен режим многословных (verbose) сообщений.
-c  -  Только проверка, генерация выходного файла редактора связей отсутствует.
-C  -  Генерировать программу редактора связей на C.
-e  -  Выводить полный список зависимостей последовательности элаборации.
-E  -  Сохранять обратную трассировку в точках возникновения исключений для целевых платформ которые ее поддерживают. Действует по умолчанию, с нулевыми затратами производительности для механизма исключений. В настоящее время, опция поддерживается только для Solaris, Linux и Windows на платформе ix86.

Для Solaris и Linux необходимо явное использование флага -funwind-tables для gcc (gnatgcc), при компиляции каждого файла приложения. Дополнительная информация находится в пакетах GNAT.Traceback и GNAT.Traceback.Symbolic.

Чтобы активировать действие этой опции для Windows нет необходимости в использовании дополнительных опций, однако нельзя использовать флаг -fomit-frame-pointer для gnatgcc.

-f  -  Полная семантика элаборации, в соответствии с требованиями стандарта.
-h  -  Вывод справочного сообщения (help) об использовании.
-I  -  Определяет каталог для поиска файлов с исходными текстами и *.ALI-файлов.
-I-  -  Не производить поиск файлов с исходными текстами в текущем каталоге, откуда gnatbind был запущен, и не производить поиск *.ALI-файлов в каталогах указанных в командной строке.
-l  -  Отобразить выбранный порядок элаборации.
-Mxyz  -  Переименовать сгенерированную главную программу из main в xyz.
-mn  -  Ограничить число обнаруженных ошибок до n (1-999).
-n  -  Главная программа отсутствует.
-nostdinc  -  Не производить поиск файлов с исходными текстами в системных каталогах по умолчанию.
-nostdlib  -  Не производить поиск библиотечных файлов в системных каталогах по умолчанию.
-o file  -  Указывает имя file для выходного файла (по умолчанию имя выходного файла задается как b~xxx.adb). Примечательно, что при использовании этой опции компоновка приложения должна быть выполнена вручную, то есть, компоновщик gnatlink не может быть использован автоматически.
-O  -  Вывод списка объектов.
-p  -  Пессиместический (худший случай) порядок элаборации.
-s  -  Требуется присутствие всех файлов с исходными текстами.
-static  -  Выполнить компоновку приложения со статическими библиотеками времени выполнения GNAT.
-shared  -  Выполнить компоновку приложения с динамически связываемыми библиотеками времени выполнения GNAT, если они доступны.
-t  -  Допускать ошибку метки времени создания и другие ошибки целостности/согласованности.
-Tn  -  Установить значение кванта времени (time slice) в n миллисекунд. Нулевое значение подразумевает отсутствие квантования по времени, а также указывает могозадачному окружению времени выполнения на необходимость максимального соответствия требованиям приложения D (Annex D) RM.
-v  -  Режим многословных (verbose) сообщений. Осуществляет вывод сообщений об ошибках, заголовков и общий отчет на stdout.
-wx  -  Установка режима предупредительных (warning) сообщений.
(x=s/e для подавления / для трактования как ошибки).
-x  -  Исключить проверку целостности/согласованности для файлов с исходными текстами (проверка выполняется только для объектных файлов).
-z  -  Главная подпрограмма отсутствует.

Следует заметить, что данный список опций может быть получен при запуске программы редактора связей gnatbind без аргументов.

3.3.2.2 Правила поиска файлов для gnatbind

Программа редактора связей gnatbind принимает имя ALI-файла как аргумент и нуждается в указании файлов с исходными текстами и других ALI-файлов для проверки целостности и согласованности всех объектов проекта.

При поиске файлов с исходными текстами используются те же правила, которые используются для gcc (gnatgcc). Для ALI-файлов используются следующие правила поиска:

  1. Каталоги с ALI-файлами, указанные в командной строке, если не указана опция -I-.
  2. Все каталоги с ALI-файлами, указанные в командной строке с помощью опции -I, в соответствии с порядком указания каталогов.
  3. В каждом каталоге, который перечислен в значении переменной окружения ADA_OBJECTS_PATH. Значение этой переменной окружения строится также как значение переменной окружения PATH: список каталогов разделенных двоеточием.
  4. Содержимое файла ada_object_path, который является составной частью инсталляции GNAT и используется для хранения информации о стандартных библиотеках, таких как GNAT Run Time Library (RTL) пока в командной строке не указана опция -nostdlib.

Опция -I редактора связей gnatbind используется для указания пути поиска как для файлов с исходными текстами, так и для библиотечных файлов. Чтобы указать путь поиска только для файлов с исходными текстами необходимо использовать опцию -aI, а при необходимости указания пути поиска только для библиотечных файлов необходимо использовать опцию -aO. Это подразумевает, что для редактора связей gnatbind, указание опции -Idir будет эквивалентно одновременному указанию опций -aIdir и -aOdir. Редактор связей gnatbind генерирует файл связывания (файл с исходным текстом на языке C) в текущем рабочем каталоге.

Пакеты Ada, System и Interfaces совместно со своими дочерними модулями, а также пакет GNAT совместно со своими дочерними модулями, которые содержат множество дополнительных библиотечных функций, формируют окружение времени выполнения реализации системы компилятора GNAT (GNAT Run-Time Library). Исходные тексты для этих модулей необходимы компилятору и храняться в одном каталоге. ALI-файлы и объектные файлы, которые сгенерированы при компиляции библиотеки времени выполнения (RTL), необходимы редактору связей gnatbind и компоновщику gnatlink. Эти файлы сохраняются с одном каталоге, как правило отличном от каталога в котором храняться файлы с исходными текстами. При обычной инсталляции, нет необходимости в спецификации этих каталогов при выполнении компиляции или связывания (binding). Обнаружение этих файлов возможно как при использовании переменных окружения, так и при использовании встроенных соглашений по умолчанию.

В дополнение к упрощению доступа к библиотеке времени выполнения (RTL), основным предназначением использования путей поиска является компиляция исходных текстов из различных каталогов. Это позволяет сделать окружение разработки более гибким.

3.3.3 Компоновка проекта

3.3.3.1 Компоновщик gnatlink

Компоновщик gnatlink используется для компоновки Ада-программ и построения исполняемых файлов. Эта простая программа вызывает компоновщик системы (через команду gcc/gnatgcc) и предоставляет ему корректный список ссылок на объектные и библиотечные файлы. Программа gnatlink выполняет автоматическое определение списка необходимых файлов для сборки Ада-программы. Для определения этого списка файлов gnatlink использует файл сгенерированный редактором связей gnatbind.

Команда запуска компоновщика gnatlink имеет следующий вид:


$ gnatlink [switches] mainprog[.ali] [non-Ada objects] [linker options]

В данном случае, файл mainprog.ali является ALI-файлом главной программы. Расширение имени файла .ali может не указываться, поскольку такое расширение имени файла подразумевается по умолчанию. Из этой команды компоновщик gnatlink определяет соответствующий файл b~mainprog.adb, который генерируется редактором связей gnatbind, и, используя информацию из этого файла, вместе со списком не Ада-объектов и опций компоновщика, конструирует команду для запуска компоновщика системы, в результате выполнения которой выполняется построение результирующего исполняемого файла.

Аргументы команды, которые следуют за mainprog.ali передаются компоновщику без какой-либо дополнительной интерпретации. Обычно такие аргументы содержат имена объектных файлов модули которых написаны на других языках программирования, а также ссылки на библиотечные файлы которые необходимы для модулей написанных на других языках программирования или используются директивами компилятора pragma Import в модулях Ада-программы.

Список linker options (опции компоновщика) - это не обязательный список опций, которые специфичны для компоновщика, По умолчанию, в качестве компоновщика используется gcc (gnatgcc), который вызывает соответствующий системный компоновщик, обычно называемый ld. При этом, как обычно, могут быть представлены стандартные опции компоновщика, такие как -lmy_lib или -Ldir. Для опций, которые не распознаются gcc (gnatgcc) как опции компоновщика должны использоваться -Xlinker или -Wl,. Для получения более детальной информации необходимо обратиться к документации на GCC. Примером того как выполнить генерацию компоновщиком файла-карты (linker map file), подразумевая, что используется системный компоновщик ld, может служить следующее:


$ gnatlink my_prog -Wl,-Map,MAPFILE

Компоновщик gnatlink определяет список объектов, необходимых для Ада-программы, и предваряет их списком объектов передаваемых компоновщику. Кроме того, gnatlink собирает любые аргументы установленные директивой компилятора pragma Linker_Options и добавляет их к списку аргументов передаваемых компоновщику системы.

3.3.3.2 Опции компоновщика gnatlink

Следующий список перечисляет опции которые допускается использовать с компоновщиком gnatlink:

-A  -  Указывает gnatlink, что сгенерированный редактором связей gnatbind код является Ада-кодом. Это принимается по умолчанию.
-C  -  Указывает gnatlink, что сгенерированный редактором связей gnatbind код является C-кодом.
-g  -  Опция включения отладочной информации, использование которой приводит к тому, что Ада-файл редактора связей gnatbind (b~mainprog.adb) будет скомпилирован с опцией -g. Дополнительно, при указании этой опции, редактор связей gnatbind не будет удалять файлы b~mainprog.adb, b~mainprog.o и b~mainprog.ali, которые удаляются в случае отсутствия опции -g.

Та же самая процедура выполняется при генерации редактором связей gnatbind C-файла, в результате указания для редактора связей опции -C. В этом случае файлы, которые генерирует редактор связей gnatbind, будут иметь следующие имена: b_mainprog.c и b_mainprog.o.

-n  -  Не выполнять компиляцию файла сгенерированного редактором связей gnatbind. Это может быть использовано при перезапуске компоновщика с различными опциями, но при этом нет необходимости выполнять перекомпиляцию файла, который сгенерирован редактором связей gnatbind.
-v  -  Использование этой опции приводит к выводу дополнительной информации, включая полный список подключаемых объектных файлов (такой режим также называют "многословным"). Эта опция полезна когда необходимо видеть множество объектных файлов используемых на этапе компоновки проекта.
-v -v  -  "Очень многословный режим". Такой режим указывает, что компилятор, при компиляции файла который сгенерирован редактором связей gnatbind, и системный компоновщик должны работать в "многословном" режиме.
-o exec-name  -  exec-name указывает альтернативное имя для генерируемого исполняемого файла программы. Если эта опция не указана, то имя исполняемого файла программы будет таким же как и имя головного модуля. Например, команда
gnatlink try.ali
будет создавать исполняемый файл с именем try.
-b target  -  Компиляция программы для запуска на платформе target, при этом target определяет имя системной конфигурации. Для выполнения этого, необходимо наличие построенного кросс-компилятора GNAT, если платформа target не является хост-системой.
-Bdir  -  Загрузить исполняемый файл компилятора (например, gnat1 - Ада-компилятор) из каталога dir, вместо каталога по умолчанию. Эта опция может быть использована только при наличии множества версий компилятора GNAT. Вместо этой опции могут быть использованы опции -b или -V.
--GCC=compiler_name  -  Эта опция указывает программу compiler_name, которая будет использована для компиляции файла сгенерированного редактором связей gnatbind. По умолчанию - используется программа gcc (gnatgcc). Если указание compiler_name содержит пробелы или другие разделительные символы, то compiler_name необходимо заключать в кавычки. В качестве примера, --GCC="foo -x -y" указывает gnatlink, что в качестве компилятора необходимо использовать foo -x -y. Примечательно, что опция -c всегда вставляется после имени команды. Таким образом, показанный выше пример команды компилятора, которая будет использована gnatlink, в результате, будет иметь вид foo -c -x -y.
--LINK=name  -  Данная опция указывает имя name используемого компоновщика системы. Это удобно при работе с программами части которых написаны на разных языках программирования, например, c++ требует использования своего собственного компоновщика. Когда эта опция не указана, то используется имя компоновщика по умолчанию - gcc (gnatgcc).

3.3.4 Утилита gnatmake

Как уже было показано ранее, утилита gnatmake используется для компиляции Ада-программ. Например:


gnatmake main.adb

Она осуществляет проверку всех пакетов от которых зависит программа main.adb и автоматически компилирует любой пакет, который нуждается в компиляции или перекомпиляции. После завершения процесса компиляции утилита gnatmake автоматически выполняет процесс связывания и компоновки, для получения, в результате, исполняемого файла программы.

Бывают случаи, когда необходимо выполнить только компиляцию проекта и не выполнять связывание и компоновку. Это можно сделать используя опцию -n:


gnatmake -n main.adb

3.3.4.1 Опции gnatmake

В команде запуска утилиты gnatmake могут быть использованы различные опции, которые управляют процессом сборки проекта. Следующий список перечисляет опции, которые допускается использовать с утилитой gnatmake:

--GCC=compiler_name  -  Указывает программу используемую для компиляции. По умолчанию используется gcc (gnatgcc).

Если compiler_name содержит пробелы или другие разделительные символы, то compiler_name должно заключаться в кавычки.

Как пример, --GCC="foo -x -y" указывает утилите gnatmake, что в качестве команды запуска компилятора необходимо использовать команду foo -x -y.

Примечательно, что опция -c всегда вставляется после имени команды. Таким образом, показанный выше пример команды компилятора, которая будет использована утилитой gnatmake, в результате, будет иметь вид foo -c -x -y.

--GNATBIND=binder_name  -  Указывает программу используемую в качестве редактора связей. По умолчанию используется редактор связей gnatbind.

Если binder_name содержит пробелы или другие разделительные символы, то binder_name должно заключаться в кавычки.

Как пример, --GNATBIND="bar -x -y" указывает утилите gnatmake, что в качестве команды запуска редактора связей необходимо использовать команду bar -x -y.

Опции редактора связей, которые обычно принимаются утилитой gnatmake для передачи их редактору связей, будут добавлены после bar -x -y.

--GNATLINK=linker_name  -  Указывает программу используемую в качестве компоновщика. По умолчанию используется компоновщик gnatlink.

Если linker_name содержит пробелы или другие разделительные символы, то linker_name должно заключаться в кавычки.

Как пример, --GNATLINK="lan -x -y" указывает утилите gnatmake, что в качестве команды запуска компоновщика необходимо использовать команду lan -x -y.

Опции компоновщика, которые обычно принимаются утилитой gnatmake для передачи их компоновщику, будут добавлены после lan -x -y.

-a  -  Эта опция указывает утилите gnatmake, что в процессе построения приложения, необходимо выполнять анализ всех файлов, включая внутренние системные файлы GNAT (например, предопределенные файлы Ада-библиотеки), а также все заблокированные файлы. Заблокированными файлами являются файлы у которых запись в соответствующие ALI-файлы запрещена.

По умолчанию, утилита gnatmake не выполняет анализ таких файлов, поскольку подразумевается, что внутренние системные файлы GNAT обновлены, а также то, что все заблокированные файлы правильно установлены. Примечательно, что если для таких файлов существует какая-либо ошибка инсталляции, то она может быть обнаружена с помощью редактора связей. Реально, необходимость использования этой опции может возникнуть только в случае если вы непосредственно работаете с исходными текстами GNAT.

При необходимости полной перекомпиляции исходных текстов приложения, включая исходные тексты файлов библиотеки времени выполнения, может также оказаться полезным использование опции -f совместно со специальными директивами управления конфигурацией компилятора, подобными не стандартной директиве компилятора Float_Representation.

По умолчанию, gnatmake -a выполняет компиляцию всех внутренних файлов GNAT путем использования gnatgcc -c -gnatg, а не gnatgcc -c.

-c  -  Выполнить только компиляцию и не выполнять связывание и компоновку.

Выполняется по умолчанию, если корневой модуль, который специфицирован как file_name не является головным модулем.

В другом случае, утилита gnatmake будет пытаться выполнить связывание и компоновку, пока все объекты не будут обновлены и результирующий выполняемый файл не будет новее объектов.

-f  -  Принудительная перекомпиляция.

Выполнить перекомпиляцию всех файлов с исходными текстами, даже в случае если некоторые объектные файлы обновлены, но при этом не выполнять перекомпиляцию предопределенных внутренних файлов GNAT или заблокированных файлов (файлы для которых запрещена запись в соответствующие ALI-файлы), пока не указана опция -a.

-i  -  В обычном режиме, утилита gnatmake выполняет компиляцию всех объектных файлов и ALI-файлов только в текущем каталоге. При использовании опции -i существующие в различных каталогах объектные и ALI-файлы будут соответственно переписаны. Это подразумевает, что утилита gnatmake способна правильным образом выполнять автоматическую обработку и обновление файлов большого проекта, у которого различные файлы размещаются в различных каталогах. При этом, если объектные и ALI-файлы не будут обнаружены в путях поиска объектных файлов Ады, то будут созданы новые объектные и ALI-файлы в каталоге, который содержит файлы с компилируемыми исходными текстами. Если желательна другая организация, когда объектные файлы и файлы с исходными текстами храняться в отдельных каталогах, может быть использован удобный прием при котором в требуемых каталогах создаются ALI-файлы "заглушки". При обнаружении таких файлов "заглушек", утилита gnatmake будет вынуждена выполнить перекомпиляцию соответствующих файлов с исходными текстами, и она поместит результирующие объектные и ALI-файлы в те каталоги, в которых были обнаружены файлы "заглушки".
-jn  -  Использовать n процессов для выполнения перекомпиляции.

В этом случае, на многопроцессорной системе, компиляция будет выполняться параллельно. В случае ошибок компиляции, сообщения от различных процессов компиляции могут быть получены в разбросанном порядке (однако gnatmake в завершении представит полностью упорядоченный список ошибочных компиляций). Если это вызывает проблемы, то следует перезапустить процесс сборки установив n в 1, для получения более чистого списка сообщений.

-k  -  Продолжать выполнение сборки проекта после обнаружения ошибки компиляции настолько долго, насколько это возможно.

При использовании этой опции, в случае ошибок компиляции, после завершения своей работы, утилита gnatmake выдает список файлов с исходными текстами при компиляции которых были обнаружены ошибки.

-m  -  Эта опция указывает, что необходимо выполнить минимально необходимое количество перекомпиляций.

В этом режиме gnatmake игнорирует различие меток времени вызванное только модификацией исходных текстов при котором производилось только добавление/удаление комментариев, пустых строк, символов пробела или табуляции.

Это подразумевает, что если в исходном тексте изменения затронули только комментарии или исходный текст был только переформатирован, то использование этой опции указывает утилите gnatmake, что нет необходимости выполнять перекомпиляцию файлов, зависимых от этого файла.

-M  -  Проверка согласованности обновлений всех объектов.

В случае согласованности обновлений вывод взаимозависимости объектов производится на stdout в форме которая позволяет непосредственное использование этой информации в файле Makefile для сборки проекта под управлением программы GNU make.

По умолчанию, префиксом для каждого файла с исходным текстом является имя каталога (относительное или абсолютное) в котором этот файл с исходным текстом находится. Такое префиксное имя будет соответствовать тому, что было указано с помощью различных опций -aI и -I.

При использовании gnatmake -M -q, на stdout будут выводиться только имена файлов с исходными текстами, без относительных путей поиска файлов в каталогах.

Если указана только опция -M, то вывод зависимостей от внутренних системных файлов GNAT не производится. Как правило, это отображает именно ту информацию которая необходима.

Если дополнительно указать опцию -a, то тогда будет отображаться информация о зависимости от внутренних системных файлах GNAT.

Примечательно, что зависимость от объектов которые расположены во внешних Ада-библиотеках (см. опции -aLdir) никогда не отображается.

-n  -  Выполнить только проверку согласованности обновлений всех объектов, и не выполнять компиляцию, связывание и/или компоновку приложения.

Если при выполнении такой проверки обнаружена не согласованность обновлений, то будет показано полное имя первого файла который нуждается в перекомпиляции.

Многократное повторное использование этой опции, с последующей компиляцией показанных файлов с исходными текстами, в результате приведет к перекомпиляции всех требуемых модулей.

-o exec_name  -  Определение имени для генерируемого исполняемого файла приложения. При этом имя исполняемого файла будет exec_name.

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

-q  -  Устанавливает "молчаливый" режим работы утилиты gnatmake.

При обычном режиме (без использования этой опции) утилита gnatmake отображает все выполняемые ею команды.

-s  -  Выполнить перекомпиляцию, если опции компилятора были изменены при последней компиляции.

Все опции компиляции, кроме -I и -o, рассматриваются в следующем порядке: порядок следования между различными опциями (которые заданы первыми буквами) игнорируется, но выполняется анализ порядка следования между одинаковыми опциями.

Например, указание опций -O -O2 будет отличаться от -O2 -O, но указание опций -g -O эквивалентно -O -g.

-v  -  Устанавливает "многословный" режим при котором утилита gnatmake отображает смысл причины выполнения всех необходимых перекомпиляций.
-z  -  Указывает на отсутствие главной подпрограммы.

В результате, выполняется связывание и компоновка программы даже в случае когда имя модуля, указанное в команде запуска утилиты gnatmake, является именем пакета.

Результирующий исполняемый файл будет запускать на выполнение подпрограммы элаборации пакета, а его завершение будет запускать на выполнение подпрограммы очистки.

Опции gcc
(gnatgcc)
 -  Опция -g или любая другая опция заданная символом верхнего регистра (кроме -A или -L) или любая опция, которая описывается более чем одним символом будет передана gnatgcc (например, -O, -gnato и т.д.).

3.3.4.2 Указание путей поиска файлов для gnatmake

Кроме показанных ранее опций, утилита gnatmake поддерживает опции указания путей поиска для файлов с исходными текстами и библиотечных файлов:

-aIdir  -  При поиске файлов с исходными текстами, поиск файлов должен также осуществляться в каталоге dir.
-aLdir  -  Предположим, что в каталоге dir расположена дополнительная внешняя Ада-библиотека. Эта опция указывает утилите gnatmake на то, что нет нужды выполнять перекомпиляцию модулей чьи .ali файлы расположены в каталоге dir. Это позволяет не иметь тела (реализацию) для модулей в каталоге dir. Однако, при этом остается необходимость в указании места расположения файлов со спецификациями этих модулей с помощью опций -aIdir или -Idir.

Примечание: эта опция предусмотрена для совместимости с предыдущими версиями утилиты gnatmake. Наиболее простым способом, который приводит к исключению анализа стандартной библиотеки, является блокировка ALI-файлов этой библиотеки (запрещение записи в ALI-файлы).

-aOdir  -  При поиске библиотечных и объектных файлов, поиск должен также осуществляться в каталоге dir.
-Adir  -  Эквивалентно -aLdir -aIdir.
-Idir  -  Эквивалентно -aOdir -aIdir.
-I-  -  Не выполнять поиск файлов с исходными текстами в каталогах с исходными текстами, которые указаны в командной строке.

Не выполнять поиск объектных и ALI-файлов в каталоге из которого утилита gnatmake была запущена.

-Ldir  -  Добавить каталог dir к списку каталогов в которых компоновщик будет осуществлять поиск библиотечных файлов.

Это эквивалентно использованию -largs -Ldir.

-nostdinc  -  Не осуществлять поиск файлов с исходными текстами в системном каталоге по умолчанию.
-nostdlib  -  Не осуществлять поиск библиотечных файлов в системном каталоге по умолчанию.

3.3.4.3 Управление режимами gnatmake

Опции управления режимами gnatmake позволяют использовать опции командной строки, которые будет непосредственно переданы компилятору, редактору связей или компоновщику. Эффект использования опций управления режимом приводит к тому, что последующий список опций, вплоть до завершения всего списка или до следующей опции управления режимом, будет интерпретироваться как опции, которые необходимо передать определенному компоненту системы GNAT (компилятору, редактору связей или компоновщику).

-cargs switches  -  Опции компилятора. Здесь, switches представляет список опций которые допустимо использовать с gcc (gnatgcc). Этот список опций будет передаваться компилятору каждый раз когда утилита gnatmake проходит этап компиляции.
-bargs switches  -  Опции редактора связей. Здесь, switches представляет список опций которые допустимо использовать с gcc (gnatgcc). Этот список опций будет передаваться редактору связей каждый раз когда утилита gnatmake проходит этап связывания.
-largs switches  -  Опции компоновщика. Здесь, switches представляет список опций которые допустимо использовать с gcc (gnatgcc). Этот список опций будет передаваться компоновщику каждый раз когда утилита gnatmake проходит этап компоновки.

3.3.4.4 Примечания для командной строки gnatmake

Здесь предоставляются некоторые дополнтельные сведения, которые могут быть полезны при работе с командной строкой для утилиты gnatmake.

3.3.5 Связывание и компоновка, утилита gnatbl

Бывают случаи, когда необходимо выполнить сборку проекта части которого написаны на других языках программирования. В таких ситуациях, компиляция выполняется с помощью различных компиляторов, а этапы связывания и компоновки могут быть выполнены автоматически за один шаг. Для этого можно использовать утилиту gnatbl, которая автоматически вызывает редактор связей gnatbind и компоновщик gnatlink, соответственно выполняя связывание и компоновку проекта.

3.4 Сравнение моделей компиляции

3.4.1 Модели компиляции GNAT и C/C++

Модель компиляции GNAT очень похожа на модель компиляции, которая традиционна для языков программирования C/C++. Файлы спецификации могут рассматриваться как соответствующие файлы заголовков (*.h) C/C++. Также как и в случае с файлами заголовков C/C++, нет необходимости выполнять компиляцию файлов спецификаций. Файлы спецификаций компилируются только в случае их непосредственного использования. Спецификатор with обладает эффектом, который подобен использованию директивы #include в C/C++.

При этом существует одно примечательное отличие: в Аде можно выполнять раздельную компиляцию спецификации с целью осуществления ее семантической и синтаксической проверки. Это не всегда возможно для файлов заголовков C/C++ поскольку они являются фрагментами программы, которая использует иные семантические и синтаксические правила.

Еще одним значительным отличием является необходимость запуска редактора связей gnatbind, на который возложены две важных функции. Во-первых, редактор связей осуществляет проверку согласованности отдельных компонентов программы. В C/C++ такая проверка согласованности различных частей программы, как правило, возлагается на файл управляющий сборкой проекта (Makefile). Таким образом, редактор связей gnatbind не позволяет скомпоновать результирующую программу из несогласованных компонентов при обычном режиме использования компилятора, что обеспечивает соответствие стандартным требованиям Ады.

Второй, весьма важной задачей, которая возложена на редактор связей, является обработка и анализ очередности элаборации отдельных компонентов программы. Следует заметить, что обработка очередности элаборации присутствует также в C++. Считается, что в C++ она осуществляется автоматически и поэтому о ней, как правило, не упоминается. Однако фактическая очередность элаборации самостоятельных объектных модулей C++ определяется порядком компоновки объектных модулей компоновщиком. Преимуществом подхода C++ является простота, но при этом программист не имеет реального контроля над процессом элаборации. В результате, в случаях когда редактор связей gnatbind может указать на отсутствие корректного порядка элаборации и, следовательно, не возможность компоновки результирующей программы, компилятор C++ выполнит построение программы не работоспособность которой будет обнаружена только во время выполнения.

3.4.2 Модель компиляции GNAT и общая согласованная Ада-библиотека

Эта информация может оказаться полезной для тех программистов, которые ранее использовали какой-либо другой Ада-компилятор использующий традиционную модель общей согласованной Ада-библиотеки, как описано в "Руководстве по языку программирования Ада 95".

Система компилятора GNAT не использует традиционную модель общей согласованной Ада-библиотеки. Вместо этого, GNAT использует множество файлов с исходными текстами совокупность которых играет роль общей библиотеки. Компиляция Ада-программы не генерирует никакой централизованной информации. Вместо этого в результате компиляции генерируются объектные файлы и ALI-файлы, которые предназначены для обработки редактором связей gnatbind и компоновщиком gnatlink. В традиционной Ада-системе компилятор читает информацию не только из файла с исходным текстом, который компилируется, но и из центральной библиотеки, что подразумевает зависимость текущей компиляции от того, что было скомпилировано ранее. В частности:

В системе компилятора GNAT, компиляция одного модуля никогда не влияет на компиляцию каких-либо других модулей поскольку компилятор всегда читает только файлы с исходным текстом. Только изменение файлов с исходными текстами может повлиять на результаты компиляции. В частности:

Наиболее существенным результатом таких различий является то, что для GNAT последовательность выполнения компиляции не имеет значения. Не существует ситуации при которой для компиляции чего-либо необходимо выполнить какую-либо другую, предварительную компиляцию. То что в традиционной Ада-системе с общей библиотекой проявляется как требование строго определенной последовательности компиляции для GNAT проявляется как простая зависимость файлов с исходными текстами. Другими словами, существует только набор правил, который указывает какие файлы с исходными текстами должны быть представлены при компиляции файла.

3.5 Директивы конфигурации

Согласно "Руководства по языку программирования Ада 95" существует набор директив компилятора, которые предназначены для управления конфигурацией среды компиляции Ада-системы. Такие директивы называют директивами конфигурации. Кроме того, некоторые директивы определяемые реализацией Ада-системы также являются директивами конфигурации. Примером директивы конфигурации может служить определяемая в реализации GNAT директива Source_File_Name, которая позволяет указывать имена файлов с исходными текстами когда эти имена не соответствуют принятым по умолчанию соглашениям именования для файлов с исходными текстами. Ниже представлен полный перечень директив конфигурации распознаваемых компилятором GNAT:

Ada_83   Normalize_Scalars
Ada_95   Polling
C_Pass_By_Copy   Propagate_Exceptions
Component_Alignment   Queuing_Policy
Discard_Names   Ravenscar
Elaboration_Checks   Restricted_Run_Time
Eliminate   Restrictions
Extend_System   Reviewable
Extensions_Allowed   Source_File_Name
External_Name_Casing   Style_Checks
Float_Representation   Suppress
Initialize_Scalars   Task_Dispatching_Policy
License   Unsuppress
Locking_Policy   Use_VADS_Size
Long_Float   Warnings
No_Run_Time   Validity_Checks

3.5.1 Обработка директив конфигурации

Директивы конфигурации могут присутствовать в начале исходного текста компилируемого модуля, оказывая, таким образом, воздействие только на соответствующий компилируемый модуль. Кроме того, директивы конфигурации могут использоваться для воздействия на всю среду компиляции в целом.

Система компилятора GNAT предусматривает утилиту gnatchop, которая обеспечивает способ автоматической обработки директив конфигурации в соответствии с семантикой компиляции (а именно, для файлов с множеством модулей) описанной в "Руководстве по языку программирования Ада 95". Однако, в большинстве случаев, для общей настройки среды компиляции, предпочтительнее модифицировать содержимое файла gnat.adc, который предназначен для непосредственного хранения директив конфигурации.

3.5.2 Файлы директив конфигурации

В системе компилятора GNAT, среда компиляции определяется текущим каталогом на момент запуска команды компиляции. Этот текущий каталог используется для поиска файла с именем gnat.adc. При обнаружении этого файла, предполагается, что он содержит одну или более директив конфигурации, которые должны быть использованы в текущей компиляции. Однако, если в командной строке команды компиляции присутствует опция -gnatA, то содержимое файла gnat.adc не рассматривается..

Директивы конфигурации могут быть введены в файл gnat.adc как путем запуска утилиты gnatchop для обработки файла с исходным текстом, который состоит только из директив конфигурации, так и с помощью непосредственного редактирования gnat.adc, который является обычным текстовым файлом (последний способ считается более предпочтительным).

В дополнение к gnat.adc для воздействия на среду текущей компиляции может быть дополнительно использован еще один файл содержащий директивы конфигурации. Для указания этого, в командной строке необходимо использовать опцию -gnatecpath. В этом случае, параметр опции "path" должен указывать существующий файл, который состоит только из директив конфигурации. Директивы конфигурации указанного файла будут служить как дополнение к директивам конфигурации, которые расположены в файле gnat.adc (предполагается, что файл gnat.adc присутствует, и не используется опция -gnatA).

Следует заметить, что в командной строке может присутствовать несколько опций -gnatec. Однако, фактическое значение будет иметь только последняя указанная опция.


Copyright (C) А.Гавва V-0.4w май 2004