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

редактировать
Делать
Парадигма макрос, декларативный
Разработано Стюарт Фельдман
Впервые появился Апрель 1976 г. ; 45 лет назад ( 1976-04)
Язык реализации C
Операционные системы Unix-подобный, Inferno
Форматы файлов Makefile
Основные реализации
BSD, GNU, nmake
Диалекты
BSD make, GNU make, Microsoft nmake
Под влиянием
Ant, Rake, MSBuild и другие

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

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

СОДЕРЖАНИЕ
  • 1 Происхождение
  • 2 Производные
  • 3 Поведение
  • 4 Makefile
    • 4.1 Правила
    • 4.2 Макросы
    • 4.3 Суффиксные правила
    • 4.4 Правила паттернов
    • 4.5 Другие элементы
  • 5 Примеры make-файлов
  • 6 См. Также
  • 7 ссылки
  • 8 Внешние ссылки
Источник

В настоящее время существует ряд утилит сборки, отслеживающих зависимости, но Make - одна из самых распространенных, в первую очередь из-за ее включения в Unix, начиная с PWB / UNIX 1.0, в которой были представлены различные инструменты, предназначенные для задач разработки программного обеспечения. Первоначально он был создан Стюартом Фельдманом в апреле 1976 года в Bell Labs. Фельдман получил награду ACM Software System Award 2003 за разработку этого широко распространенного инструмента.

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

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

-  Стюарт Фельдман, Искусство программирования Unix, Эрик С. Реймонд, 2003 г.

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

Производные
Снимок экрана GNU Make, реализации Make

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

  • Sun DevPro Make появилась в 1986 году вместе с SunOS-3.2. С SunOS-3.2 она поставлялась как дополнительная программа; с SunOS-4.0 SunPro Make была сделана программой Make по умолчанию. В декабре 2006 года Sun DevPro Make была сделана с открытым исходным кодом в рамках усилий по созданию Solaris с открытым исходным кодом.
  • dmake или Distributed Make, которые поставлялись с Sun Solaris Studio в качестве Make по умолчанию, но не по умолчанию в операционной системе Solaris (SunOS). Первоначально это требовалось для сборки OpenOffice, но в 2009 году система сборки была переписана для использования GNU Make. Хотя Apache OpenOffice по- прежнему содержит смесь обеих систем сборки, в гораздо более активно развивающемся LibreOffice сейчас используется только модернизированная «gbuild».
  • BSD Make ( pmake, bmake или fmake), который является производным от работы Адама де Бура над версией Make, способной создавать цели параллельно, и выживает с различной степенью модификации во FreeBSD, NetBSD и OpenBSD. В частности, он имеет условные операторы и итерационные циклы, которые применяются на этапе синтаксического анализа и могут использоваться для условного и программного создания файла makefile, включая создание целей во время выполнения.
  • GNU Make (сокращенно gmake) - это стандартная реализация Make для Linux и macOS. Он предоставляет несколько расширений по сравнению с исходной Make, например условные. Он также предоставляет множество встроенных функций, которые можно использовать для устранения необходимости в сценариях оболочки в правилах make-файла, а также для управления переменными, установленными и используемыми в make-файле. Например, функцию foreach можно использовать для перебора списка значений, например имен файлов в заданном каталоге. GNU Make требуется для создания многих программных систем, включая GCC (начиная с версии 3.4), ядро ​​Linux, Apache OpenOffice, LibreOffice и Mozilla Firefox.
  • Ремейк Рокки Бернстайна - это ответвление GNU Make и предоставляет несколько расширений по сравнению с GNU Make, например улучшенный отчет о местоположении и обнаружении ошибок, отслеживание выполнения, профилирование выполнения, а также содержит отладчик.
  • Nmake Гленна Фаулера не имеет отношения к одноименной программе Microsoft. Его вход аналогичен Make, но не совместим. Эта программа предоставляет ярлыки и встроенные функции, которые, по словам разработчиков, уменьшают размер make-файлов в 10 раз.
  • Microsoft nmake, инструмент командной строки, который обычно является частью Visual Studio. Он поддерживает директивы препроцессора, такие как include и условные выражения, которые используют переменные, установленные в командной строке или в make-файлах. Правила вывода отличаются от Make; например, они могут включать пути поиска. Инструмент Make, поставляемый с продуктами Embarcadero, имеет параметр командной строки, который «заставляет MAKE имитировать Microsoft NMAKE.». Qt Project «s Jom инструмент представляет собой клон NMAKE.
  • Mk заменил Make в Research Unix, начиная с версии 9. Это переработанная версия оригинального инструмента, разработанная программистом Bell Labs Эндрю Дж. Хьюмом, с другим синтаксисом. Mk стал стандартным инструментом сборки в Plan 9, предполагаемом преемнике Bell Labs для Unix.
  • Кати - это замена Google GNU Make, используемого в сборках ОС Android. Он переводит make-файл в Ninja для более быстрой инкрементальной сборки.

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

