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

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

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

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

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

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

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

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

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

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

При переносе Ада-программы из среды компилятора который поддерживает другие соглашения по наименованию файлов для создания файлов с исходными текстами, имена которых будут соответствовать соглашениям 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.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) принимает следующие опции командной строки, которые позволяют непосредственно управлять процессом компиляции:

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. Она принимает следующие опции командной строки, которые позволяют непосредственно управлять процессом связывания:

Следует заметить, что данный список опций может быть получен при запуске программы редактора связей 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:

3.3.4 Утилита gnatmake

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

    
    
    gnatmake main.adb
    

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

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

    
    
    gnatmake -n main.adb
    

3.3.4.1 Опции gnatmake

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

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

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

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

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

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:

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