Утилита MAKE фирмы Borland (MAKE - для защищенного режима и MAKER для реального режима) - это утилита управления проектами, работающая в режиме командной строки. Она помогает вам создавать выполняемую версию программы на основе самых последних версий исходных файлов. Многие программы состоят из значительного числа исходных файлов, каждый из которых, возможно, должен пропускаться через препроцессоры, ассемблеры, компиляторы и другие утилиты перед тем, как он будет объединяться с остальной частью программы. Если вы забудете перекомпилировать какой-либо модуль, который был модифицирован, или модуль, который зависит от какого-либо другого модифицированного исходного текста, то это может привести к разрушительным логическим ошибкам. С другой стороны, перекомпиляция всех исходных файлов лишь для того, чтобы обезопасить себя, может привести к слишком большим затратам времени.
Эта задача разрешается утилитой MAKE. Утилите MAKE задается описание того, как должны обрабатываться исходные и объектные файлы вашей программы для того, чтобы получить результирующий продукт. Утилита MAKE анализирует эти описания и маркеры даты ваших файлов, а затем выполняет действия, необходимые для создания самой последней версии продукта. Во время выполнения этого процесса утилита MAKE может вызывать множество различных компиляторов, ассемблеров, компоновщиков и утилит, однако, для обновления результирующей программы она никогда не сделает ничего, что превышало бы необходимый минимум.
Полезность утилиты MAKE выходит далеко за рамки чисто программных приложений. Вы можете воспользоваться утилитой MAKE для управления любым процессом, который связан с выбором файлов по имени и их обработкой для создания результирующего продукта. К числу некоторых широко распространенных приложений относится обработка текстов, автоматическое создание дубликатных копий, сортировка файлов по расширению имени с занесением их в другие каталоги, а также уничтожение временных файлов в ваших каталогах.
Утилита MAKE создает самую последнюю версию вашей программы, выполняя при этом следующие задачи:
Утилита MAKE полностью полагается на дату и время, которые
DOS присваивает каждому файлу. Это означает, что для нормальной
работы утилиты MAKE необходимо корректно устанавливать системные
дату и время.
Ниже приводится синтаксис вызова команды MAKE:
MAKE [параметр...][результат...]
Здесь "параметр" является параметром утилиты MAKE (они описываются далее), а "результат" представляет собой имя результирующего файла, который должен быть создан.
Ниже описываются синтаксические правила вызова утилиты MAKE:
Если в командной строке не содержатся имена результирующих файлов, то утилита MAKE использует в качестве явно заданного результирующего файла имя первого обнаруженного результирующего файла. Если в командной строке указан один или несколько результирующих файлов, то они будут создаваться по мере необходимости.
Вы быстро обнаружите, что существуют макрокоманды и правила утилиты MAKE, которые требуется использовать снова и снова. Существует три способа их обработки:
Каждый раз, когда вы запускаете утилиту MAKE, она ищет файл с именем BUILTINS.MAK. Однако, наличие файла BUILTINS.MAK не является обязательным. Если MAKE обнаруживает файл BUILTINS.MAK, то сначала она интерпретирует этот файл. Если утилита MAKE не может обнаружить файл BUILTINS.MAK, то она переходит непосредственно к интерпретации файла MAKEFILE (или того формирующего файла утилиты MAKE, который был вами задан с помощью параметра -f).
Утилита MAKE сначала ищет файл BUILTINS.MAK в текущем каталоге. Если он отсутствует, и вы работаете под управлением DOS версии 3.0 или старше, то MAKE осуществляет поиск в том каталоге, откуда была вызвана сама утилита MAKE. Вам следует заносить файл BUILTINS.MAK в тот же каталог, где находится файл MAKE.EXE.
Утилита MAKE всегда осуществляет поиск формирующего файла только в текущем каталоге. Этот файл содержит правила для конкретной создаваемой выполняемой программы. Как файл BUILTINS.MAK, так и формирующий файл подчиняются одинаковым синтаксическим правилам.
Поиск файлов, задаваемых с помощью директивы !include, также осуществляется в текущем каталоге. Если вы используете параметр -I (файлы включения), то она будет также выполнять поиск в каталоге, заданном с помощью параметра -I.
BUILTINS.MAK содержит стандартные правила и макрокоманды, которые MAKE применяет перед тем, как MAKE использует формирующий файл (параметр -r позволяет MAKE игнорировать BUILTINS.MAK).
Иногда требуется вызвать принудительную перекомпиляцию или построение целевого файла, даже если он еще не изменялся. Это можно сделать с помощью утилиты TOUCH, которая изменяет дату и время одного или более файлов на текущие дату и время, делая его (их) более новым, чем файлы, от которых он зависит.
Вы можете также вынудить MAKE перестроить целевой файл, изменив один из файлов, от которых он зависит. Для этого наберите в командной строке:
TOUCH имя_файла [имя_файла]После этого TOUCH обновляет дату и время создания файла.
Параметры командной строки управляют поведением утилиты MAKE. Заметьте, что имеет значение регистр букв (верхний или нижний); параметр -d не является допустимой заменой параметру -D.
Кроме того, для указания параметров можно задавать либо косую черту (/), либо дефис (-).
Параметр | Действие |
---|---|
-? или -h | Выводит информационное сообщение. Отображаются стандартные параметры, за которыми следует знак плюс. |
-B | Осуществляет полную перекомпиляцию всех результирующих файлов вне зависимости от дат создания файлов. |
-Dмакро | Определяет "макро" как один символ - выражение !ifdef макро будет возвращать True. |
[-D]ид=[стр] | Определяет названный идентификатор "ид" как строку "стр", стоящую после знака равенства. Эта строка не может содержать ни пробелов, ни знаков табуляции. |
-fимя_файла | Использует "имя_файла" в качестве формирующего файла для утилиты MAKE. Если "имя_файла" не существует и не задано расширение имени файла, то утилита MAKE пытается найти файл FILENAME.MAK. |
-Iкаталог | Осуществляет поиск файлов включения в указанном каталоге (а также в текущем каталоге). |
-K | Сохраняет (не стирает) временные файлы, созданные утилитой MAKE. Все временные файлы имеют формат MAKEnnnn.$$$, где nnnn лежит в диапазоне от 0000 до 9999. |
-N | Выполняет MAKE как Microsoft NMAKE. |
-Uидентиф | Отменяет все заданные ранее описания названного идентификатора. |
-W | Заносит в файл MAKE.EXE заданные в настоящий момент нестроковые параметры (типа -s или -a). |
-a | Проверяет зависимости включаемых файлов и вложенных включаемых файлов, связанных с файлами .OBJ, и обновляет файл .OBJ, если файл .H изменен. |
-c | Кэширует информацию о зависимостях, что улучшает производительность MAKE. Не используйте его с -a а также если MAKE изменяет включаемые файлы. |
-dкаталог | Используется с -S для задания диска и каталога, который MAKE использует для свопинга (для MAKER не действует). |
-e | Игнорирует макрокоманду, если ее имя совпадает с именем переменной операционной среды. |
-i | Игнорирует состояние завершения всех запускаемых из MAKE программ и продолжает процесс построения. |
-m | Выводит дату и время каждого файла при обработке его MAKE. |
-n | Выводит команды, но не выполняет их (полезно использовать при отладке). |
-p | Перед выполнением формирующего файла выводит все макроопределения и неявные правила. |
-q | Возвращает 0, если цель имеет новую дату и время и не 0 в противном случае (используется в командных файлах). |
-r | Игнорирует все правила, определенные в BUIL- TINS.MAK. |
-s | Подавляет вывод команд на экран. |
-S | Выгружает MAKE из памяти при выполнении команд, что уменьшает использование памяти и позволяет компилировать большие модули. Для MAKER не действует. |
Параметр -W позволяет вам установить некоторые параметры MAKE, которые будут использоваться по умолчанию. Чтобы задать такие параметры, наберите:
make -параметр[-] [-параметр][-] ... -WНужно учитывать, что -W не работает, когда загружена программа DOS SHARE, а таке со следующими параметрами MAKE:
-Dмакро -fимя_файла [-D]ид=[стр] -? или -h -dкаталог -lкаталог -Uидентификатор
Параметр командной строки -N увеличивает совместимость с утилитой фирмы Microsoft NMAKE. Его следует использовать только в том случае, если вам требуется построить проект с использованием формирующих файлов, созданных для утилиты NMAKE. Предпочтительнее запускать утилиту MAKE без параметра -N, так как данный параметр вносит в утилиту MAKE некоторые трудноуловимые отличия:
TEST = this is ^ a testприведет к тому, что TEST будет расширяться в this is \na test, где \n - это символ языка Си перевода на новую строку. Это особенно полезно, когда вам нужно закончить строку символом продолжения строки:
SOURCEDIR = C:\BOB\OBJ^\
Формирующий файл содержит описания и отношения, необходимые программе MAKE для поддержания самых последних версий ваших программ. Вы можете создавать столько формирующих файлов, сколько вам требуется и присваивать им произвольные имена; MAKEFILE представляет собой лишь имя, используемое по умолчанию, на которое ориентируется утилита MAKE, если при ее запуске имя формирующего файла не задано.
Формирующий файл можно создать с помощью любого текстового редактора, который поддерживает формат ASCII, например, встроенного редактора интегрированной среды, редакторов Sрrint, MicroStar или SideKick. Все правила, описания и директивы завершаются концом строки. Если строка является слишком длинной, то вы можете продолжить ее на следующей строке, поместив на текущей строке в качестве последнего символа обратную косую черту (\).
Для разделения соседних идентификаторов (например, при задании последовательностей) и для задания структурного отступа команд внутри правила следует пользоваться пробельными символами (пробелами и знаками табуляции). Формирующий файл может содержать комментарии, явные и неявные правила, макрокоманды и директивы.
Символическая цель вынуждает MAKE строить в формирующем файле несколько целей (вам не нужно будет полагаться на сцепленные зависимости). В строке зависимости перечисляются все цели, которые вы хотите построить. Никаких команд для символических целей указывать не нужно.
Например, в следующем формирующем файле символические цели Files строятся из FILE1.EXE и FILE2.EXE.
Files: file1.exe file2.exe #Эта цель не имеет команд file1.exe: file1.obj bcc file1.obj file2.exe: file2.obj bcc file2.objДля символических целей действуют следующие правила:
Явные и неявные правила, инструктирующие MAKE, в общем случае определяются следующим образом:
Строка зависимости Команды . . .
Строка зависимости для явных и неявных правил отличается, но команды одни и те же. MAKE поддерживает несколько правил на одну цель. После первого явного правила вы можете добавить файл, от которого зависит цель, например:
Target1: dependent1 dep2 dep3 dep4 dep5 Target2: dep6 del7 del8 bcc -c $**
Явное правило - это правило, которое явным образом задает полные имена файлов. Явные правила имеют следующий вид:
целевой_файл[целевой_файл]...:[{маршрут}][исходный_файл...] [команда] . . .
Здесь "целевой_файл" представляет собой файл, который должен быть обновлен, "исходный_файл" представляет собой файл, от которой зависит файл "целевой_файл", а "команда" представляет собой любую команду, допустимую в DOS (включая вызовы .BAT файлов и выполнение .EXE и .COM файлов).
Явные правила определяют одно или несколько имен результирующих файлов, ноль или более исходных файлов, а также необязательный перечень команд, которые должны быть выполнены. Имена результирующего (целевого) и исходного файлов, указываемые в явных правилах, могут содержать обычные спецификации дисковода и каталога, допустимые в DOS, а также содержать трафаретные символы.
Обязательны для соблюдения следующие указанные ниже синтаксические правила:
Наличие как имен исходных файлов, так и команд является необязательным; возможно существование явных правил, которые состоят только из строки целевой_файл[целевой_файл...], за которой следует символ двоеточия.
Идея использования явного правила заключается в том, что команда или перечень команд будут осуществлять создание или обновление результирующего файла целевой_файл как правило на основе исходного файла "исходный_файл". Когда утилита MAKE обнаруживает явное правило, она сначала проверяет, не являются ли сами исходные файлы "исходный_файл" результирующим файлом "целевой_файл" в каком-либо другом правиле формирующего файла. Если это так, то сначала утилита MAKE анализирует это второе правило.
После того, как на основе других правил были созданы или обновлены все исходные файлы "исходный_файл", утилита MAKE проверяет наличие результирующего файла "целевой_файл". Если "целевой_файл" не существует, то все команды выполняются в том порядке, в котором они заданы. Если "целевой_файл" существует, то дата и время его последней модификации сравниваются с датой и временем каждого исходного файла "исходный_файл". Если какой-либо исходный файл был модифицирован после того, как был модифицирован файл "целевой_файл", то выполняется заданный перечень команд.
Имя файла может указываться в левой части явного правила файла описания утилиты MAKE лишь один раз.
Каждая командная строка в явном правиле начинается с символа пробела. Утилита MAKE рассматривает все строки, которые следуют за явным правилом и продолжаются до очередной строки, начинающейся со столбца 1 (которой не предшествуют символы пробела) или до конца файла, как часть списка команд для этого правила. Пустые строки игнорируются.
Явное правило, за которым не следуют командные строки, интерпретируется несколько иначе, чем явное правило с командными строками.
.c.obj BCC -c $< рrog.obj:
Файл рrog.obj зависит от файла рrog.c; если не совпадают даты этих файлов, то будет выполняться командная строка:
BCC -c рrog.c
Для одного целевого файла можно задать несколько явных правил. Множественные явные правила вы можете использовать для создания с помощью TLIB библиотечного модуля. Например, поскольку файлы объектных модулей .OBJ могут строиться по-разному (некоторые с помощью компилятора BCC, а другие, например, с помощью TASM).
Здесь используется тот же формат, что и для обычных явных правил, но за целевым файлом указывается два двоеточия. Второе двоеточие сообщает утилите MAKE, что для данного целевого файла ожидаются дополнительные явные правила.
В следующем примере MYLIB.LIB состоит из четырех объектных модулей, два из которых являются модулями С++. Первое явное правило компилирует модули С++ и обновляет библиотеку. Второе явное правило ассемблирует файлы ASM и также обновляет библиотеку.
mylib.lib:: f1.cpp f2.cpp bcc -c f1.cpp f2.cpp tlib mylib -+f1.obj -+f2.obj mylib.lib:: f3.asm f4.asm tasm /mx f3.asm f4.asm tlib mylib -+f3.obj -+f4.obj
1. рrog.exe: myрrog.obj рrog2.obj BCC myрrog.obj рrog2.obj 2. myрrog.obj: myрrog.c include\stdio.h BCC -c myрrog.c 3. рrog2.obj: рrog2.c include\stdio.h BCC -c -K рrog2.c
Эти три примера взяты из одного и того же формирующего файла. Повторно будут обрабатываться только те модули, которые подвергались модификациям. Если был модифицирован файл PROG2.C, то будет перекомпилироваться только этот файл. То же самое справедливо для файла MYPROG.C. Но если был изменен файл включения stdio.h, то будут перекомпилированы оба файла. Перекомпоновка будет осуществляться в том случае, если был модифицирован хотя бы один из объектных файлов, указанных в списке зависимости. Это имеет место в том случае, если в результате изменения исходного файла была произведена перекомпиляция.
Система Borland C++ ориентирована также на использование утилиты MAKE в целях автоматической проверки зависимостей для включаемых файлов. Компиляторы BCC и BCC32 создают объектные файлы, которые содержат используемую утилитой MAKE информацию о всех файлах включения, необходимых для создания объектного файла. Параметр командной строки -a утилиты MAKE проверяет эту информацию, чтобы удостовериться в "современности" всех используемых файлов.
Когда утилита MAKE осуществляет автоматическую проверку зависимостей, она считывает имена файлов включения, а также время и дату создания объектных файлов. Если какой-либо включаемый файл был модифицирован, утилита MAKE осуществляет перекомпиляцию для обновления объектного файла.
Утилита MAKE позволяет на ряду с явными правилами задавать неявные правила. Неявные правила представляют собой обобщение явных правил; они применяются ко всем файлам, которые имеют соответствующие расширения имен файлов.
Ниже приводится пример, который иллюстрирует отношение между двумя правилами. Рассмотрим явное правило из предыдущего примера. Данное правило является типичным, поскольку оно следует общему принципу: объектный файл(с расширением имени .OBJ) зависит от файла с тем же основным именем и расширением .C и создается путем выполнения программы BCC. Фактически, можно создать формирующий файл для утилиты MAKE, который будет содержать несколько(или несколько десятков) явных правил, соответствующих одному и тому же формату.
Переписывая явное правило в виде неявного правила, вы можете убрать все явные правила, которые подчиняются одинаковому форма ту. Неявное правило будет иметь следующий вид:
.c.obj: BCC -c $<
Это правило означает следующее: "Любой файл с расширением .C может быть оттранслирован в файл с тем же основным именем и расширением .OBJ с помощью следующей последовательности команд". Создание файла .OBJ происходит с помощью второй строки этого правила, где $< означает имя файла с расширением, присущим исходному файлу (.C). (Символ $< представляет макрокоманду особого вида. Объяснение макрокоманд приводится далее. Макрокоманда $< при каждом выполнении команды будет заменена полным именем соответствующего исходного файла .C).
Идентификатор $< представляет собой специальную макрокоманду. Макрокоманды обсуждаются ниже. Макрокоманда $< при каждом выполнении команды будет заменяться полными именем соответствующего исходного файла .С.
Ниже приводится синтаксис неявного правила:
[{исходный_каталог}].исх_расшир.[{целевой_каталог}]цел_расшир: [команда] ...
Как и ранее, использование команды является необязательным. Если команда используется, то перед ней должны стоять один или несколько символов пробелов.
"Исх_расшир" (расширение имени файла, которое должно начинаться точкой в столбце 1) представляет собой расширение имени исходного файла; то есть, оно относится к любому файлу, который имеет следующий формат:
имя_файла.исх_расширАналогично, "цел_расшир" относится к файлу, который удовлетворяет спецификации:
имя_файла.цел_расшир
Здесь "имя_файла" является одинаковым для обоих файлов. Другими словами, данное неявное правило заменяет все явные правила, которые соответствуют следующему формату:
имя_файла.исх_расшир:имя_файла.цел_расшир [команда] ...для любого имени файла.
Если утилита MAKE не может обнаружить явное правило для заданного результирующего файла, или если имя результирующего файла появляется в явном правиле, у которого отсутствуют команды, то она использует неявные правила.
Расширение имени интересующего утилиту MAKE файла используется для определения того неявного правила, которое должно использоваться. Это неявное правило применяется в том случае, если обнаружен файл с тем же самым основным именем, что и у результирующего файла, но с заданным расширением исходного файла.
Предположим, например, что у вас имеется формирующий файл утилиты MAKE (с именем MAKEFILE), который имеет следующее содержимое:
c.obj: BCC -c $<
Если у вас имеется написанная на Си программа с именем RATIO.C, которую вы хотите скомпилировать в файл RATIO.OBJ, то вы можете воспользоваться командой:
make ratio.obj
Утилита MAKE будет рассматривать файл RATIO.OBJ в качестве результирующего файла. Поскольку явное правило для создания файла RATIO.OBJ не существует, утилита MAKE применяет неявное правило и генерирует следующую команду:
BCC -c ratio.c
которая, естественно, выполняет компиляцию для создания файла RATIO.OBJ.
Утилита MAKE использует неявные правила и в том случае, когда ей задаются явные правила, не сопровождающиеся никакими командами. Предположим, что в начале файла описания вы задали следующее неявное правило:
.c.obj: BCC -c $<
Если это правило задано, вы можете удалить команду из приведенного ниже явного правила:
myрrog.obj: myрrog.c include\stdio.h BCC -c myрrog.cПроцесс обработки будет прежним.
Если вы используете систему Borland C++ и разрешаете утилите MAKE выполнять автоматическую проверку зависимостей, вы можете удалить все явно заданные зависимости, в которых объектные файлы указываются в качестве результирующих. Если задана автоматическая проверка зависимостей, и используются неявные правила, то представленный в начале раздела по явным правилам пример с тремя правилами превращается в следующий:
c.obj: BCC -c $< рrog.exe: myрrog.obj рrog2.obj tlink lib\c0s myрrog рrog2, рrog, ,lib\cs
Вы можете создать несколько неявных правил с одним и тем же расширением имени результирующего файла. Если для заданного расширения имени результирующего файла имеется более одного неявного правила, то правила проверяются в том порядке, в котором они появляются в файле описания, до тех пор, пока не найдется правило, подходящее для расширения имени исходного файла, или до тех пор, пока утилита MAKE не осуществит проверку всех применимых правил.
Утилита MAKE использует первое неявное правило, в котором указан файл с расширением имени исходного файла. Даже если выполнение команды, заданной в этом правиле, заканчивается безуспешно, никакие неявные правила больше не проверяются.
Все строки, следующие за неявным правилом вплоть до очередной строки, которая не начинается с символа пробела, или до конца файла, считаются частью списка команд для этого правила.
Цель в явном правиле получает свою командную строку из явного правила. Следующий пример показывает неявное правили и явное правило без командной строки:
.c.obj bcc -c $< #использует макрокоманду $< myprog.obj: #явное правило, использующее команду # bcc -c myprog.c
Как явные, так и неявные правила (описываемые ниже) могут содержать списки команд. Команды в списке команд подчиняются следующим синтаксическим правилам:
[префикс...]тело_команды
Каждая команда в списке команд состоит из (необязательного) списка префиксов, за которым следует тело единственной команды.
Префиксы, допустимые в команде, модифицирует интерпретацию этих команд утилитой MAKE. Префиксом является либо символ @, либо дефис (-), за которым непосредственно следует какое-либо число.
Префикс | Действие |
---|---|
@ | Указывает утилите MAKE, что не нужно отображать команды перед их выполнением. Отображение не осуществляется даже в том случае, если в командной строке утилиты MAKE не задается параметр -s. Этот префикс применяется только к тем командам, перед которыми он указывается. |
-num | Оказывает влияние на то, как утилита MAKE интерпретирует коды выхода. Если задается какое-либо число num, то утилита MAKE прекращает обработку
только в том случае, если полученный код выхода превышает заданное число. В приведенном ниже примере утилита MAKE прекращает работу только в том случае, если код выхода превышает 4:
-4myрrog samрle.xЕсли префикс -num не задается, а код выхода является ненулевым, то утилита MAKE прекращает работу и удаляет текущий результирующий файл. Примечание: Коды выхода являются значениями, которые возвращаются выполняемыми командами (внутри программы). |
- | Если задается дефис, но не задается никакого числа, то утилита MAKE совсем не будет проверять код выхода. Независимо от кода выхода выполнение утилиты MAKE будет продолжено. |
В дополнение к операциям переназначения <, > и >>, утилита MAKE добавляет операции << и &&. Эти операции для создания подаваемых на вход команды данных создают в оперативном порядке файл. Операция << создает временный файл и переназначает поток стандартного ввода команды таким образом, что он поступает из созданного файла. Если у вас имеется программа, которая допускает ввод данных из потока stdin, то команда:
MYPROG <<! Это лишь тест !
будет создавать временный файл, содержащий строку "Это лишь тест \n", переопределяя ее как единственный поток входной информации для программы myрrog. Восклицательный знак (!) представляет собой в данном примере разделитель; в качестве разделителя для этого файла можно использовать любой символ за исключением символов # или \. Первая строка, начальным символом которой является символ разделителя, завершает файл. Остальная часть строки, следующая за символом разделителя (в данном примере, восклицательным знаком) считается часть предшествующей команды.
Операция && аналогична операции <<. Он создает временный файл, но вместо того, чтобы сделать этот файл стандартным потоком ввода для указанной команды, операция && заменяется именем временного файла. Это оказывается полезным в том случае, если вы хотите, чтобы утилита MAKE создала файл, который должен быть использован в качестве источника входных данных команды. В приведенном ниже примере показывается, как создать "файл подсказки" для утилиты TLINK.
MYPROG.EXE: $(MYOBJS) tlink /c @&&! COS $(MYOBJS) $* $* $(MYLIBS) EMU.LIB MATHS.LIB CS.LIB
Заметьте, что макрокоманда (которая обозначается с помощью знака $) расширяется при создании файла. $* заменяется именем создаваемого файла без расширения, а $(MYOBJS) и $(MYLIBS) заме- няются значениями макрокоманд MYOBJS и MYLIBS. Таким образом, для TLINK файл будет выглядеть следующим образом:
COS a.obj b.obj c.obj d.obj MYPROG MYPROG w.lib x.lib y.lib z.lib EMU.LIB MATHS.LIB CS.LIB
Если не используется параметр командной строки -K, то все временные файлы удаляются. Параметром -K следует пользоваться для "отладки" временных файлов, если возникает впечатление, что эти файлы работают неверно.
Макрокоманда MAKE - это строка, которая расширяется при вызове макрокоманды в формирующем файле. Макрокоманды позволяют создавать шаблоны формирующих файлов и изменять их для конкретных проектов.
Макроопределение имеет следующую форму:
имя_макрокоманды = текст_макрорасширения
Здесь "имя_макрокоманды" представляет имя данной макрокоманды. "Имя_макрокоманды" должно являться строкой из букв и цифр, не содержащей символов пробела, хотя пробелы между "именем_макрокомандЫ" и знаком равенства (=) допустимы. "Текст_макрорасширения" представляет собой произвольную строку, содержащую буквы, цифры, символы пробела и знаки пунктуации. Эта строка завершается символом перехода на новую строку.
Если "имя_макрокоманды" уже было определено ранее (либо с помощью макроопределения в формирующем файле, либо с помощью параметра -D командной строки утилиты MAKE), то новое описание макрокоманды заменяет старое.
При задании макрокоманд регистр букв учитывается; то есть, model, Model и MODEL определяют разные макрокоманды.
При вызове макрокоманды в формирующем файле должен соблюдаться следующий формат:
$(имя_макрокоманды)
Круглые скобки должны использоваться во всех случаях вызова макрокоманд, даже в том случае, если имя макрокоманда состоит из единственной буквы (за исключением предопределенных макрокоманд). Данная конструкция - $(имя_макрокоманды) - называется вызовом макрокоманда.
Когда утилита MAKE обнаруживает вызов макрокоманды, она заменяет ее на текст, раскрывающий макрокоманду (текст макрорасширения). Если текст макрорасширения не определен, то MAKE заменяет ее пустой (нулевой) строкой.
Если вы вызываете макрокоманду, для которой "имя_макрокоманды" еще не определено в формирующем файле или в командной строке, утилита MAKE будет пытаться найти "имя_макрокоманды", как переменную операционной среды DOS. Если MAKE находит ее в операционной среде, то текстом макрорасширения будет значение этой переменной операционной среды.
Если не был задан параметр -e, то макрокоманды, определенные в формирующем файле или в командной строке, переопределяют переменные операционной среды с тем же именем.
Используя специальный формат вызова макрокоманды, вы можете вызвать макрокоманду, изменив ее текст. Вместо стандартной формы вызова используйте следующую:
$(имя_макрокоманды:текст_1=текст_2)
При использовании такой формы вызова каждое вхождение в макрокоманду "текста_1" будет заменяться "текстом_2". "Имя_макрокоманды'" может быть одной из предопределенных макрокоманд. Это полезно использовать, если вы предпочитаете использовать в макрокоманде один список файлов.В приведенном ниже примере макрокоманда SOURCE содержит список файлов C++, от которых зависит целевой файл. Командная строка TLINK изменяет все расширения .CPP на соответствующие расширения .OBJ объектных файлов и компонует их.
SOURCE = f1.cpp f2.cpp f3.cpp myapp.exe: $(SOURCE) bcc -c $(SOURCE) tlink c0s $(SOURCE:.cpp=.obj),myapp,,cs
Между : и = не нужно включать лишних пробелов. Если после двоеточия указывается пробел, MAKE будет пытаться найти строку, включающую предшествующий пробел.
Макрокоманда не может вызываться в левой части ("имя_макрокоманды") макроопределения. Макрокоманды могут использоваться в правой части ("текст_макрорасширения"), но их раскрытие не будет осуществляться до тех пор, пока описанный макрокоманд не будет вызван. Другими словами, когда осуществляется раскрытие макроопределения, будет также осуществляться расширение всех макрокоманд, вложенных в раскрывающий текст.
Вызов макрокоманд в строках правил раскрывается немедленно.
Вызовы макрокоманд в директивах !if и !elif раскрываются немедленно. Если вызываемая в директивах !if или !elif макрокоманда в данный момент не определена, то она расширяется в значение 0 (ложно).
Вызовы макрокоманд в командах раскрываются при выполнении команд.
Утилита MAKE содержит в себе несколько специальных встроенных макрокоманд: $d, $*, $<, $:, $. и $&. Первая из них осуществляет проверку на существование макрокоманды с заданным именем. Он используется в директивах !if и !elif. Остальные представляют собой макрокоманды имен файлов, используемые в явных и неявных правилах. В дополнение к этому, в качестве макрокоманд автоматически загружаются строки установленной к настоящему моменту среды DOS (строки, которые можно просматривать и задавать в DOS с помощью команды SET). Наконец, в MAKE определяются несколько предопределенных макрокоманд, показанных ниже:
Макрокоманда | Описание |
---|---|
__MSDOS__ | Имеет значение 1, если MAKE выполняется в DOS. |
__MAKE__ | Номер версии MAKE в шестнадцатиричном виде (для данной версии "Ox0370"). |
MAKE | Имя выполняемого файла MAKE (обычно MAKE или MAKER. |
MAKEFLAG | Все параметры, используемые в командной строке утилиты MAKE. |
MAKEDIR | Каталог, из которого запущена утилита MAKE. |
Макро- команда | Расширение в неявных файлах | Расширение в явных файлах |
---|---|---|
$* | маршрут\исходный_файл | маршрут\целевой_файл |
$< | маршрут\исходный_файл+расш | маршрут\целевой_файл+расш |
$: | маршрут исходных файлов | маршрут целевых файлов |
$. | исходный файл+расширение | целевой файл+расширение |
$& | исходный файл | целевой файл |
$@ | маршрут\целевой_файл+расш | маршрут\целевой_файл+расш |
$** | маршрут\исходный_файл+расш | все исходные файлы+расш |
$? | маршрут\исходный_файл+расш | старые исходные файлы |
Если нет предопределенной макрокоманды имени файла, которая позволяет вам задавать части нужного имени файла, для выделения частей имени файла вы можете использовать модификаторы макрокоманд. Они имеют следующий формат:
$(макрокоманда[D F B R])
где "макрокоманда" - одна из предопределенных макрокоманд имени файла (показанных выше), а R, B, D и F - модификаторы. Заметим, что поскольку макрокоманда теперь имеет длину более одного символа, необходимы круглые скобки. Каждый из модификаторов описывается в следующей таблице. В примерах предполагается, что $< возвращает C:\OBJS\BOB.OBJ.
Модификатор | Какую часть имени файла он определяет | Пример |
---|---|---|
D | Диск и каталог. | $(<D)=C:\OBJS\ |
F | Базовое имя файла и расширение. | $(<F)=BOB.OBJ |
B | Только базовое имя файла. | $(<B)=BOB |
R | Диск, каталог и расширение. | $(<R)=C:\OBJS\BOB |
Утилита MAKE фирмы Borland позволяет выполнять операции, которые не допускаются в других версиях MAKE: задавать директивы, подобные тем, которые имеются в языках Си, ассемблере и Паскале. Эти директивы могут использоваться для реализации значительного числа полезных и мощных операций. Некоторые директивы начинаются в файле описания с восклицательного знака (!), который должен являться первым символом строки. Другие начинаются с точки. Ниже приводится полный перечень директив утилиты MAKE:
Директива | Описание |
---|---|
.autodeрend | Включает проверку автоматических зависимостей. |
!elif | Условное выполнение. |
!else | Условное выполнение. |
!endif | Условное выполнение. |
!error | Указывает, что утилита MAKE должна остановиться и выдать сообщение об ошибке. |
!if | Условное выполнение |
.ignore | Указывает, что утилита MAKE должна игнорировать возвращаемое командой значение |
!include | Задает файл, который должен быть включен в формирующий файл. |
.noautodepend | Выключает автоматическую проверку зависимостей. |
.noignore | Выключает действие директивы .ignore. |
.nosilent | Указывает утилите MAKE, что нужно отображать команды перед их выполнением. |
.noswaр | Указывает утилите MAKE, что не нужно осуществлять выгрузку самой себя из памяти и подкачку в память. |
.рath.ext | Задает утилите MAKE маршрут для поиска файлов с расширением ."EXT". |
.precious | Указывает утилите MAKE, что целевой файл удалять не нужно, даже при неудачном выполнении команд построения целевого файла. |
.silent | Указывает утилите MAKE, что не нужно отображать команды перед их выполнением. |
.swaр | Указывает утилите MAKE, что нужно осуществлять выгрузку самой себя из памяти и подкачку в память. |
.suffixes | Указывает MAKE, что при неоднозначности целевого файла нужно использовать неявное правило. |
!undef | Задает отмену описания заданной макрокоманды. |
Каждая из представленных ниже директив имеет соответствующий ей параметр командной строки, но при этом обладает приоритетом по сравнению с этим параметром. Например, если утилита MAKE вызывается следующей командной строкой:
make -a
но в формирующем файле содержится директива .noautodeрend, то автоматическая проверка зависимостей будет отменена.
Директива | Параметр |
---|---|
.autodepend | -a |
.ignore | -i |
.noautodepend | -a- |
.noignore | -i- |
.nosilent | -s- |
.noswap | -S- |
.silent | -s |
.swap | -S |
Директивы .AUTODEPEND и .NOAUTODEPEND включают (задают) и выключают (отменяют) автоматическую проверку зависимостей. Они соответствуют параметру -a командной строки.
Директивы .IGNORE и .NOIGNORE указывают утилите MAKE, что нужно игнорировать возвращаемое программой значение, примерно так же, как это делает префикс - перед командой вызова программы (он описан ранее). Эти директивы соответствуют параметру -l командной строки.
Директивы .SILENT и .NOSILENT указывают утилите MAKE, следует ли отображать команды перед их выполнением. Они соответствуют параметру -s командной строки.
Директивы .SWAP и .NOSWAP указывают утилите MAKE, нужно выгружать себя из памяти или нет. Они соответствуют параметру -S командной строки.
.precious:целевой_файл[...]
где "целевой_файл" - это один или более целевых файлов. Директива .precious указывает утилите MAKE, что целевой файл удалять не нужно, даже при неудачном выполнении команд построения целевого файла. В некоторых случаях целевой файл будет допустимым. Например, если к библиотеке нельзя присоединить объектный модуль, то библиотеку удалять не следует. Или если при построении прикладной программы Winsdows выполнение администратора ресурсов завершается неудачно, то выполняемый файл .EXE удалять не следует.
Данная директива, помещенная в формирующий файл, указывает утилите MAKE, где нужно искать файл с заданным расширением имени файла. Например, если в формирующем файле имеются следующие строки:
.PATH.c = C:\CSOURCE .c.obj: BCC -c $* tmр.exe: tmр.obj BCC tmр.obj
то утилита MAKE будет искать файл TMP.C, который является неявно заданным исходным файлом для создания файла TMP.OBJ, в каталоге C:\CSOURCE, а не в текущем каталоге.
Директива .PATH также является макрокомандой, которая содержит значение имени маршрута. Ниже приводится пример использования этой директивы. Исходные файлы содержатся в одном каталоге, объектные файлы - в другом, а все выполняемые файлы - в текущем каталоге.
.PATH.c = C:\CSOURCE .PATH.obj = C:\OBJS .c.obj: BCC -c -o$(.PATH.obj)\$& $< obj.exe: tmр.obj BCC -e$&.exe $< tmр.exe: tmр.obj
В следующем примере MYPROG.OBJ можно создать из файлов MYPROG.ASM, MYPROG.CPP и MYPROG.C:
myprog.exe: myprog.obj: tlink mprog.obj .asm.obj: tasm /mx $< .cpp.obj: bcc -p $< .c.obj: bcc -p- $<
Если доступно более одного из этих исходных файлов, директива .suffixes определяет, какой из них будет использоваться. Директива .suffixes имеет следующий синтаксис:
.suffixes: .исх_расшир...
где ".исх_расшир" - это список расширений, для которых имеются неявные правила, в том порядке, в каком должны использоваться неявные правила.
Например, если мы добавим .suffixes: .asm .c .cpp в начало предыдущего формирующего файла, утилита MAKE сначала будет искать файл MYPROG.ASM, MYPROG..C и наконец MYPROG.CPP.
Директива включения файлов (!include) задает файл, который должен быть включен в формирующий файл для интерпретации в том месте, где располагается эта директива. Данная директива имеет следующую форму:
!include имя_файла
Возможен любой уровень вложенности этих директив. Если директива включения файла пытается включить какой-либо файл, который уже был включен на некотором внешнем уровне вложения (таким образом, что может начаться бесконечный цикл вложения), то внутренняя директива включения игнорируется как ошибочная.
Как можно использовать эту директиву? Предположим, что вы создали файл MODEL.MAC, который содержит следующие строки:
!if !$d(MODEL) MODEL = m !endif
Вы можете использовать представленное условное (используемое в зависимости от выполнения условия) макроопределение в любом формирующем файле, задав следующую директиву:
!include "MODEL.MAC"
Когда утилита MAKE обнаруживает директиву !include, она открывает заданный файл и считывает его содержимое, как если бы строки файла включения являлись бы строками самого формирующего файла.
Директивы условного выполнения (!if, !elif, !else и !endif) предоставляют вам определенную степень гибкости при конструировании формирующих файлов. Правила и макрокоманды можно сделать условными, поэтому, используя в командной строке макроопределения (с помощью параметра -D), можно задавать или отменять интерпретацию определенных разделов формирующих файла.
Формат этих директив аналогичен тому, который используется в Си, ассемблере и Паскале:
!if выражение [строки] . . . !endif !if выражение [строки] . . . !else [строки] . . . !endif !if выражение [строки] . . . !elif выражение [строки] . . . !endif !ifdef макрокоманда [строки] . . . !endif выражение [строки] !ifndef макрокоманда [строки] . . . !endif выражение [строки]
где [строки] могут представлять собой один из следующих типов операторов:
Директивы условного выполнения образуют группу, которая состоит как минимум из открывающей группу директивы !if и завершающей группу директивы !endif.
Любые правила, команды и директивы должны завершаться внутри одного исходного файла.
Всем директивам !if внутри одного исходного файла должны соответствовать директивы !endif. Таким образом, следующее включение файла является неверным вне зависимости от того, какое содержание имеет файл, включающий данный, поскольку в нем не содержится парная директива !endif:
!if $(FILE_COUNT) > 5 какие-либо правила !else другие правила <конец файла>
Еще один способ определения макрокоманды предоставляет директива !ifdef. Директива !ifdef MACRO эквивалентна !if $d(MACRO). Это верно также для директивы !ifndef: директива !ifdef MACRO эквивалентна !if $d(MACRO).
В директивах !if и !elif возможно задание выражений; они используют синтаксис, присущий языку Cи. Выражение вычисляется как обычное 32-битовое целое со знаком.
Вы можете вводить числа как десятичные, восьмеричные или шестнадцатиричные константы. Если вы знаете язык Си, то вы уже знаете, как нужно задавать константы утилите MAKE: форматы одинаковы. Если вы программируете на ассемблере или на Турбо Паскале, то рекомендуем вам внимательно проанализировать приведенные ниже примеры. Ниже приводятся допустимые для утилиты MAKE константы:
4536 | # десятичная константа |
0677 | # восьмеричная константа (различается по начальному нулю) |
0x23aF | # шестнадцатиричная константа (различается по начальной последовательности 0x) |
Операция | Действие |
---|---|
Символы унарных операций: | |
- | унарный минус |
~ | побитовое дополнение (инверсия всех битов) |
! | логическое отрицание NOT (0, если операнд ненулевой, 1 - в противном случае) |
Символы бинарных операций: | |
+ | сложение |
- | вычитание |
* | умножение |
/ | деление |
% | остаток |
>> | сдвиг вправо |
<< | сдвиг влево |
& | поразрядное И (AND) |
| | поразрядное ИЛИ (OR) |
^ | поразрядное исключающее ИЛИ (XOR) |
&& | логическое И (AND) |
|| | логическое ИЛИ (OR) |
> | больше чем |
" | меньше чем |
>= | больше либо равно |
"= | меньше или равно |
== | равенство |
!= | неравенство |
Символ тернарной операции: | |
?: | Операнд перед знаком ? рассматривается как тестовый. |
Символы операций имеют тот же самый приоритет, что и в языке Си. Для группирования операндов в выражении можно использовать круглые скобки. В отличие от языка Си утилита MAKE может сравнивать строки с помощью обычных операций ==, !=, <, >, >= и =>. Числовые (например, + или *) операции со строками использовать нельзя.
Строковые выражения могут содержать пробелы, но в этом случае их нужно заключать в кавычки:
Model = "Medium model" . . . !if $(Model) == "Medium model" CFLAG = -mm !elif $(Model) == "Large model" CFLAG = -m1 !endif
Вы можете вызвать макрокоманды в выражении; будет распознаваться специальная макрокоманда $d(). После того, как произошло расширение всех макрокоманд, синтаксис выражения должен соответствовать установленным требованиям.
Директива выдачи сообщения об ошибке (!error) указывает утилите MAKE, что нужно прервать выполнение и отобразить диагностическое сообщение о неисправимой ошибке, содержащее текст после директивы !error. Данная директива имеет формат:
!error произвольный_текст
Данная директива предназначена для включения в директивы условного выполнения, чтобы заданное пользователем условие определения ошибки могло бы прервать выполнение утилиты MAKE. Например, вы можете вставить перед первым явным правилом следующий код:
!if !$d(MODEL) # если MODEL не определена !error MODEL не определена !endif
Если при подходе к данной точке директива MODEL еще не была определена, то утилита MAKE прекращает выполнение с выдачей следующего сообщения об ошибке:
Fatal makefile 4: Error directive: MODEL не определена
Директива отмены макроопределения (!undef) указывает на необходимость отмены любого определения для заданного макрокоманда. Если в настоящий момент данная макрокоманда не определен, то данная директива действовать не будет. Директива имеет следующий синтаксис:
!undef имя_макрокоманды
Назад | Содержание | Вперед