Поведение

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

Make вызывается со списком имен целевых файлов для сборки в качестве аргументов командной строки :

make [TARGET...]

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

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

Файлы Makefile традиционно используются для компиляции кода (*.c, *.cc, *.C и т. Д.), Но их также можно использовать для предоставления команд для автоматизации общих задач. Один из таких make-файлов вызывается из командной строки:

make # Without argument runs first TARGET make help # Show available TARGETS make dist # Make a release archive from current dir
Makefile

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

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

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

Make-файлы могут содержать пять типов вещей:

  1. Явное правило говорит, когда и как переделать один или несколько файлов, называемые целями правила. В нем перечислены другие файлы, от которых зависят цели, называемые предпосылками цели, а также может быть указан рецепт для использования при создании или обновлении целей.
  2. Неявное правило говорит, когда и как переделать класс файлов на основе их имен. Он описывает, как цель может зависеть от файла с именем, аналогичным цели, и дает рецепт для создания или обновления такой цели.
  3. Определение переменной - это строка, в которой указывается значение текстовой строки для переменной, которая может быть подставлена ​​в текст позже.
  4. Директива является инструкцией для макияжа, чтобы сделать что - то особенное, читая Makefile, такие как чтение другого Makefile.
  5. Строки, начинающиеся с #, используются для комментариев.

Правила

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

target [target...]: [component...] Tab ↹[command 1]... Tab ↹[command n]

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

Например, объектный файл C. o создается из файлов.c, поэтому файлы.c идут первыми (т.е. конкретный целевой объектный файл зависит от исходного файла C и файлов заголовков ). Поскольку сам Make не понимает, не распознает и не распознает файлы разных типов, это открывает возможность человеческой ошибки. Забытая или дополнительная зависимость может быть не сразу очевидна и может привести к незначительным ошибкам в сгенерированном программном обеспечении. Можно написать make-файлы, которые генерируют эти зависимости, вызывая сторонние инструменты, а некоторые генераторы make-файлов, такие как инструментальная цепочка Automake, предоставляемая проектом GNU, могут делать это автоматически.

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

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

targets: prerequisites ; command

Например,

hello: ; @echo "hello"

Make может решить, с чего начать топологическую сортировку.

Каждая командная строка должна начинаться с символа табуляции, чтобы ее можно было распознать как команду. Табуляция представляет собой пробельный символ, но пробел не имеет такого особого значения. Это проблематично, поскольку между табуляцией и серией пробелов может не быть визуальной разницы. Этот аспект синтаксиса make-файлов часто подвергается критике; Эрик С. Реймонд описал ее как «одну из худших дизайнерских неудач в истории Unix», а в «Справочнике ненавистников Unix» говорится, что «использование вкладок в качестве части синтаксиса похоже на одну из ловушек в « Зеленых беретах ». ". Фельдман объясняет этот выбор обходным решением проблемы ранней реализации, сохраненной стремлением к обратной совместимости с самыми первыми пользователями:

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

-  Стюарт Фельдман

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

.RECIPEPREFIX:= : all::@echo "recipe prefix symbol is set to '$(.RECIPEPREFIX)'"

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

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

realclean: clean distclean

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

file.txt: file.html lynx -dump file.html gt; file.txt

Приведенное выше правило срабатывает при обновлении файла "file.txt". В следующем вызове Make обычно использует это правило для обновления целевого файла «file.txt», если «file.html» был более новым.

make file.txt

Командные строки могут иметь один или несколько из следующих трех префиксов:

  • дефис-минус (-), указав, что ошибки игнорируются
  • в знак (@), указав, что команда не выводится на стандартный вывод перед его выполнением
  • знак плюс (+), команда выполняется, даже если Make вызывается в режиме «не выполнять»

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

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

Макросы

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

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

Новые макросы (или простые «переменные») традиционно обозначаются заглавными буквами:

MACRO = definition

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

NEW_MACRO = $(MACRO)-$(MACRO2)

