stringtranslate.com

Марка (программное обеспечение)

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

Make широко используется, особенно в Unix и Unix-подобных операционных системах , хотя доступно множество конкурирующих технологий и инструментов, включая: похожие инструменты, которые выполняют действия на основе зависимостей, некоторые компиляторы и интерактивно через интегрированную среду разработки .

Помимо ссылки на оригинальный инструмент Unix , Make также является технологией, поскольку было реализовано несколько инструментов с примерно одинаковой функциональностью, включая схожий синтаксис и семантику make-файлов .

Источник

Стюарт Фельдман создал Make, работая в Bell Labs . Ранняя версия была завершена в апреле 1976 года. [1] [2] [3] Фельдман получил премию ACM Software System Award 2003 за создание Make. [4]

Фельдман описывает, что вдохновение на написание Make пришло из-за разочарования коллеги по работе в доступном на тот момент инструментарии:

Make возник из-за визита Стива Джонсона (автора yacc и т. д.), который ворвался в мой офис, проклиная Судьбу, которая заставила его потратить утро на отладку правильной программы (ошибка была исправлена, файл не был скомпилирован, cc *.oпоэтому не был затронут). Поскольку я провел часть предыдущего вечера, борясь с той же катастрофой в проекте, над которым я работал, возникла идея инструмента для ее решения. Все началось с тщательно продуманной идеи анализатора зависимостей, свелось к чему-то гораздо более простому и превратилось в Make в те выходные. Использование инструментов, которые еще не были готовы, было частью культуры. Makefiles были текстовыми файлами, а не магически закодированными двоичными файлами, потому что таков был дух Unix : печатаемые, отлаживаемые, понятные вещи.

До Make сборка на Unix в основном состояла из скриптов оболочки , написанных для кодовой базы каждой программы. Упорядочивание зависимостей и проверка на устаревание в Make делают процесс сборки более надежным и эффективным. Makefile позволял лучше организовать логику сборки и часто использовать меньше файлов сборки.

Make широко используется отчасти из-за его раннего включения в Unix , начиная с PWB/UNIX 1.0, в котором было представлено множество инструментов разработки программного обеспечения. [3]

Варианты

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

POSIX включает стандартизацию основных функций и работы утилиты Make и реализован с различной степенью совместимости с версиями Make на базе Unix. В общем случае простые make-файлы могут использоваться между различными версиями Make с приемлемым успехом. GNU Make, Makepp и некоторые версии BSD Make по умолчанию сначала ищут файлы с именами "GNUmakefile", [35] "Makeppfile" [36] и "BSDmakefile" [37] соответственно, что позволяет размещать make-файлы, использующие поведение, определяемое реализацией, в отдельных местах.

Использовать

В общем, на основе makefile, Make обновляет целевые файлы из исходных файлов, если какой-либо исходный файл имеет более новую временную метку , чем целевой файл, или целевой файл не существует. Например, это может включать компиляцию файлов C*.c ( ) в объектные файлы , а затем связывание объектных файлов в исполняемую программу. Или это может включать компиляцию файлов TypeScript ( *.ts) в JavaScript для использования в браузере. Другие примеры включают: преобразование исходного файла изображения в другой формат, копирование файла в систему управления контентом и отправку электронного письма о статусе сборки.

Makefile определяет цели, каждая из которых представляет собой либо файл для генерации, либо определенную пользователем концепцию, называемую фиктивной целью.

Обновите цели, переданные в качестве аргументов:

сделать [ -f makefile ] [ опции ] [ цели ]    

Если цель не указана, Make обновляет первую цель в make-файле, которая часто является фиктивной целью для выполнения наиболее часто используемого действия.

Make пропускает действия сборки, если временная метка целевого файла находится после временной метки исходных файлов. [38] Это оптимизирует процесс сборки, пропуская действия, когда целевой файл актуален, но иногда обновления ошибочно пропускаются из-за проблем с временной меткой файла, включая восстановление более старой версии исходного файла, или когда сетевая файловая система является источником файлов, а ее часы или часовой пояс не синхронизированы с машиной, на которой запущен Make. Кроме того, если временная метка исходного файла находится в будущем, make многократно запускает ненужные действия, что приводит к увеличению времени сборки.

