Значение $* - a Значение $@ - a.t Значение $? - file.h a.c Значение $< - a.c Действия правила .c.t : Значение $* - b Значение $@ - b.t Значение $? - file.h b.c Значение $< - b.c Действия правила .c.t : Значение $* - c Значение $@ - c.t Значение $? - file.h c.c Значение $< - c.c Действия правила result - 24 - Значение $@ - result Значение $? - d.t a.t b.t c.t Заметим, что правило .k.t выполняется только один раз, пра- вило .c.t - три раза, как и требовалось для списка исходных файлов, указанных в списке подцелей правила result. Смысл макропеременной "?" в правиле с суффиксом тот же, что и в обычном файле - список подцелей. Макропеременная "@" в обыч- ном правиле - имя цели, а здесь имя результата - файл с име- нем основа.суффикс_2. Интерпретатор make содержит список правил для стандарт- ных суффиксов имен файлов и определения самих суффиксов. Этот список подключается к Make-программе пользователя, если make запускается на выполнение без ключа -r. Программист полностью освобождается от указания правил преобразований файлов со стандартными суффиксами имен. Обрабатываются файлы, имена которых включают следующие суффиксы: .out - файл в загрузочном формате; .o - объектный файл; .c - файл на языке Си; .f - файл на языке Фортран; .p - файл на языке Паскаль; .s - файл на ассемблере; .l - файл на lex; .y - файл на yacc; Кроме того, в Make-программу включаются предопределенные макропеременные: LOADLIBES = # имена библиотек AS = as - # имя ассемблера CC = cc # имя Си-компилятора CFLAGS = # ключи Си-компилятора PC = pc # имя Паскаль-компилятора PFLAGS = # ключи Паскаль-компилятора FF = f77 # имя f77-компилятора FFLAGS = # ключи f77-компилятора LEX = lex # имя генератора LFLAGS = # ключи lex YACC = yacc # имя генератора YFLAGS = # ключи yacc Значения предопределенных макропеременных можно менять в Make-программе, например, если ввести строку CFLAGS = -O, то предопределенная макропеременная CFLAGS будет иметь новое значение в Make-программe. Ниже приводятся граф зависимос- тей целей и список правил Make-программы, реализующей обра- ботку файлов по суффиксам имен. - 25 - .c .f .p .s .l .y | | | | | | |------------------------- | | ---> .out <--- .o --- | | -------------------------- | | | | | | .p .f .c .s .l .y | --- | | .l .y - 26 - .l.out: $(LEX) $< $(CC) $(CFLAGS) lex.yy.c $(LOADLIBES) -ll -o $@ rm lex.yy.c .y.out: $(YACC) $(YFLAGS) $< $(CC) $(CFLAGS) y.tab.c $(LOADLIBES) -ly -o $@ rm y.tab.c .f.out: $(FF) $(FFLAGS) $< $(LOADLIBES) -o $@ -rm $*.o .o.out: $(CC) $(CFLAGS) $< $(LOADLIBES) -o $@ .c.out: $(CC) $(CFLAGS) $< $(LOADLIBES) -o $@ .p.out: $(PC) $(PFLAGS) $< $(LOADLIBES) -o $@ .s.out: $(CC) $(CFLAGS) $< $(LOADLIBES) -o $@ .l.c: $(LEX) $< mv lex.yy.c $@ .y.c: $(YACC) $(YFLAGS) $< mv y.tab.c $@ .l.o: $(LEX) $(LFLAGS) $< $(CC) $(CFLAGS) -c lex.yy.c rm lex.yy.c; mv lex.yy.o $@ .y.o: $(YACC) $(YFLAGS) $< $(CC) $(CFLAGS) -c y.tab.c rm y.tab.c; mv y.tab.o $@ .s.o: $(AS) -o $@ $< .f.o: $(FF) $(FFLAGS) -c $< .c.o: $(CC) $(CFLAGS) -c $< - 27 - .p.o: $(PC) $(PFLAGS) -c $< .SUFFIXES: .out .o .c .f .p .y .l .s Допустим, имеются файлы f[1-6].c с исходными текстами прог- раммы result. Файлы f[1-3].c содержат строки # include file1.h # include file2.h и файлы f[4-6].c содержат строку # include file3.h Следующая программа управляет созданием программы result: CFLAGS = -O LDFLAGS = -s -n -o OBJS = f1.o f2.o f3.o f4.o f5.o f6.o result: ${OBJS} ${CC} ${OBJS} ${LDFLAGS} $@ f1.o f2.o f3.o : file1.h file2.h f4.o f5.o f6.o : file3.h Так выглядит протокол выполнения: cc -O -c f1.c cc -O -c f2.c cc -O -c f3.c cc -O -c f4.c cc -O -c f5.c cc -O -c f6.c cc f1.o f2.o f3.o f4.o f5.o f6.o -s -n -o result Теперь изменим время модификации файла командой touch file3.h и снова выполним программу, в результате получим: cc -O -c f4.c cc -O -c f5.c cc -O -c f6.c cc f1.o f2.o f3.o f4.o f5.o f6.o -s -n -o result Теперь изменим время модификации файла командой touch f3.c и снова выполним программу - 28 - cc -O -c f3.c cc f1.o f2.o f3.o f4.o f5.o f6.o -s -n -o result Программист может отключить стандартные определения и список правил с суффиксами (ключ -r), может их использовать наряду с теми, что определены в Make-программе. Допустим, к имею- щимся файлам предыдущего примера добавляются файлы a1.t, a2.t и a3.t, их необходимо обработать программой sed, выхо- дом которой будут файлы a1.c a2.c a3.c. Теперь Make- программа выглядит так: CFLAGS = -O LDFLAGS = -o OBJS = a1.o a2.o a3.o f1.o f2.o f3.o f4.o f5.o f6.o result: ${OBJS} ${CC} ${OBJS} ${LDFLAGS} $@ f1.o f2.o f3.o : file1.h file2.h f4.o f5.o f6.o : file3.h a1.c: a1.t a2.c: a2.t a3.c: a3.t .t.c: sed s/aaa/bbb/ < $< > $*.c .SUFFIXES: .t Протокол выполнения программы: sed s/aaa/bbb/ < a1.t > a1.c cc -O -c a1.c sed s/aaa/bbb/ < a2.t > a2.c cc -O -c a2.c sed s/aaa/bbb/ < a3.t > a3.c cc -O -c a3.c cc -O -c f1.c cc -O -c f2.c cc -O -c f3.c cc -O -c f4.c cc -O -c f5.c cc -O -c f6.c cc a1.o a2.o a3.o f1.o f2.o f3.o f4.o f5.o f6.o -o result Make допускает обработку суффиксов только одного уровня вло- женности. В правиле SUFFIXES указан только суффикс t, суф- фикс c определен в подключаемом списке суффиксов. - 29 - 8. Управление архивом в Make-программе В ДЕМОС существуют два типа архивов: архив текстовых файлов и архив объектных файлов (имеющий структуру библио- теки объектных модулей). Созданный архив является одним файлом, а файлы, из которых он собран, образуют его части. Управление архивом включает две задачи: создание файла_архива определенной структуры и его модификация (добавление, удаление и замена частей, изменение структуры, декомпозиция архива на файлы, из которых он был образован). Для решения таких задач Make-программа должна обеспечивать работу с целями двух типов: файл_архив и файл для включения в архив. При этом оценивается время последней модификации включаемого в архив файла (а не время создания архива или записи файла_части в архив). Имя файла_архива может указы- ваться в списке зависимостей правил как обычная цель: имя_архивного_файла(имя_файла_для_включения_в_архив) Кроме имен файлов, при работе с библиотекой объектных моду- лей можно указывать имена функций имя_файла_библиотеки((_внешнее_имя_библ_функции)) Рассмотрим фрагмент Make-программы для построения библиотеки с именем libP.a: L = libP.a CFLAGS = -O $(L):: ar r $(L) $(L):: $(L)(Ia.o) $(L)(La.o) $(L)(Da.o) # Iabs, Labs, Dabs - имена функций $(L)(Iabs.o): lib/Ia.c $(CC) $(CFLAGS) lib/Ia.c ar r $(L) Ia.o -rm -f Ia.o $(L)(Labs.o): lib/La.c $(CC) $(CFLAGS) lib/La.c ar r $(L) La.o -rm -f La.o $(L)(Dabs.o): lib/Da.c $(CC) $(CFLAGS) lib/Da.c ar r $(L) Da.o -rm -f Da.o У такого способа работы с библиотекой есть недостаток - - 30 - Make-программа должна содержать структуру библиотеки. Список имен библиотечных модулей во втором правиле "$(L)::" соот- ветствует порядку их размещения в библиотеке. Еще одно неу- добство заключается в том, что если бы библиотека содержала большое количество модулей, например 100, то потребовалась бы запись 100 правил в программе. Для построения однопро- ходных библиотек такой способ указания структуры имеет существенный недостаток, так как изменение исходного текста объектного модуля может привести к необходимости изменить структуру библиотеки, а это, в свою очередь, приведет к необходимости реконструировать Make-программу. Кроме того, при построении библиотеки необходимо, чтобы все объектные файлы были в рабочем каталоге. Рассмотрим Make-программу, в которой эти недостатки устранены. Возьмем в качестве примера файлы с исходными текстами модулей объектной библиотеки mylib m1.c m2.c m3.c m4.s m5.c m6.c m7.s Допустим, структура однопроходной библиотеки с учетом вызо- вов модулей должна быть такой: m4.o m2.o m1.o m5.o m6.o m7.o m3.o Текст Make-программы: - 31 - CFLAGS = -O SRC = m1.c m2.c m3.c m4.s m5.c m6.c m7.s LIB = mylib ${LIB}: ${SRC} echo $? | sed s/\\.[cs]/\\.o/g > list make `cat list` ar cr $@ `cat list` lorder $@ | tsort > list -@if cmp list topology ; \ then \ rm -f `cat list` list;\ else \ ar x ${LIB}; rm $@;\ mv list topology;\ ar cr $@ `cat topology`;\ rm -f `cat topology`;\ echo Структура $@ изменилась.;\ fi ranlib ${LIB} echo Библиотека $@ готова. m1.c : x.h touch m1.c m2.c : x.h y.h touch m2.c m3.c : x.h touch m3.c m5.c : y.h touch m5.c m6.c : x.h touch m6.c Рассмотрим простые случаи реконструкции уже существующей библиотеки. Допустим, изменился исходный текст одного из модулей. В этом случае достаточно на его место в библиотеке включить новую версию объeктного файла этого модуля. Чтобы не компилировать другие файлы библиотеки, можно использовать предопределенную макропеременную "?" - список файлов, кото- рые стали МОЛОЖЕ файла mylib. Как уже говорилось выше, в каталоге нет объектных файлов. Следовательно, в Make- программу необходимо включить предопределенные средства обработки суффиксов, а в качестве аргумента формировать имя цели с суффиксом o, тогда make автоматически построит новый объектный файл этого модуля. В примере файл list использу- ется в качестве временного рабочего файла. Строка вида echo $? | sed s/\\.[cs]/\\.o/g > list - 32 - записывает в файл list список целей с суффиксом o. Редактор sed используется в этой командной строке для замены суффик- сов c и s на o. Таким образом, файл list содержит имена файлов-целей, которые необходимо создать и на этой основе реконструировать библиотеку. Это можно сделать, например, так: make `cat list` В результате выполнения будут созданы нужные объектные файлы. После этого можно включить объектные модули на свои места в библиотеке mylib ar rc mylib `cat list` Если же библиотека mylib отсутствует,то она создается, если модуль в библиотеке исходно отсутствовал, он записывается в конец библиотеки (так работает команда ar с ключами cr). По команде "make `cat list`" выполняться будет Makefile (здесь срабатывает механизм умолчания имени файла с Make- программой). Таким образом, имеет место рекурсивный вызов Make-программы. При рекурсивном вызове в качестве имен целей передаются имена объектных файлов, которые необходимо получить и включить в библиотеку. В интерпретаторе make нет средств, позволяющих менять список целей в процессе выполне- ния Make-программы. Когда это необходимо, список целей соз- дается в Make-программе и передается на выполнение как спи- сок аргументов при вызове подпрограммы. Рекурсия в примере понадобилась для того, чтобы не записывать полный список правил для всех файлов-целей, а вызвать make с актуальным списком аргументов. Возможна такая реконструкция библиотеки, когда меняется ее структура. Для этого в Make-программе используются команды lorder и tsort. Lorder выводит список вызовов моду- лей существующей библиотеки, а tsort сортирует этот список таким образом, чтобы структура библиотеки была непротиворе- чивой, т.е. однопроходный редактор связей мог бы за одно чтение библиотечного файла найти все необходимые модули. В Make-программу включаются действия, в которых строится структура библиотеки во временном файле list и запоминается в сохраняемом файле topology. Возможны следующие случаи реконструкции библиотеки: Реконструкция библиотеки не изменила ее структуры, в этом случае файл topology не отличается от файла list. Реконструкция изменила структуру библиотеки. В этом случае файл topology отличается от файла list и требуется, во-первых, получить верную структуру и запомнить ее в файле topology, во-вторых, извлечь из библиотеки все объектные модули (разобрать библиотеку и удалить файл с библиотекой), - 33 - затем собрать ее в соответствии с новой структурой. Разоб- рать библиотеку можно командой ar x mylib В рабочем каталоге будут созданы копии объектных модулей из библиотечного файла. Библиотечный файл при этом сохраняется. Разобранную библиотеку можно собрать заново, используя информацию о структуре библиотеки в файле topology и команду: ar rc mylib `cat topology` В shell допускается записать if одной строкой следующим образом: if список_команд;\ then \ список_команд;\ else \ список_команд;\ fi В Makefile эта конструкция записана: -@if cmp list topology ; \ then \ rm -f `cat list` list;\ else \ ar x $(LIB); rm $@;\ mv list topology;\ ar cr $@ `cat topology`;\ rm -f `cat topology`;\ echo Структура $@ изменилась.;\ fi Первая строка в ней выглядит так: 'табуляция'-@if cmp list topology ; \ Остальные строки имеют более 8 ведущих пробелов. Символ "-" указан, так как в отдельных версиях shell оператор if при нормальном завершении возвращает не 0. Символ "@" отменяет вывод этой строки перед выполнением. Приведенная Make-программа позволяет работать с любыми объектными библиотеками. Для конкретной библиотеки (или архива) нужно изменить макропеременные LIB, SRC и записать зависимости от файлов включений. Если необходимо работать с текстовыми архивами, то достаточно удалить строку ranlib $@. Рассмотрим на примерах работу программы при различных исходных условиях. - 34 - Библиотеки нет, структура неизвестна make -s cc -c m1.c cc -c m2.c cc -c m3.c as - -o m4.o m4.s cc -c m5.c cc -c m6.c as - -o m7.o m7.s cmp: не могу открыть topology Структура mylib изменилась. Библиотека mylib готова. Библиотека mylib имеется, структура остается без изме- нений, модифицируется файл x.h touch x.h make -s cc -c m1.c cc -c m2.c cc -c m3.c cc -c m6.c Библиотека mylib готова. Меняется содержимое библиотечного модуля m5.c. Меня- ется структура библиотеки: модуль m5 вызывает теперь модуль m1 make -s cc -c m5.c Структура mylib изменилась. Библиотека mylib готова. В файле topology теперь новая структура библиотеки m4.o m2.o m5.o m1.o m6.o m7.o m3.o Добавляется новый модуль в библиотеку. Придется изме- нить строку SRC в Make-программе. Имя модуля m8.c , вызы- вает он модуль m5.c cc -c m8.c list topology различны: char 12, line 3 Структура mylib изменилась. Библиотека mylib готова. В файле topology теперь новая структура библиотеки m4.o m2.o m8.o m5.o m1.o m6.o m7.o m3.o - 35 - Изменим модуль m1.c так, чтобы он вызывал модуль m2.c, а модуль m2.c вызывал m1.c, т.е. получается зацикленная вза- имная зависимость библиотечных модулей m1 и m2 make -s cc -c m1.c tsort: зацикленная зависимость tsort: m2.o tsort: m1.o Структура mylib изменилась. Библиотека mylib готова. Команда tsort вывела сообщение об ошибке в структуре библио- теки. Библиотека собрана, но пользоваться ею нельзя, необ- ходимо исправить структуру модуля. Удалять файл mylib не нужно, так как он содержит все объектные модули, которые понадобятся для новой сборки. 9. Особенности программирования на языке Make Всюду в примерах Make-программа размещалась в одном Makefile. Существует возможность разместить ее в файле с другим именем и при вызове интерпретатора make указать это имя make -f имя_файла Иногда возникает необходимость использовать несколько Make- файлов, образующих одну Make-программу, тогда при вызове make можно указать make -f имя_файла1 -f имя_файла2 и т.д. Указанные файлы составят текст одной Make-программы в том порядке, в котором они указаны в командной строке. Внутри одной Make-программы можно вызывать make на выполнение другой Make-программы, например: LLL: a b c d make -k -f имя_Make-файла $? В том случае, если эта командная строка не может быть нор- мально выполнена, ключ -k указывает на необходимость продол- жить выполнение других разделов Make-программы, которые не зависят от цели данного правила. Если в этом примере не указать имя файла, в котором размещена Make-программа, то автоматически будет выполняться Makefile и будет иметь место рекурсивный вызов на выполнение одной программы. Есть некоторые особенности при использовании макропере- менных. Допустим, в Make-программе указана строка - 36 - SRC = a1.c a2.c a3.c # комментарий Между a3.c и символом # 9 пробелов, они будут передаваться всюду, где будет использовано значение макропеременной SRC. Предопределенные макропеременные "<" и "*" в правилах без суффиксов не определены, и их использование может при- вести к непредсказуемым результатам. Все, что указано за символом табуляция в строке дейст- вий передается на выполнение shell. Однако идущие за симво- лом табуляция символы "-" и "@" обрабатываются make. Интерпретатор make оптимизирует скорость выполнения дейст- вий. Если строка действий - простая команда системы, она выполняется без порождения процесса shell. По этой причине, например, такая строка вызовет состояние ошибки 'табуляция'#cat file Действительно, как бы выполнялась строка "exec(# cat file);" в Си-программе? Если в списке зависимостей отсутствуют имена подцелей, можно использовать сокращенную форму записи правила с одним действием. Оно имеет вид: имя_цели:[:]; одна_строка_действия [# комментарий] символ ";" обязателен. Особую осторожность необходимо соблюдать при указании в Make-программе имени цели, которая не является файлом. В этом случае программист должен учитывать, что он сознательно исключает возможность использования этой цели при реконст- рукциях, так как она не связана соотношениями времен созда- ния (модификации) с другими объектами Make-программы. Это препятствие можно обойти, создавая ЛОЖНЫЙ файл-цель, напри- мер: print: f1 f2 f3 print $? touch print .DEFAULT: touch print В рабочем каталоге создан пустой файл с именем print. Теперь выводиться на печать будут только те файлы, которые требу- ется распечатать как изменившиеся. Правило DEFAULT записано на тот случай, когда файл print отсутствует. Команду touch можно использовать, когда необходимо раз- рушить динамическую структуру связей между файлами. Надо - 37 - учитывать, что при этом make будет реконструировать все файлы заново. Ниже перечислены все ключи интерпретатора make и их действие: -d отладочный режим, в котором выводится дополнительная информация о выполнении Make-программы. -f следующий параметр является именем Make-файла. По умол- чанию ищется Makefile или makefile. Если имеются оба, то выполняется Makefile. В командной строке можно ука- зать несколько ключей -f и параметров. -i режим игнорирования кодов завершения команд не равных нулю. Эквивалентно директиве IGNORE. -k если код завершения команды не равен нулю, прекратить выполнение текущего правила и перейти к выполнению дру- гих разделов, не зависящих от файла-цели этого правила. -n вывести, но не выполнять строки действий Make- программы. -p вывести полную информацию о структуре Make-программы. -q получить информацию о необходимости реконструкции цели. Если реконструкция указанной цели не требуется, возвра- щается -1, иначе 0. -r отменяет предопределенную обработку правил с суффик- сами, предопределенные макропеременные и суффиксы. -s отменить вывод выполняемых строк. Эквивалентно дирек- тиве SILENT. -S прервать выполнение Make-программы при ошибочном завер- шении какой-либо команды. -t уничтожить сложившуюся структуру динамических (завися- щих от времени) связей между файлами. 10. Автоматизация программирования Make-программ Для создания новой Make-программы можно иметь файл- шаблон, добавляя в него необходимые строки мы получим гото- вую к использованию программу. Такой принцип реализован в программе mkmf. Рассмотрим ее работу на примере. Пусть име- ются исходные файлы f.h, f1.c, f2.c и f3.c, из которых необ- ходимо получить файл a.out: - 38 - /* ** файл f.h */ # include <stdio.h> # include <ctype.h> # include <time.h> /* ** файл f1.c */ # include f.h main(ac, av) int ac; char **av; { f1(); f2(); f3(); printf("Результат выполнения программы example.\n"); } f1(){ return; } /* ** файл f2.c */ # include f.h int f2(){ return( a2()); } # include <stat.h> char *a2(){ return; } /* ** файл f3.c */ # include f.h int f3(){ return( nn()); } char *nn(){ return; } Пусть все эти файлы размещены в одном каталоге. Выполним команду mkmf. В результате ее выполнения будет создан Makefile с программой сборки файла a.out: - 39 - DEST = . EXTHDRS = /usr/include/ctype.h \ /usr/include/stat.h \ /usr/include/stdio.h \ /usr/include/time.h HDRS = f.h LDFLAGS = LIBS = LINKER = cc MAKEFILE = Makefile OBJS = f1.o f2.o f3.o PRINT = pr PROGRAM = a.out SRCS = f1.c f2.c f3.c all: $(PROGRAM) $(PROGRAM): $(OBJS) $(LIBS) @echo -n "Сборка $(PROGRAM) ..." @$(LINKER) $(LDFLAGS) $(OBJS) \ $(LIBS) -o $(PROGRAM) @echo "готово." clean:; @rm -f $(OBJS) depend:; @mkmf -f $(MAKEFILE) \ PROGRAM=$(PROGRAM) DEST=$(DEST) index:; @ctags -wx $(HDRS) $(SRCS) install: $(PROGRAM) @echo Установка $(PROGRAM) в $(DEST) @install -s $(PROGRAM) $(DEST) print:; @$(PRINT) $(HDRS) $(SRCS) program:; $(PROGRAM) tags: $(HDRS) $(SRCS) @ctags $(HDRS) $(SRCS) update: $(DEST)/$(PROGRAM) - 40 - $(DEST)/$(PROGRAM): $(SRCS) $(LIBS) \ $(HDRS) $(EXTHDRS) @make -f $(MAKEFILE) \ DEST=$(DEST) install ### f1.o: f.h /usr/include/stdio.h \ /usr/include/ctype.h \ /usr/include/time.h f2.o: f.h /usr/include/stdio.h \ /usr/include/ctype.h \ /usr/include/time.h \ /usr/include/stat.h f3.o: f.h /usr/include/stdio.h \ /usr/include/ctype.h \ /usr/include/time.h Программой mkmf в качестве исходного файла-шаблона использо- ван стандартный файл /usr/new/lib/p.Makefile, но можно ука- зать для использования и любой другой. Программа mkmf работает следующим образом: сначала выбираются и вносятся в файл-шаблон имена всех исходных фай- лов рабочего каталога, далее определяется от каких include- файлов зависят исходные файлы, формируются правила и записы- ваются в файл-шаблон. Для обозначения исходных файлов используются правила с суффиксами. Makefile можно редактировать, изменять значения макро- переменных. При этом, если повторить вызов программы mkmf, в нем появятся только те изменения, которые необходимы для сборки с учетом изменений в исходных текстах. В Makefile, полученном из стандартного файла-шаблона, определены следующие макропеременные: CFLAGS ключи Си-компилятора; DEST каталог, в котором будет размещен результат; EXTHDRS перечень полных имен include-файлов; HDRS перечень имен include-файлов, размещенных в рабочем каталоге; LIBS список объектных библиотек для сборки программы; - 41 - MAKEFILE имя файла с Make-программой; OBJS список объектных файлов, участвующих в сборке прог- раммы; PROGRAM имя программы, которую необходимо получить; SRCS список имен всех файлов с исходными текстами; Значения макропеременных EXTHDRS, HDRS, OBJS, SRCS устанавливаются программой mkmf и всегда имеют актуальные значения. Остальные макропеременные получают при создании Makefile значения по умолчанию, их можно изменять по своему усмотрению. Рассмотрим правила Make-программы, котороые можно использовать как самостоятельные входы: all трансляция, сборка и запуск на выполнение полученной программы; clean удаление ненужных файлов; depend изменение структуры Make-программы с учетом существую- щего Makefile; index печать индексов функций собираемой программы; install трансляция, сборка и установка программы в указанный каталог; print печать include-файлов и текстов программы; tags создание файла ./tags - ссылок программ, написанных на языках Си, Паскаль и Фортран; update изменение Makefile, перегенерация, сборка и установка программы в указанный каталог. С учетом произошедших изменений в текстах исходных файлов будет выполнено только то, что необходимо в данный момент времени. - 42 - Пусть имеются файлы f[123].c, f.h и Makefile, заменим в нем значение макропеременной DEST на /usr/tmp и макропере- менной PROGRAM - на example. Выполним следующую командную строку: % make program install clean получим на экране сообщение cc -c f1.c cc -c f2.c cc -c f3.c Сборка example ... готово. Результат выполнения программы example Установка example в /usr/tmp Выполним командную строку % make index получим имена функций и места их определений a2 5 f2.c char *a2(){ f1 11 f1.c f1(){ f2 2 f2.c int f2(){ f3 2 f3.c int f3(){ main 5 f1.c main(ac, av) nn 6 f3.c char *nn(){ Программа mkmf позволяет создавать Makefile для сборки биб- лиотеки. Для этого используется файл-шаблон /usr/new/lib/l.Makefile и дополнительно вводятся макропере- менная LIBRARY (имя библиотеки) и правила extract (извлече- ние из библиотеки всех частей в виде отдельных файлов), library (трансляция и загрузка библиотеки). Программист может отказаться от стандартных файлов- шаблонов /usr/new/lib/[lp].Makefile и создать свои шаблоны в рабочем каталоге. Файлы шаблоны должны иметь имена l.Makefile и p.Makefile. - 43 - ЛИТЕРАТУРА 1. "Банахан М., Раттер Э. Введение в операционную систему UNIX. - М.: Радио и связь, 1986." AI 2. "Баурн С. Операционная система UNIX.- М.: Мир, 1986." AN 3. "Браун П. Введение в операционную систему UNIX. - М.: Мир, 1987." AM 4. "Готье Р. Руководство по операционной системе UNIX. - М.: Финансы и статистика, 1985." AE 5. "Диалоговая единая мобильная операционная система ДЕМОС. - Калинин: ЦЕНТРПРОГРАММСИСТЕМ, 1985." AK 6. "Инструментальная мобильная операционная система ИНМОС/ М.И. Беляков, А.Ю. Ливеровский, В.П. Семик и др. - М.: Финансы и статистика, 1985." AH 7. "Керниган Б., Ритчи Д., Фьюер А. Язык программирования Си. Задачи по языку Си. - М.: Финансы и статистика, 1985." AF 8. "Кристиан К. Введение в операционную систему UNIX. - М.: Финансы и статистика, 1985." AJ 9. "Хенкок Л., Кригер М. Введение в программирование на языке СИ. - М.: Радио и связь, 1986." AG 10. "Aho A. V., Kernighan Brian V. W., Weinberger Peter J. AWK - a pattern scanning and processing language. Second edition. UNIX Programmers manual, 42 BSD, 1980. Bell Laboratries: Murray Hill, New Jersey, 1978." AL 11. "Feldman S. I. Make - a program maitaining computer pro- gramms. Bell Laboratries: Murray Hill, New Jersey, 1978." AB 12. "Joy W. N. An introduction the UNIX C-shell. UNIX Pro- grammers manual, 42 BSD, 1980. Bell Laboratries: Murray Hill, New Jersey, 1978." AA 13. "Johnson S. C. YACC - yet another compiler-compiler. Comp. Sci. tech. rep. N 32. Bell Laboratries: Murray Hill, New Jersey, 1975." AD 14. "Lesk M. E. Lex - lexical analyzer generator. Comp. Sci. tech. rep. N 39. Bell Laboratries: Murray Hill, New Jer- sey, 1975." AC - 44 - СОДЕРЖАНИЕ АННОТАЦИЯ ......................................... 2 1. Введение .......................................... 3 2. Принципы выполнения Make-программы ................ 4 3. Соглашения языка Make ............................. 10 4. Использование макропеременных ..................... 13 5. Выполнение правил в Make-программе ................ 16 6. Режимы выполнения Make-программы .................. 18 7. Правила с суффиксами .............................. 21 8. Управление архивом в Make-программе ............... 30 9. Особенности программирования на языке Make ........ 36 10. Автоматизация программирования Make-программ ...... 38 ЛИТЕРАТУРА ........................................ 44 - 45 -