17.7. Компиляция программы
Написанную с помощью экранного редактора программу нужно затем скомпилировать - преобразовать исходный текст к виду, доступному для вычислительной машины (получить машинный код, состоящий из двоичных данных и инструкций процессора), и объединить в одно целое части программы. Здесь же к программе добавляются подпрограммы из стандартных модулей. В результате компиляции будет получена либо программа, находящаяся в оперативной памяти машины, либо программа, размещенная в файле на диске. Файл будет иметь то же имя, что и файл с исходным текстом программы, но с расширением .ЕХЕ. Исключением являются файлы модулей, которые после компиляции получают расширение .TPU.
Компиляция простейших программ, состоящих из одного файла, осуществляется с помощью команды меню Compile| Compile (см. п. 17.5.5) или комбинации клавиш Alt+F9. В этом случае компилируется программа, находящаяся в актив-ном окне редактирования. Эти программы могут включать также файлы типа Include, присоединяемые ключом компилятора ($1 ).
Место размещения скомпилированной программы - в оперативной памяти или на диске - зависит от выбранного параметра, задаваемого командой меню Compile I Destination. Первоначально желательно компилировать программу в оперативную память, т. к. это ускоряет процесс компиляции. Окончательно целесообразно скомпилировать программу на диск с тем, чтобы можно было в дальнейшем запускать ее не из интегрированной среды. Компиляция на диск может потребоваться и в том случае, когда программа слишком велика и не помещается в оперативной памяти.
Сложные программы, использующие модули, компилируются либо с помощью команды меню Compile | Make (этой команде эквивалентна клавиша F9), либо с помощью команды меню Compile | Build. Перед использованиеми этих программ следует предварительно задать имя основного файла, с которого начнется компиляция, с помощью команды меню Compile|Primary file (см. п. 17.5.5).
При использовании команды Compile | Make наряду с компиляцией основного файла компилируются и все другие файлы, которые используются основным файлом и у которых к моменту компиляции был изменен текст. Если же у такого используемого и уже скомпилированного файла не было изменений в тексте с момента его последней компиляции, то он не перекомпилируется. При компиляции с помощью данной команды совсем не обязательно, чтобы основной файл находился в активном окне, более того, он вообще может быть не вызван ни в одно из окон редактирования. Это замечание касается и любого используемого файла. Все эти файлы в этом случае автоматически по мере необходимости вызываются в оперативную память. Если в каком-либо из них во время компиляции будет обнаружена синтаксическая ошибка, этот файл будет отображен на экране дисплея в активном окне редактирования. Будет одновременно указано курсором место ошибки в тексте и выведено сообщение о ней. В какое конкретно окно (старое активное или новое) будет отображен файл, зависит от установленного параметра в селективном списке Source tracking, вызываемого командой меню Options I Environment! Preferences (см. п. 17.5.8).
Использование команды меню Compile | Build отличается от предыдущего случая только тем, что все используемые файлы перекомпилируются безусловно.
Компилятор выявляет ошибки, связанные с нарушением правил написания предложений языка (синтаксические ошибки). При этом компиляция прекращается, выводится сообщение об ошибке, а курсор указывает место в тексте программы, где находится ошибка. Если обнаружена ошибка, объектный файл не создается, ошибку следует устранить, а затем вновь скомпилировать программу.
Если компиляция завершилась успешно, на экран выдается соответствующее сообщение.
Для задания параметров, определяющих режим и условия работы компилятора, можно использовать в тексте программы ключи компилятора. Многие из этих ключей имеют аналоги среди команд меню, при этом ключи, установленные в программе, имеют приоритет над ключами, задаваемыми с помощью ме- ню. Все ключи компилятора можно разбить на три группы: переключающие, ключи параметров и ключи условной компиляции. Ключи компилятора представляют собой своеобразные комментарии, заключенные в обычные фигурные скобки. После открывающей фигурной скобки при задании ключа должен сразу же идти символ $, далее - имя ключа, а затем через один или несколько пробелов -параметр, если он в ключе необходим. Завершается ключ также фигурной скобкой. У переключающих ключей после имени ключа должен стоять символ + или -, означающий, задан или нет данный ключ. Примеры ключей компилятора:
{$F+} - переключающий ключ (задает формирование "дальней" адресации);
{$L ASM.OBJ} - ключ параметра (подключение объектного файла);
{$IFDEF DEBUG} - ключ условной компиляции ("Если происходит отладка...").
17.7.1. Переключающие ключи
Эти ключи задают (знак +) или запрещают (знак -) тот или иной режим компиляции. По диапазону действия эти ключи могут быть глобальными, когда их действие распространяется на всю программу, и локальными, действие которых распространяется только на часть программы. Глобальные ключи могут стоять только в самом начале программы или модуля (перед ними может быть только заголовок, комментарий или другие ключи). Локальные ключи могут располагаться в любом месте программы там, где это необходимо.
Переключающие ключи можно задавать в одну строку, перечисляя их через запятую, но без пробелов, например,
{$N+,E+}
Далее для каждого ключа этой категории приведено краткое описание, его значение по умолчанию, тип, эквивалент среди команд меню.
{$А+/-} - выравнивание по границе машинного слова Если используется ключ {$А+}, данные размером больше одного байта записываются в память начиная с четного адреса. Такое размещение немного увеличивает объем требуемой памяти, но ускоряет процесс работы с данными. При ключе {$А-} данные располагаются начиная с первого свободного адреса. Ключ является глобальным. Более того, если в программе используется несколько файлов, во всех файлах должны быть одинаковые ключи. По умолчанию используется ключ {$А+}. Эквивалент меню - Options| Compiler| Word align data.
{$В+/-} - полное вычисление логических выражений Если используется ключ {$В+}, происходит полное вычисление логических выражений (см. п. 4.4.2). В противном случае (когда используется ключ {$В-}) производится укороченное вычисление. Ключ является локальным. По умолчанию используется ключ {$В-}. Эквивалент меню - Options| Compiler| Complete boolean eval,
{$D+/-} - отладочная информация Если используется ключ {$D+}, фиксируется связь отдельных строк программы с адресами соответствующих кодов скомпилированной программы. Это позво-ляет фиксировать место обнаружения ошибки, использовать возможности интегрированного отладчика (задавать точки останова, выполнять программу по шагам и т. д.). Ключ является глобальным. По умолчанию используется ключ {$D+}. Эквивалент меню - Options | Compiler (Debug infirmation.
{$Е+/-} - эмуляция сопроцессора Если используется ключ {$Е+}, в процессе компоновки программы используется библиотека, позволяющая реализовать функции сопроцессора программным образом, если он отсутствует. Ключ является глобальным. По умолчанию используется ключ {$Е+}. Эквивалент меню - Options|Compiler|Emulation.
{$F+/-} - формирование "дальних" или "ближних" адресов Если используется ключ {$F+}, для подпрограмм формируются "дальние" адреса, состоящие из адреса сегмента и смещения. Если ключ {$F-} - формируются "ближние" адреса, представляющие собой только смещения. Ключ {$F+} эквивалентен директиве far, а ключ {$F-} - директиве near (см. п. 10.5.2). Ключ является локальным. По умолчанию используется ключ {$F-}. Эквивалент меню - Options I Compiler | Force far calls.
{$G+/-} - формирование команд для процессора 80286 Если используется ключ {$G+}, компилятор включает при необходимости инструкции процессора 80286 и эти программы не могут выполняться на процессорах 8086 и 8088. Если используется ключ {$G-}, скомпилированная программа может выполняться на любом процессоре семейства 80x86. Ключ является локальным. По умолчанию используется ключ {$G-}. Эквивалент меню -Options I Compiler 1286 instructions.
{$I+/-} - проверка результата ввода-вывода Если используется ключ {$1+}, при возникновении ошибки ввода-вывода программа прекращает работу. В случае ключа {$1-} при возникновении ошибки ввода-вывода программа не выбрасывается, а код ошибки можно получить с помощью функции IOResult. Ключ является локальным. По умолчанию используется ключ {$1+}. Эквивалент меню - Options|Compiler| I/O checking.
{$L+/-} - включение информации о локальных параметрах модулей Если используется ключ {$L+}, включается информация о локальных параметрах модулей (параметрах исполнительной части модулей). Это позволяет анализировать значения таких параметров и даже модифицировать их при отладке. Действует только совместно с ключом {$D+}. Ключ является глобальным. По умолчанию используется ключ {$L+>. Эквивалент меню Options I Compiler | Local symbols.
{$N+/-} - использование сопроцессора Если используется ключ {$N+}, при компиляции формируются инструкции для сопроцессора 8087/80287. В противном случае операции, выполняемые сопроцессором, реализуются программным путем (не следует путать с эмуляцией сопроцессора - см. ключ {$Е+/-}, когда инструкции сопроцессора реализуются программным образом). Ключ является глобальным. По умолчанию используется ключ {$N-}. Эквивалент меню - Options | CompilerI8087/80287.
{$O+/-} - использование оверлейных структур Применяется в модулях, которые могут использоваться как оверлейные (перезагружаемые). Если используется ключ {$0+}, модуль можно затем использовать как оверлейный, подключая к основной программе ключом {$0 unitname} (см. п. 17.7.2). Ключ {$0+} следует использовать совместно с ключом {$F+} для формирования "дальних" адресов подпрограмм. Ключ является глобальным. По умолчанию используется ключ {$0-}. Эквивалент меню -Options | Compiler| Overlays allowed.
{$P+/-} - использование в качестве параметров массивов открытого типа Эквивалент меню - Options | Compiler | Open parameters.
{$Q+/-} - проверка переполнения при арифметических операциях Эквивалент меню - Options | Compiler | Overflow checking.
{$R+/-} - проверка диапазонов Если используется ключ {$R+}, проверяется допустимость значений переменных порядкового типа, в том числе индексы элементов массивов и строк. Ключ является локальным. По умолчанию используется ключ {$R-}. Эквивалент меню, - Options | Compiler | Range checking.
{$S+/-} - проверка стека. Если используется ключ {$S+}, при каждом обращении к подпрограмме проверяется наличие достаточного места в стеке для локальных параметров. Если такого места нет, программа прекращает работу и выдается сообщение об ошибке. В случае ключа {$S-} эта ситуация приведет к фатальной ошибке в работе системы. Ключ является локальным. По умолчанию используется ключ {$S+}. Эквивалент меню - Options | Compiler | Stack checking.
{$Т+/-} - использование типизированного адресного оператора @ Эквивалент меню - Options | Compiler | Typed @ operator.
{$V+/-} - проверка строковых параметров Если используется ключ {$V+}, при обращении к подпрограмме и передаче ей параметра типа string фактический и формальный параметры должны быть идентичными (см. пп. 9.1 и 10.3). Если же используется ключ {$V-}, формальный и фактический параметры могут быть строками разного типа, в том числе и разной длины. Ключ является локальным. По умолчанию используется ключ {$V+}. Эквивалент меню - Options | Compiler| Strict var-strings.
{$Х+/-} - использование расширенного синтаксиса Если используется ключ {$Х+}, можно обращаться к подпрограмме-функции как к подпрограмме-процедуре. Этот ключ не действует на функции модуля System. Кроме этого наличие ключа {$Х+} позволяет рассматривать переменные типа PChar (см. п. 6.3) как ASCIIZ-строки. Если используется ключ {$Х-}, попытка использовать подпрограмму-функцию как процедуру приведет к ошибке. Переменные типа PChar в этом случае являются указателями на первый (нулевой) символ строки (см. п. 6.3). Ключ является глобальным. По умолчанию используется ключ {$Х+}. Эквивалент меню - Options | Compiler | Extended syntax.
Набор указанных выше ключей может меняться в зависимости от этапа создания программы. На этапе компиляции и отладки целесообразно по возможности включить все проверки, что позволит проще выявить многие ошибки программы. Однако после отладки ряд проверок следует отключить, т. к. многие из них приводят к увеличению размера программы и уменьшению быстродействия.
17.7.2. Ключи параметров
Эти ключи позволяют задавать компилятору те или иные параметры (имена файлов, численные значения).
{$I filename} - включение файла По этому ключу текст из файла с именем filename вставляется в то место программы, где находится этот ключ. Допустимая глубина вложенности - до 15. Если у файла не указано расширение, ищется файл с расширением .PAS. Если в имени файла не указан путь, то он сначала ищется в текущем каталоге, а затем в каталогах, заданных командой меню Options | Directories | Include directories. Этот ключ нельзя использовать внутри любого составного оператора. Ключ является локальным.
{$L filename} - компоновка объектного файла По этому ключу компонуется объектный файл с именем filename к основному файлу. В файле filename находятся подпрограммы, написанные на языке ассемблера и объявленные в основном файле с директивой external. Если у файла не указано расширение, ищется файл с расширением .OBJ. Если в имени файла не указан путь, то он сначала ищется в текущем каталоге, а затем в каталогах, заданных командой меню Options | Directories I Object directories. Ключ является локальным.
{$М stacksize,heapmin,heapmax} - задание размеров памяти С помощью этого ключа задаются размеры элементов памяти: stacksize размер стека (от 1024 до 65520 байт), heapmin минимальный размер динамической памяти (от 0 до 655360 байт), heapmax - максимальный размер динамической памяти (от heapmin до 655360 байт). По умолчанию задаются размеры: {$М 16384,0,655360}. Ключ является глобальным и эквивалентен команде меню Options | Memory sizes.
{$O unitname} - компоновка оверлейного модуля По этому ключу подпрограммы оверлейного модуля с именем unitname компонуются к основной программе. Модуль должен быть скомпилирован с ключом {$O+}. Ключ является локальным и должен стоять в основной программе непосредственно за разделом uses.
17.7.3. Ключи условной компиляции
Ключи условной компиляции позволяют различным образом компилировать программу, включая те или иные фрагменты в зависимости от заданных условий. Это позволяет создавать различные варианты программы (например, для этапа отладки и для окончательного варианта), отличающиеся своими функциями, размером, быстродействием. Эти ключи используются с аргументами, в качестве которых выступают обычно те или иные идентификаторы. Наряду с идентификаторами, задаваемыми пользователем, существует четыре стандартных имени, которые можно использовать в ключах условной компиляции:
VER70 - используется Turbo Pascal 7.0;
MSDOS - используется стандартный режим операционной системы MS DOS;
CPU86 - используется процессор семейства 80x86;
CPU87 - используется сопроцессор семейства 80x87.
Ключи условной компиляции можно вкладывать друг в друга, максимальное число уровней вложенности - 16.
{$DEFINE name} - определение идентификатора для условной компиляции По этому ключу задается идентификатор name, который затем можно использовать в ключе условной компиляции {$IFDEF name} или {$IFNDEF name}.
{$UNDEF name} - прекращение действия идентификатора для условной компиляции По этому ключу прекращается действие идентификатора name, используемого в ключах {$IFDEF name} и {$IFNDEF name}.
{$IFDEF name} - компиляция при определенном идентификаторе name По этому ключу осуществляется компиляция последующих операторов программы до ключа {$ELSE} или {$ENDIF}, если перед этим был определен идентификатор name ключом {$DEFINE name}. Этот ключ похож на оператор IF, но выполняется во время компиляции, а не во время работы программы.
{$IFNDEF name} - компиляция при неопределенном идентификаторе name По этому ключу осуществляется компиляция последующих операторов программы вплоть до ключа {$ELSE} или {$ENDIF}, если не был определен идентификатор name ключом {$DEFINE name}.
{$IFOPT switch} - компиляция при задании ключа switch По этому ключу осуществляется компиляция последующего фрагмента программы вплоть до ключа {$ELSE} или {$ENDIF}, если задан ключ switch; switch задает имя ключа и его состояние (+ или -).
{$ELSE} - алтернативная секция ключам {$IFDEF name}, {$IFNDEF name},{$IFOPT switch} По этому ключу осуществляется компиляция последующего фрагмента программы вплоть до ключа {$ENDIF}, если не выполняется условие предыдущего ключа {$IFDEF name}, {$IFNDEF name} или {$IFOPT switch}. Ключу {$ELSE} должен обязательно предшествовать один из этих операторов. Этот ключ похож на секцию ELSE оператора IF, но выполнение происходит во время компиляции, а не во время работы программы.
{$ENDIF} - завершение условной компиляции Этот ключ устанавливает нижнюю границу действия любого условного ключа.
Пример. Пример использования ключей условной компиляции.
{$DEFINE Debug} {Задание идентификатора для условной компиляции}
{$IFDEF Debug} {Компиляция при отладке}
{$G+,N+,R+} {Ключи при отладке}
{$ELSE} {Компиляция после отладки}
{$D-,E-,L-,N+,S-,V-} {Ключи после отладки}
{$ENDIF}
В этом примере для этапа отладки задаются ключи, с помощью которых можно осуществить различные проверки, после отладки проверки отключаются, что уменьшает объем программы и увеличивает быстродействие. Следует иметь в виду, что и в первом, и во втором случае ряд не перечисленных ключей (например, {$D+} при отладке или {$R-} после отладки) используются по умолчанию.
|