При запуске Make он использует makefile, указанный в командной строке, или, если он не указан, то использует тот, который найден с помощью определенных правил поиска. Обычно Make по умолчанию использует файл в рабочем каталоге с именем Makefile . GNU Make ищет первый подходящий файл: GNUmakefile , makefile или Makefile .

Make обрабатывает параметры командной строки на основе загруженного make-файла.

Makefile

Язык makefile представляет собой частично декларативное программирование , в котором описаны конечные условия, но не порядок выполнения действий. [40] [41] [42] [43] Этот тип программирования может сбивать с толку программистов, привыкших к императивному программированию .

Makefiles могут содержать следующие конструкции: [44]

Правила

Каждое правило начинается со строки зависимости , которая состоит из имени цели правила, за которым следует двоеточие (:) и, по желанию, список целей, от которых зависит цель правила, его предварительных условий. [45]

цель [цель ...]: [компонент ...] Tab ↹[команда 1] . . .Tab ↹[команда n]

Обычно правило имеет одну цель, а не несколько.

За строкой зависимости может следовать рецепт; ряд командных строк с отступом TAB , которые определяют, как сгенерировать цель из компонентов (т. е. исходных файлов). Если какое-либо предварительное условие имеет более позднюю временную метку, чем целевой файл, или цель не существует как файл, рецепт выполняется.

Первая команда может располагаться на той же строке после предварительных условий, разделенных точкой с запятой.

цели : предпосылки  ; команда 

например,

привет :  ; @ echo " привет "

Каждая командная строка должна начинаться с символа табуляции. Несмотря на то, что пробел также является пробелом , Make требует табуляции. Поскольку это часто приводит к путанице и ошибкам, этот аспект синтаксиса makefile подвергается критике; Эрик С. Рэймонд описал его как «один из худших ляпов дизайна в истории Unix» [46] , а в The Unix-Haters Handbook сказано: «использование табуляции как части синтаксиса похоже на одну из тех ловушек-палок в «Зеленых беретах »». Фельдман объясняет этот выбор как решение , вызванное необходимостью обойти раннюю сложность реализации, сохраненную желанием обеспечить обратную совместимость с самыми первыми пользователями:

Почему табуляция в колонке 1? Yacc был новым, Lex был совершенно новым. Я не пробовал ни того, ни другого, поэтому решил, что это будет хорошим поводом научиться. После того, как я запутался в своей первой попытке с Lex, я просто сделал что-то простое с шаблоном newline-tab. Это сработало, это осталось. А затем, через несколько недель, у меня было около дюжины пользователей, большинство из которых были друзьями, и я не хотел портить свою встроенную базу. Остальное, к сожалению, уже история.

—  Стюарт Фельдман [46]

GNU Make, начиная с версии 3.82, позволяет выбирать любой символ (один символ) в качестве префикса рецепта с помощью специальной переменной .RECIPEPREFIX, например:

.RECIPEPREFIX := : all : :@echo "символ префикса рецепта установлен на '$(.RECIPEPREFIX)'"   

Каждая команда выполняется в отдельной оболочке . Поскольку операционные системы используют разные оболочки, это может привести к непереносимым make-файлам. Например, GNU Make (все Make POSIX) по умолчанию выполняет команды с /bin/sh , где обычно используются команды Unix, такие как cp . В отличие от этого, nmake от Microsoft выполняет команды с cmd.exe, где доступны пакетные команды, такие как copy , но не обязательно cp.

Поскольку рецепт необязателен, строка зависимости может состоять исключительно из компонентов, которые ссылаются на другие цели, например:

realclean : чистый distclean  

Следующий пример правила оценивается, когда Make обновляет целевой file.txt; т. е. через make file.txt. Если file.html новее file.txt или file.txt не существует, то запускается команда для генерации file.txt из file.html.

файл.txt : файл . html lynx -dump файл.html > файл.txt     

Команда может иметь один или несколько из следующих префиксов (после табуляции):

Игнорирование ошибок и подавление эха можно также осуществить с помощью специальных целей .IGNOREи .SILENT. [47]

В NMAKE от Microsoft есть предопределенные правила, которые можно исключить из этих make-файлов, например .c.obj $(CC)$(CFLAGS)