Макросы могут состоять из команд оболочки с помощью оператора подстановки команд, обозначаемого обратными кавычками ( `).

YYYYMMDD = ` date `

Содержание определения хранится «как есть». Используется ленивое вычисление, что означает, что макросы обычно раскрываются только тогда, когда их расширения действительно требуются, например, когда они используются в командных строках правила. Расширенный пример:

PACKAGE = package VERSION = ` date +"%Y.%m.%d" ` ARCHIVE = $(PACKAGE)-$(VERSION) dist: # Notice that only now macros are expanded for shell to interpret: # tar -cf package-`date +"%Y.%m.%d"`.tar tar -cf $(ARCHIVE).tar.

Общий синтаксис для переопределения макросов в командной строке:

make MACRO="value" [MACRO="value"...] TARGET [TARGET...]

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

target: component1 component2 # contains those components which need attention (i.e. they ARE YOUNGER than current TARGET). echo $? # evaluates to current TARGET name from among those left of the colon. echo $@

Несколько общее расширение синтаксиса является использование + =, ? = И ! = Вместо знака равенства. Он работает как на BSD, так и на GNU.

Суффиксные правила

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

.SUFFIXES:.txt.html # From.html to.txt.html.txt: lynx -dump $lt; gt; $@

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

$ make -n file.txt lynx -dump file.html gt; file.txt

Правила паттернов

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

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

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

# From %.html to %.txt %.txt: %.html lynx -dump $lt; gt; $@

Прочие элементы

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

Некоторые директивы в make-файлах могут включать другие make-файлы.

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

 target: component \ component Tab ↹command ; \ Tab ↹command | \ Tab ↹piped-command
Примеры make-файлов

Makefile:

PACKAGE = package VERSION = ` date "+%Y.%m%d%" ` RELEASE_DIR =.. RELEASE_FILE = $(PACKAGE)-$(VERSION) # Notice that the variable LOGNAME comes from the environment in # POSIX shells. # # target: all - Default target. Does nothing. all: echo "Hello $(LOGNAME), nothing to do by default" # sometimes: echo "Hello ${LOGNAME}, nothing to do by default" echo "Try 'make help'" # target: help - Display callable targets. help: egrep "^# target:" [Mm]akefile # target: list - List source files list: # Won't work. Each command is in separate shell cd src ls # Correct, continuation of the same shell cd src; \ ls # target: dist - Make a release. dist: tar -cf $(RELEASE_DIR)/$(RELEASE_FILE) amp;amp; \ gzip -9 $(RELEASE_DIR)/$(RELEASE_FILE).tar

Ниже приведен очень простой make-файл, который по умолчанию (правило «все» указано первым) компилирует исходный файл с именем «helloworld.c» с использованием системного компилятора C, а также предоставляет «чистую» цель для удаления сгенерированных файлов, если пользователь желает начать все сначала. $@И $lt;являются двумя из так называемых внутренних макросов (также известные как автоматические переменные) и стоять имя цели и «неявный» источник, соответственно. В приведенном ниже примере $^расширяется до списка предварительных требований, разделенных пробелами. Есть ряд других внутренних макросов.

CFLAGS ?= -g all: helloworld helloworld: helloworld.o # Commands start with TAB not spaces $(CC) $(LDFLAGS) -o $@ $^ helloworld.o: helloworld.c $(CC) $(CFLAGS) -c -o $@ $lt; clean: FRC $(RM) helloworld helloworld.o # This pseudo target causes all targets that depend on FRC # to be remade even in case a file with the name of the target exists. # This works with any make implementation under the assumption that # there is no file FRC in the current directory. FRC:

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

all: helloworld helloworld: helloworld.o $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ clean: FRC $(RM) helloworld helloworld.o # This is an explicit suffix rule. It may be omitted on systems # that handle simple rules like this automatically..c.o: $(CC) $(CFLAGS) -c $lt; FRC:.SUFFIXES:.c

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

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

# Generic GNUMakefile # Just a snippet to stop executing under other make(1) commands # that won't understand these lines ifneq (,) This makefile requires GNU Make. endif PROGRAM = foo C_FILES:= $(wildcard *.c) OBJS:= $(patsubst %.c, %.o, $(C_FILES)) CC = cc CFLAGS = -Wall -pedantic LDFLAGS = LDLIBS = -lm all: $(PROGRAM) $(PROGRAM):.depend $(OBJS) $(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $(PROGRAM) $(LDLIBS) depend:.depend.depend: cmd = gcc -MM -MF depend $(var); cat depend gt;gt;.depend;.depend: @echo "Generating dependencies..." @$(foreach var, $(C_FILES), $(cmd)) @rm -f depend -include.depend # These are the pattern matching rules. In addition to the automatic # variables used here, the variable $* that matches whatever % stands for # can be useful in special cases. %.o: %.c $(CC) $(CFLAGS) -c $lt; -o $@ %: %.o $(CC) $(CFLAGS) -o $@ $lt; clean: rm -f.depend $(OBJS).PHONY: clean depend
Смотрите также
использованная литература
внешние ссылки
Последняя правка сделана 2024-01-01 03:33:33
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте