Рис.150 – Сообщение об успешной компиляции модуля
Если же выявятся синтаксические ошибки, вам придется устранить их.
Модули компилируются и в ходе сборки проекта. При нажатии клавиши F9 (или при выборе в меню Compile –> Make) компилятор просматривает списки импорта USES как в главной программе, так и в модулях. Обнаружив очередной модуль, компилятор сравнивает время редакции его исходного файла (PAS) со временем создания откомпилированного файла. Если исходный файл оказался свежее откомпилированного или последний пока не существует, то модуль компилируется. Так или иначе, но перед сборкой проекта все его модули будут скомпилированы. Только после удачной компиляции первичного файла и всех связанных с ним модулей создаётся исполняемый EXE–файл.
Фирменные библиотеки
Я уже упоминал о библиотеках, входящих в состав IDE, – они поставляются и в исходном, и в откомпилированном виде. Вы можете применять эти библиотеки наряду со своими, предварительно ознакомившись с ними по документации или по встроенной справке. Ощутить полезность фирменных библиотек можно по этой небольшой программе.
uses CRT; { Из CRT импортируются процедуры Sound, NoSound, Delay, ClrScr }
procedure Beep; { короткий гудок }
begin
Sound(300); { включение динамика на частоте 300 Гц }
Delay(500); { задержка на полсекунды }
NoSound; { отключение динамика }
end;
begin {--- Главная программа ---}
ClrScr; { очистка экрана }
Writeln(’Привет, Мартышка!’);
Beep; { короткий гудок }
Readln;
end.
Здесь на предварительно очищенный экран выводится приветствие, сопровождаемое коротким гудком. В программе используется ряд процедур из библиотеки CRT, – там собраны средства для работы с экраном. Для успешной компиляции надо указать компилятору путь к файлу «CRT.TPU». При установке среды программирования фирменные библиотеки обычно попадают в папку «…\Units» (многоточием обозначена папка установки IDE). Уточнив положение библиотек, подскажите компилятору путь к месту их проживания через пункт меню Options –> Directories… (рис. 151).
Рис.151 – Указание пути к фирменным библиотекам
В данном примере предполагаем, что компилятор установлен в директорию «C:\BP», а библиотечные модули размещены в папке «C:\BP\UNITS».
Динамически загружаемые библиотеки (DLL)
Порой несколько разных программ используют общие для них процедуры и функции. Если при их компиляции подключить общую библиотеку, то процедуры из неё войдут в каждую из программ, увеличивая их общий «вес». Кому-то пришла в голову мысль отделить библиотеку от использующих её программ так, чтобы библиотека загружалась в память лишь единожды в момент запуска первой из применяющих её программ. И тогда, при старте последующих программ, нужные им средства оказываются уже загруженными в память. Это уменьшает общий объём оперативной памяти, потребляемой всеми работающими программами. Динамически загружаемые библиотеки (DLL) могут разрабатываться не только на Паскале, но и на других языках (например, на Си или Ассемблере).
Итоги
• В программировании принято разделение труда, и для этого используют модульную технологию. Современные программы собирают из модулей, разработанных разными программистами.
• Модуль содержит все необходимое для выполнения логически связанных действий: константы, типы, переменные, процедуры и функции.
• Каждый модуль обладает именем и содержит две обязательные секции: секцию интерфейса и секцию реализации.
• Имя модуля должно совпадать с именем файла без расширения.
• Секция интерфейса содержит объявления, видимые за пределами модуля.
• Секция реализации содержит невидимые за пределами модуля объявления, а также тела процедур и функций.
• Для установки начальных значений глобальных переменных модуля применяют секцию инициализации.
А слабо?
А) Разбейте на два модуля проект «P_58_1» – обход графа в ширину. Что должно быть видимо за пределами модуля? Что поместить в секцию инициализации?
Задачи на темы предыдущих глав
Б) Императорские заботы. После постройки империи (главы 57 и 58) бывшие независимые государства стали провинциями и породили новые проблемы. Для доставки туда правительственных бумаг император нанял гонцов. Чтобы доставка была по возможности скорой, гонцы следовали кратчайшими путями лишь в одном направлении – от центра к окраинам империи. Сколько гонцов для этого нужно? – вот первый вопрос. Сколько времени потребуется для достижения самых дальних окраин, если переход из провинции в провинцию отнимает сутки? – это второй вопрос. В конечных пунктах (на окраинах) перед возвращением гонцам нужен отдых, что это за окраины, где надо построить гостиницы? – это третий вопрос.
Подсказка: возьмите за основу программу «P_58_1» – обход графа в ширину – и внесите необходимые дополнения в процедуру Expand.
Глава 60
Мелкие хитрости
Нелегко совладать с крупным проектом, и тут не грех прибегнуть ко всяким уловкам и хитростям!
Включаемые файлы
Рассмотрим ещё одно средство дробления программного проекта – включаемые файлы, которые называют ещё INCLUDE–файлами. В сравнении с библиотечными модулями возможности этих файлов скромны, но каждая вещь хороша на своем месте.
Механизм включаемых файлов до безобразия прост: содержимое такого файла как бы вставляется в другой. Место вставки определяется директивой $I, за которой следует имя вставляемого файла. Вы скажете, что вставку можно сделать иначе – редактором текста. Но ценность директивы $I в том, что вставки как таковой не происходит, – оба файла не изменяются. Но в момент компиляции проекта включаемый файл как бы составит часть того файла, в который он «вставлен».
Вот пример. Создадим и сохраним в рабочей папке два файла, первый из которых назовем «HELLO.INC», и в нём будет лишь одна строка.
Writeln(’Привет!’);
Второй файл – «HELLO.PAS» – будет таким.
begin {--- Главная программа HELLO.PAS ---}
{$I Hello}
end.
Компиляция файла «HELLO.PAS» породит приветливую программу. Здесь в директиве $I указано имя вставляемого файла без расширения, поскольку расширение INC берется по умолчанию. Разумеется, что INCLUDE–файл не вставишь куда попало, – его содержимое должно сочетаться с тем окружением, в которое его погружают.
Незамысловатый механизм включаемых файлов даёт ощутимую пользу, вот пример. Предположим, вы работаете над крупным проектом, состоящим из нескольких модулей. Время от времени вам надо компилировать эти модули вместе с первичным файлом так, чтобы опции компилятора для всех файлов совпадали. Такого совпадения можно добиться следующим образом:
Сначала настройте нужные опции компилятора через пункт меню Options –> Compiler…. Затем создайте новый файл и вставьте в него директивы компиляции нажатием комбинации Ctrl+O+O; в результате в файле могут оказаться такие, например, строки.