Макросы

Makefile может определять и использовать макросы. Макросы обычно называются переменными , когда они содержат простые определения строк, например . Макросы в makefile могут быть переопределены в аргументах командной строки, переданных утилите Make. Переменные среды также доступны как макросы.CC=clang

Например, макрос CCчасто используется в makefile для указания местоположения компилятора C. Если он используется последовательно во всем makefile, то используемый компилятор можно изменить, изменив значение макроса, а не изменяя каждую команду правила, которая вызывает компилятор.

Макросы обычно именуются заглавными буквами :

МАКРО = определение  

Значение макроса может состоять из других значений макроса. Значение макроса расширяется при каждом использовании ( лениво ).

Макрос используется путем расширения либо через $ NAME , либо через $( NAME ). Последний вариант безопаснее, поскольку пропуск скобок приводит к тому, что Make интерпретирует следующую букву после $как полное имя переменной. Эквивалентная форма использует фигурные скобки вместо круглых скобок, т.е. ${}, что является стилем, используемым в BSD .

НОВЫЙ_МАКРОС = $( МАКРОС ) - $( МАКРОС2 )  

Макросы могут быть составлены из команд оболочки с помощью оператора подстановки команд!= , . [48]

ГГГГММДД != дата  

Синтаксис командной строки для переопределения макроса:

сделать МАКРОС = "значение" [ МАКРОС = "значение" ... ] ЦЕЛЬ [ ЦЕЛЬ ... ]      

Makefiles могут получать доступ к предопределенным внутренним макросам , причем ?и @являются общими.

цель : компонент 1 компонент 2 # echo компоненты МОЛОЖЕ ЦЕЛИ echo $? # echo имя ЦЕЛИ echo $@    

Обычный синтаксис при определении макросов, который работает в BSD и GNU Make, заключается в использовании += , ?= и != вместо знака равенства ( = ). [49]

Правила суффиксов

Правила суффиксов имеют «цели» с именами в форме .FROM.TOи используются для запуска действий на основе расширения файла. В командных строках правил суффиксов POSIX указывает [50] , что внутренний макрос $<ссылается на первое предварительное условие и $@ссылается на цель. В этом примере, который преобразует любой файл HTML в текст, токен перенаправления оболочки >является частью командной строки, тогда как $<является макросом, ссылающимся на файл HTML:

.СУФФИКСЫ :  . txt . html# Из .html в .txt .html.txt : lynx  -dump  $<  > $@ 

При вызове из командной строки приведенный выше пример расширяется.

$ make  -n  file.txt lynx -dump file.html > file.txt

Правила шаблона

Правила суффиксов не могут иметь никаких собственных предварительных условий. [51] Если они есть, они рассматриваются как обычные файлы с необычными именами, а не как правила суффиксов. GNU Make поддерживает правила суффиксов для совместимости со старыми makefiles, но в остальном поощряет использование шаблонных правил . [52]

Правило шаблона выглядит как обычное правило, за исключением того, что его цель содержит ровно один %символ в строке. Цель считается шаблоном для сопоставления имен файлов: %может соответствовать любой подстроке из нуля или более символов, [53] в то время как другие символы соответствуют только себе. Предпосылки также используются %для показа того, как их имена соотносятся с именем цели.

Приведенный выше пример правила суффикса будет выглядеть как следующее шаблонное правило:

# Из %.html в %.txt %.txt :  %. html  lynx  -dump  $<  > $@ 

Комментарий

Однострочные комментарии начинаются с символа решетки (#).

Директива

Директива определяет особое поведение, например включение другого make-файла.

Продолжение линии

Продолжение строки обозначается \символом обратной косой черты в конце строки.

 цель: компонент \ компонент Tab ↹команда ; \ команда | \ конвейерная-командаTab ↹Tab ↹

Примеры

Следующие команды находятся в контексте следующего make-файла.

make # обновляет первую цель, «все»
make help # обновляет цель «help» для получения списка целей
make dist # обновляет цель «dist» для сборки для распространения     
ПАКЕТ = ВЕРСИЯ пакета = ` дата "+%Y.%m%d%" ` КАТАЛОГ_ВЫПУСКА = .. ФАЙЛ_ВЫПУСКА = $( ПАКЕТ ) - $( ВЕРСИЯ )           # Цель по умолчанию # примечание: переменная LOGNAME берется из окружения all : echo "Привет $( LOGNAME ) , по умолчанию ничего не нужно делать" echo "Попробуйте 'make help'"  # Отображение целей при поиске в этом файле help : egrep "^# target:" [ Mm ] akefile  # Создайте дистрибутив : tar -cf  $ ( RELEASE_DIR ) / $( RELEASE_FILE ) && \ gzip -9 $( RELEASE_DIR ) / $( RELEASE_FILE ) .tar     

Ниже приведен простой makefile, который по умолчанию (правило «all» указано первым) компилирует исходный файл с именем «helloworld.c» с помощью системного компилятора C, а также предоставляет «чистую» цель для удаления сгенерированных файлов, если пользователь захочет начать заново. Макросы $@и $<являются двумя из так называемых внутренних макросов (также известных как автоматические переменные) и обозначают имя цели и «неявный» источник соответственно. В примере ниже $^расширяется до списка предпосылок, разделенных пробелами. Существует ряд других внутренних макросов. [50] [54]

CFLAGS ?= -g  все : привет мир helloworld : helloworld . o $( CC ) $( LDFLAGS ) -o $@ $^     helloworld.o : приветмир . c $( CC ) $( CFLAGS ) -c -o $@ $<      очистить : $( RM ) helloworld helloworld.o  

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

все : привет мир helloworld : helloworld . o $( CC ) $( CFLAGS ) $( LDFLAGS ) -o $@ $^      очистить : $( RM ) helloworld helloworld.o  # правило суффикса .co : $( CC ) $( CFLAGS ) -c $<   .СУФФИКСЫ :  . c


То, что "helloworld.o" зависит от "helloworld.c", теперь автоматически обрабатывается Make. В таком простом примере, как проиллюстрированный здесь, это едва ли имеет значение, но настоящая сила правил суффиксов становится очевидной, когда количество исходных файлов в программном проекте начинает расти. Нужно только написать правило для шага связывания и объявить объектные файлы в качестве предпосылок. Затем Make неявно определит, как создать все объектные файлы, и будет искать изменения во всех исходных файлах.

Простые правила суффиксов работают хорошо, пока исходные файлы не зависят друг от друга и от других файлов, таких как файлы заголовков. Другой способ упростить процесс сборки — использовать так называемые правила сопоставления шаблонов, которые можно объединить с генерацией зависимостей с помощью компилятора. В качестве последнего примера, требующего компилятора gcc и GNU Make, вот общий makefile, который компилирует все файлы C в папке в соответствующие объектные файлы, а затем связывает их с конечным исполняемым файлом. Перед компиляцией зависимости собираются в формате, удобном для makefile, в скрытый файл ".depend", который затем включается в makefile. Переносимые программы должны избегать конструкций, используемых ниже.

# Универсальный GNUMakefile# фрагмент, который будет отклонен, если не GNU ifneq (,) Для этого make-файла требуется GNU Make. endif    PROGRAM = foo C_FILES := $( wildcard *.c ) OBJS := $( patsubst %.c, %.o, $( C_FILES )) CC = cc CFLAGS = -Wall -pedantic LDFLAGS = LDLIBS = -lm                  все : $( ПРОГРАММА ) $(PROGRAM) :  . depend  $( OBJS ) $( CC ) $( CFLAGS ) $( OBJS ) $( LDFLAGS ) -o $( PROGRAM ) $( LDLIBS )      зависеть :  . зависеть.depend : cmd = gcc - MM - MF depend $( var ) ; cat depend >> .depend ; .depend : @echo "Создание зависимостей..." @ $( foreach var, $( C_FILES ) , $( cmd )) @rm -f depend          -включить .зависит# Это правила сопоставления с образцом. В дополнение к автоматическим переменным, # используемым здесь, переменная $*, которая соответствует всему, что обозначает %, # может быть полезна в особых случаях. %.o :  %. c $( CC ) $( CFLAGS ) -c $< -o $@     % :  %. o $( CC ) $( CFLAGS ) -o $@ $<    очистить : rm  -f  .depend $( OBJS ) .PHONY : чистый , зависит  

Отслеживание зависимости

Makefile состоит из зависимостей, и забытая или лишняя зависимость может быть не сразу очевидна пользователю и может привести к тонким ошибкам в сгенерированном программном обеспечении, которые трудно обнаружить. Можно использовать различные подходы, чтобы избежать этой проблемы и синхронизировать зависимости в исходном коде и makefile. Один из подходов — использовать компилятор для отслеживания изменений зависимостей. Например, GCC может статически анализировать исходный код и автоматически создавать правила для данного файла с помощью -MMswitch. Другой подход — makefile или сторонние инструменты, которые будут генерировать makefile с зависимостями (например, Automake toolchain от GNU Project , может делать это автоматически).

Другой подход — использовать инструменты метасборки, такие как CMake , Meson и т. д.

Смотрите также

Ссылки

  1. ^ "V7/usr/src/cmd/make/ident.c". tuhs.org . 1 сентября 2013 г. Архивировано из оригинала 1 сентября 2013 г. Получено 18 марта 2018 г.
  2. ^ Фельдман, СИ (апрель 1979). «Создать --- программу для обслуживания компьютерных программ». Программное обеспечение: практика и опыт . 9 (4): 255–265. CiteSeerX 10.1.1.39.7058 . doi :10.1002/spe.4380090402. S2CID  33059412. 
  3. ^ ab Thompson, TJ (ноябрь 1980 г.). «Designer's Workbench: Providing a Production Environment». Bell System Technical Journal . 59 (9): 1811–1825. doi :10.1002/j.1538-7305.1980.tb03063.x. S2CID  27213583. При общем обслуживании DWB мы использовали систему управления исходным кодом и утилиту make, предоставляемые интерактивной операционной системой PWB/UNIX*.
  4. ^ Мэтью Доар (2005). Практические среды разработки . O'Reilly Media . стр. 94. ISBN 978-0-596-00796-6.
  5. ^ "Google Groups". arquivo.pt . Архивировано из оригинала 22 января 2011 . Получено 18 марта 2018 .{{cite web}}: CS1 maint: бот: исходный статус URL неизвестен ( ссылка )
  6. ^ "OpenSolaris at Two (Jim Grisanzio)". 12 декабря 2013 г. Архивировано из оригинала 12 декабря 2013 г. Получено 18 марта 2018 г.
  7. ^ Гризанцио, Джим. История OpenSolaris.
  8. ^ abc "Development/Gbuild - The Document Foundation Wiki". wiki.documentfoundation.org . Получено 18 марта 2018 г. .
  9. ^ ab "Руководство по созданию Apache OpenOffice - Apache OpenOffice Wiki". wiki.openoffice.org . Получено 18 марта 2018 г. .
  10. ^ Исходный код FreeBSD 2.0.5 Make, 1993 г.
  11. ^ ab "Bmake(1)".
  12. ^ "Руководство по общим командам fmake(1)".
  13. ^ "make". Страницы руководства NetBSD . Получено 9 июля 2020 г.
  14. ^ "make(1) - Страницы руководства OpenBSD". man.openbsd.org . Получено 18 марта 2018 г. .
  15. ^ "make". FreeBSD . Получено 9 июля 2020 г. В make предусмотрены включение Makefile, условные структуры и циклы for, напоминающие язык программирования C.
  16. ^ Арнольд Роббинс (2005), Unix in a Nutshell, четвертое издание, O'Reilly
  17. ^ "8. Функции преобразования текста", GNU make , Free Software Foundation, 2013
  18. ^ "8.5 Функция foreach", GNU make , Free Software Foundation, 2013
  19. ^ "GCC 3.4 Release Series Changes, New Features, and Fixes". Free Software Foundation. 2006.
  20. Хавьер Мартинес Канильяс (26 декабря 2012 г.). «Kbuild: система сборки ядра Linux». Linux Journal .
  21. ^ Грег Кроа-Хартман (2006), Ядро Linux в двух словах, O'Reilly
  22. ^ «Инструкции по сборке».
  23. ^ Рокки Бернстайн. «Remake – GNU Make с понятной трассировкой и отладчиком».
  24. ^ Гленн Фаулер (4 января 2012 г.). "Обзор nmake". Исследования информационных и программных систем, AT&T Labs Research. Архивировано из оригинала 2 сентября 2015 г. Получено 26 мая 2014 г.
  25. ^ "NMAKE Reference Visual Studio 2015". Microsoft. 2015.
  26. ^ «Директивы предварительной обработки Makefile». 2014.
  27. ^ «Операторы предварительной обработки Makefile». Microsoft. 2014.
  28. ^ «Пути поиска в правилах». Microsoft. 2014.
  29. ^ "MAKE". CodeGear(TM). 2008.
  30. ^ "Джом - Qt Wiki" . Проект Qt. 2021.
  31. ^ Макилрой, МД (1987). Исследовательский ридер Unix: аннотированные выдержки из Руководства программиста, 1971–1986 (PDF) (Технический отчет). Bell Labs. CSTR 139.
  32. ^ Хьюм, Эндрю Г.; Фландрена, Боб (2002). «Поддержание файлов на Plan 9 с помощью Mk». Plan 9 Programmer's Manual . AT&T Bell Laboratories. Архивировано из оригинала 11 июля 2015 г.
  33. ^ "google/kati: Экспериментальный клон GNU make". GitHub . 30 ноября 2020 г.
  34. ^ Мёльдер, Феликс; Яблонски, Ким Филипп; Летчер, Брайс; Холл, Майкл Б.; Томкинс-Тинч, Кристофер Х.; Сохат, Ванесса; Форстер, Ян; Ли, Сухён; Твардзиок, Свен О.; Каниц, Александр; Вильм, Андреас (19.04.2021). "Устойчивый анализ данных с помощью Snakemake". F1000Research . 10 : 33. doi : 10.12688/f1000research.29032.2 . ISSN  2046-1402. PMC 8114187. PMID  34035898 . 
  35. ^ "GNU 'make'". Фонд свободного программного обеспечения.
  36. ^ "Макияж".
  37. ^ "Бесплатная сборка BSD".
  38. ^ Как сортировать вывод файла команды ls в Linux Архивировано 13 сентября 2016 г. на Wayback Machine
  39. ^ "makefile". Документация разработчика Apple: унифицированные идентификаторы типов . Apple Inc .
  40. ^ Адамс, П. и Соломон, М., 1993, Обзор среды разработки программного обеспечения CAPITL. В Международном семинаре по управлению конфигурацией программного обеспечения (стр. 1-34). Берлин, Гейдельберг: Springer Berlin Heidelberg.
  41. ^ обзор dsls Архивировано 23 октября 2007 г. на Wayback Machine , 27.02.2007, phoenix wiki
  42. ^ Re: Хореография и ОТДЫХ Архивировано 12 сентября 2016 г. на Wayback Machine , от Кристофера Б. Ферриса 2002-08-09
  43. Target Junior Makefiles Архивировано 7 января 2010 г. на Wayback Machine , Эндрю В. Фицгиббон ​​и Уильям А. Хоффман
  44. ^ 3.1 Что содержат Makefiles, GNU make , Free Software Foundation
  45. ^ "Типы предварительных условий (GNU make)". GNU.org . Проект GNU . Получено 15 декабря 2020 г. .
  46. ^ ab "Глава 15. Инструменты: make: Автоматизация ваших рецептов", Искусство программирования в Unix , Эрик С. Рэймонд 2003
  47. ^ make  – Справочник по оболочкам и утилитам, Единая спецификация UNIX , версия 4 от The Open Group
  48. ^ https://pubs.opengroup.org/onlinepubs/9799919799/utilities/make.html.
  49. ^ make(1)  –  Руководство по основным командам FreeBSD
  50. ^ ab "make". www.opengroup.org . Получено 18 марта 2018 г. .
  51. ^ "Руководство по GNU make: правила суффиксов". Free Software Foundation.
  52. ^ "Руководство по GNU make: шаблонные правила". Free Software Foundation.
  53. ^ См. раздел «Правила сопоставления с образцом» на странице руководства SunPro. Архивировано 29 мая 2014 г. на Wayback Machine.
  54. Автоматические переменные. Архивировано 25 апреля 2016 г. на Wayback Machine GNU `make'

Внешние ссылки