Makefile universal: GitHub — deminets/unimake: Universal makefile

makefile — Начало работы с makefile

замечания

Makefile — это текстовый файл, который контролирует работу программы make . Программа make обычно используется для управления созданием программ из их исходных файлов, но ее можно более широко использовать для обработки любого процесса, в котором файлы (или целевые объекты ) необходимо восстановить после того, как другие файлы (или предпосылки ) были изменены. Файл makefile описывает взаимосвязь между целями и предварительными условиями, а также указывает команды, необходимые для обновления цели, когда одно или несколько предварительных условий были изменены. Единственный способ make «устаревшим» — это сравнить время модификации целевых файлов и их предварительные условия.

Makefiles несколько уникальны несколькими способами, которые могут быть запутаны изначально.

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

рецепт, который указывает, какие команды следует вызывать, чтобы заставить эту цель обновляться. Рецепт написан как сценарий оболочки (по умолчанию POSIX sh). Программа make не анализирует этот скрипт: он запускает оболочку и передает сценарий в оболочку для запуска. Тот факт, что рецепты не анализируются make , а обрабатывается отдельным процессом оболочки, занимает центральное место в понимании make-файлов.

Во-вторых, make-файл не является процедурным языком, как скрипт: поскольку make анализирует makefile, он конструирует ориентированный граф внутри, где цели являются узлами графика, а обязательные отношения — это ребра. Только после того, как все Makefiles были полностью разобраны и график завершения будет

make выбор один узел (цель) и попытаться довести его до настоящего времени. Чтобы гарантировать, что цель обновлена, она должна сначала обеспечить, чтобы каждый из предварительных условий этой цели обновлялся и т. Д. Рекурсивно.

Версии

Основной Makefile

Подумайте о написании «привет мир!». программа в c. Допустим, наш исходный код находится в файле source.c, теперь, чтобы запустить нашу программу, нам нужно ее скомпилировать, как правило, на Linux (с использованием gcc) нам нужно будет ввести $> gcc source.c -o output где вывод это имя исполняемого файла. Для базовой программы это работает хорошо, но по мере того, как программы становятся более сложными, наша команда компиляции также может усложняться. Здесь появляется

Makefile , make- файлы позволяют нам выписывать довольно сложный набор правил для того, как скомпилировать программу, а затем просто скомпилировать ее, набрав make в командной строке. Например, вот пример Makefile для примера hello wold выше.

Основной Makefile

Давайте сделаем базовый Makefile и сохраним его в нашей системе в том же каталоге, что и наш исходный код с именем Makefile . Обратите внимание, что этот файл должен быть назван Makefile, однако Capitol M является необязательным. Тем не менее, относительно условно использовать капитолий М.

output: source.c
    gcc source.c -o output
 

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

Переменные в Make-файлах

В зависимости от проекта вы можете ввести некоторые переменные в ваш файл make. Вот пример Makefile с присутствующими переменными.

CFLAGS = -g -Wall

output: source.c
    gcc $< $(CFLAGS) -o [email protected]
 

Теперь рассмотрим, что здесь произошло. В первой строке мы объявили переменную с именем CFLAGS, которая содержит несколько общих флагов, которые вы, возможно, захотите передать компилятору, обратите внимание, что вы можете хранить столько флагов, сколько хотите в этой переменной. Затем мы имеем ту же строку, что и перед тем, как сообщать make, чтобы проверить source.c, чтобы увидеть, было ли это изменено совсем недавно, чем вывод, если это так, что оно запускает правило компиляции. Правило нашей компиляции в основном такое же, как и раньше, но оно было сокращено с помощью переменных, переменная

$< встроена в make (называемая автоматической переменной, см. Https://www.gnu.org/software/make/manual/ html_node / Automatic-Variables.html ), и это всегда означает источник, поэтому в данном случае source.c . $(CFLAGS) — это наша переменная, которую мы определили ранее, но обратите внимание, что нам пришлось поставить переменную в круглую скобку с $ front, как этот $(someVariable) . Это синтаксис для указания Make, чтобы расширить переменную до того, что вы набрали ранее. Наконец, мы имеем символ $ @, еще раз это переменная, встроенная в make, и она просто обозначает цель этапа компиляции, поэтому в этом случае это означает
вывод
.

чистый

Очистить это еще одна полезная концепция, чтобы узнать о файлах. Позволяет модифицировать Makefile сверху

CFLAGS = -g -Wall
TARGETS = output

output: source.c
    gcc $< $(CFLAGS) -o [email protected]

clean:
    rm $(TARGETS)
 

Как вы можете видеть, мы просто добавили еще одно правило в наш Makefile и одну дополнительную переменную, которая содержит все наши цели. Это довольно распространенное правило в make-файлах, поскольку оно позволяет быстро удалить все созданные вами двоичные файлы, просто набрав $> make clean . Набрав make clean, вы сообщите программе make о запуске чистого правила, а затем make запустит команду rm, чтобы удалить все ваши цели.

Я надеюсь, что этот краткий обзор использования make поможет вам ускорить ваш рабочий процесс,

Makefiles может стать очень сложным, но с этими идеями вы сможете начать использовать make и лучше понять, что происходит в других программистах Makefiles . Для получения дополнительной информации об использовании сделать отличный ресурс https://www.gnu.org/software/make/manual/ .

Определение правил

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

Правила следуют синтаксису ниже: (Обратите внимание, что команды, следующие за правилом, отступаются от вкладки )

targets: prerequisites
        <commands>
 

где цели и

предварительные условия — это имена файлов или специальные зарезервированные имена и команды (если они есть), выполняются оболочкой для создания / перестройки целей , устаревших.

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

make выполняет только правило, если цель устарела, то есть либо она не существует, либо время ее модификации старше любого из ее предварительных условий. Если список предварительных условий пуст, правило будет выполняться только при первом вызове для создания целей. Однако, когда правило не создает файл, а цель — фиктивная переменная, правило всегда будет выполняться.

GNU make

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

Представьте, что мы хотим создать цели foo.o и bar.o , скомпилировав C-скрипты, foo.c и bar.c , соответственно. Это можно сделать, используя обычные правила:

foo.o: foo.c
    cc -c $< -o [email protected]

bar.o: bar.c
    cc -c $< -o [email protected]


где автоматическая переменная $< — это имя первого предпосылки и [email protected] имя цели (полный список автоматических переменных можно найти здесь ).

Однако, поскольку цели имеют один и тот же суффикс, приведенные выше два правила теперь могут быть заменены следующим шаблоном:

%.o: %.c
    cc -c $< -o [email protected]
 

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

Пример правила шаблона, который мы видели в предыдущем разделе, на самом деле не должен быть объявлен в Makefile, поскольку make имеет неявное правило для компиляции C. Таким образом, в следующем правиле предварительные условия

foo.o и bar.o будут построены с использованием неявного правила для компиляции C, прежде чем строить foo .

foo : foo.o bar.o
    cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
 

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

Общее правило для gzip файла

если каталог содержит 2 файла:

$ ls
makefile
example.txt
 

и makefile содержат следующий текст

%.gz: %
    gzip $<
 

то вы можете получить example.txt.gz , введя в оболочку

$ make -f makefile example.txt.gz
 

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

.gz суффиксом.

makefile Hello World

C: \ Makefile:

helloWorld :
[TAB]echo hello world
 

результаты:

C:\>make
echo hello world
hello world
 

Примечание: [TAB] следует заменить фактической вкладкой, stackoverflow заменяет вкладки пробелами, а пробелы не используются так же, как вкладки в make-файле.



Как устроен Makefile и что это такое? | avr

Makefile — файл, содержащий набор инструкций для программы make. Программа make с помощью этого файла позволяет автоматизировать процесс компиляции программы и выполнять при этом различные действия. При запуске make по умолчанию ищет файл Makefile в текущей папке и обрабатывает его (можно изменить это поведение, чтобы открывался другой файл с набором инструкций, если ввести команду make -f другое_имя_makefile).

Система make родилась в мире UNIX и постепенно переползла и на Windows вместе с портами GNU-компиляторов (gcc). Если открыть пример готового Makefile, то он поначалу может показаться полной абракадаброй, поскольку содержимое файла подчиняется заранее заданному набору правил, которые необходимо предварительно изучить. Для простоты рассмотрим пример работы с проектом AVR и компилятором gcc.

Немного о структуре файла.

— Комментарии, как это принято в UNIX скриптах, начинаются с символа # и продолжаются до конца строки.
— Обычно в файле содержатся метки, идентифицирующие «цели» (targets, см. далее). Метка начинается с начала строки и оканчивается двоеточием :. После двоеточия могут идти так называемые зависимости, dependencies (сразу непонятно, что это такое и для чего надо, но дальше по ходу дела станет яснее). Обычно это имена файлов, либо ссылки на цели.
— Если в качестве dependencies указана последовательность целей, то они будут выполняться друг за другом.
— Если в качестве dependencies указаны имена файлов (обычно объектных), то утилита make может проверить — нужно их компилировать, или нет (мне непонятно, как она проверяет, однако это работает). Например, если компилируется несколько исходных файлов в несколько объектных, то некоторые исходные файлы не требуется каждый раз перекомпилировать заново, если они не изменялись. Для больших проектов это важно, поскольку существенно экономит время сборки программы (в нашем случае — получение двоичной прошивки для AVR).
— Для упрощения содержимого Makefile и для удобства используются переменные. Пример задания переменной (здесь в переменную записана командная строка вызова программатора):

JTAGICEII = c:/Program Files/AtmelAVR Tools/JTAGICEmkII/jtagiceii.exe -d $(DEVICE) -e -mi

После задания переменной на неё можно ссылаться так:

flash: main.hex
    $(JTAGICEII) -pf -if main.hex

— После задания в одной строке цели (цель: [зависимость1] .. [зависимостьN]) в последующих строках могут задаваться так называемые правила (rules). Каждое правило должно ОБЯЗАТЕЛЬНО начинаться с символа табуляции (таким способом make отслеживает правила и другие цели). Правило — это просто обычная команда (вызов компилятора, копирование, удаление и проч.), выполняемая шеллом.
— Переменные [email protected], $< , $^ называются автоматическими (automatic variables).

[email protected] заменяется на текущую цель.
$< которая заменяется на первую зависимость из списка.
$^ которая заменяется на список всех зависимостей с их каталогами.

Итак, при работе с проектом может потребоваться автоматизировать следующие часто повторяющиеся действия:

1. Компиляция программы (вводимая команда будет выглядеть как make hex).
2. Запись двоичного файла (make flash).
3. Запись бит «перемычек» (make fuse, для микроконтроллеров AVR это обычно 2 байта).
4. Полная запись микроконтроллера (и памяти и перемычек), выполняются действия и 2, и 3.
5. Очистка проекта — удаление всех промежуточных файлов, образующихся при компиляции, обычно объектных (make clean).
6. Стирание микроконтроллера (очистка flash и сброс перемычек в исходное состояние).
7. Бэкап проекта (make backup), будет выполняться цель 5 (clean), а затем архивирование файлов.
8. Вывод подсказки по возможным вариантам работы с проектом (просто make, при этом выводится подсказка по make hex, make flash, make fuse, make clean).

Для каждого такого действия 1..8 в Makefile прописывается блок команд, этот блок идентифицируется целью (target). Имя цели по сути является меткой, по которой переходит управление при обработке команды, переданной программе make. Для действия 1 это будет запуск компилятора (цель hex), для 2 — вызов программатора (цель flash) и т. д. Рассмотрим для примера ветку обработки цели hex (команда make hex) по шагам — см. рабочий Makefile [4] на примере проекта из библиотеки V-USB.

1. Пользователь вводит команду make hex.
2. Программа make открывает файл Makefile, ищет цель hex и начинает её обработку.
3. Для цели hex указана зависимость main.hex и ни одного правила (строка 131). Программа make ищет цель main.hex и начинает её обработку.
4. Для цели main.hex указана зависимость main.elf (строка 175) и несколько правил. Программа make ищет цель main.elf и начинает её обработку (правила цели main.hex будут отрабатываться после окончания обработки цели main.elf).
5. Для цели main.elf указаны зависимости usbdrv и $(OBJECTS) (строка 172), а также одно правило (вызов компилятора для получения файла main.elf). Программа make ищет цель usbdrv и начинает её обработку.
6. Для цели usbdrv не указано зависимостей (строка 169), только одно правило (копирование папки usbdrv в текущий каталог). Выполняется это правило, цель usbdrv завершена и происходит возврат к обработке цели main.elf.
7. Зависимости, входящие в переменную $(OBJECTS) (строка 172), не являются целями, это просто имена файлов, которые должны быть получены при компиляции. Поэтому сразу начинается выполняться правило, запускающее компилятор (строка 173). В результате те объектные файлы, которые должны быть скомпилированы, появляются в соответствующих каталогах, и появляется выходной файл main.elf (двоичный файл, который может использоваться в качестве входного для эмулятора или симулятора при отладке программы). Цель main.elf завершена, происходит возврат к обработке цели main.hex (строка 175).
8. Начинается обработка правил цели main.hex. Команда rm удаляет старые файлы прошивок flash и eeprom, avr-objcopy генерирует новую прошивку main.hex из файла main.elf, avr-size просто отображает информацию о размере секций в файле main.hex. Обработка цели main.hex закончена, происходит возврат к обработке цели hex.
9. Все зависимости цели hex обработаны, правил у цели hex нет. Работа make на этом завершается.

Есть утилиты-визарды для автоматической генерации файлов Makefile, например входящая в пакет WinAVR утилита MFile (запускается ярлычком C:\WinAVR-20080610\bin\wish84.exe mfile.tcl).

[Проблемы и их решение]

1. Makefile в среде Windows (Makefile работает при помощи пакета MSYS) завершается с ошибкой на команде xcopy, например (выполнение команды make backup):

/usr/bin/sh: -c: line 3: syntax error: unexpected end of file
make: *** [backup] Error 258

Проблема решается добавлением в начало Makefile строки «SHELL=cmd.exe». Вот пример рабочего Makefile, в котором эта ошибка устранена:

RAR = "c:/Program Files/WinRAR/WinRAR.exe"ARCHIVE = myproject.rarSHELL=cmd.exe
 help:
    @echo "This Makefile has no default rule. Use one of the following:"
    @echo "make backup .... backup project" 
 backup:
    $(RAR) a -r -dh -ep1 $(ARCHIVE) ../myproject
    mv $(ARCHIVE) c:/archive/ARMmyproject
    autoname /pattern:YYMMDDhhmmss c:/archive/ARM/myproject/$(ARCHIVE)
    xcopy /M /Y c:/archive/ARMmyproject*.* "\serverWORK"

2. Сетевые (UNC) пути необходимо заключать в двойные кавычки, иначе они будут неправильно переданы интерпретатору cmd.exe. Вот так:

xcopy /M /Y c:/archive/ARMmyproject*.* "serverWORK"

3. Отлаживать makefile удобно с помощью команды echo, выводя в консоль значения переменных. Пример:

[Как создать простейший makefile]

Предположим, есть три файла: program.c, program.h и header.h. Нужно их скомпилировать компилятором gcc. Как это проще всего осуществить?

Очевидно, что нужно создать командный файл makefile, и передать его утилите make. Вот простое решение, демонстрирующее общую концепцию:

HEADERS = program.h header.h
 
default: program.exe
 
program.o: program.c $(HEADERS)
    gcc -c program.c -o program.o
 
program.exe: program.o
    gcc program.o -o program.exe
 
clean:
    -rm -f *.o *.exe

Обратите внимание, что вместо пробелов в начале строк должны быть символы табуляции, иначе makefile работать не будет. Это нужно исправить, когда будете копировать этот текст как шаблон нового makefile.

Это простейший шаблон, и недостаток у него в том, что если нужно поддерживать большое количество файлов кода, то для каждого файла нужно добавлять новое правило. Этот недостаток можно устранить так:

HEADERS = program.h headers.h
OBJECTS = program.o
 
default: program.exe
 
%.o: %.c $(HEADERS)
    gcc -c $< -o [email protected]
 
program: $(OBJECTS)
    gcc $(OBJECTS) -o [email protected]
 
clean:
    -rm -f $(OBJECTS) *.exe

Это простейший пример, и для упрощения здесь опущены такие макросы, как $(CC), $(CFLAGS) и другие. Вот пример несложного makefile, который я часто использую для компилирования исходного кода на языке C.

TARGET = prog
LIBS = -lm
CC = gcc
CFLAGS = -g -Wall
 
.PHONY: clean all default
 
default: $(TARGET)
all: default
 
OBJECTS = $(patsubst %.c, %.o, $(wildcard *.c))
HEADERS = $(wildcard *.h)
 
%.o: %.c $(HEADERS)
    $(CC) $(CFLAGS) -c $< -o [email protected]
 
.PRECIOUS: $(TARGET) $(OBJECTS)
 
$(TARGET): $(OBJECTS)
    $(CC) $(OBJECTS) -Wall $(LIBS) -o [email protected]
 
clean:
    -rm -f *.o
    -rm -f $(TARGET)

В этом makefile используются функции wildcard и patsubst утилиты make для автоматического подключения файлов *.c и *.h в текущей директории. Это означает, что когда Вы добавляете новые модули исходного кода в корневой каталог проекта, то Вам уже не надо модифицировать содержимое makefile. Если Вы хотите поменять имя генерируемого исполняемого файла, то Вам нужно просто поменять значение переменной TARGET. Для очистки проекта нужно в корневом каталоге проекта ввести команду make clean, а для компиляции make all или просто make.

В любом случае, ИМХО, не стоит использовать Autoconf/Automake. Конечно, они хорошо работают, но если Вы к ним привыкнете, то не сможете делать самых простых вещей, и Вам будет трудно разобраться в содержимом готовых makefile, которые поставляются вместе с большинством open-source проектов.

addprefix. Функция addprefix позволяет добавить префикс с каждой строке в последовательности строк. Пример:

OBJDIR = Objects
OBJECTS = $(patsubst %.cpp, %.o, $(wildcard *.cpp))
@echo $(OBJECTS)
# выведется trim.o main.o bmpfile.o
OBJ = $(addprefix $(OBJDIR)/, $(OBJECTS))
@echo $(OBJ)
# выведется Objects/trim.o Objects/main.o Objects/bmpfile.o

Утилита gccmakedep. В зависимости от количества заголовков и модулей проекта, и Ваших потребностей в разработке, рассмотрите возможность использования утилиты gccmakedep [7]. Эта программа анализирует текущий каталог, и добавляет в конец makefile зависимости от заголовков для каждого найденного файла *.c/*.cpp. Конечно, если у Вас в проекте только 2 или 3 файла, то такой функционал излишен, но если модулей и заголовков намного больше, то утилита gccmakedep может пригодиться.

[Ссылки]

1. Installing MSYS site:mingw.org.
2. Home of the MinGW and MSYS Projects site:mingw.org.
3. Перевод Makefile Mini HOWTO (make) site:opennet.ru.
4. Рабочий Makefile на примере AVR-USB (USB HID-устройство и консольная утилита для работы с ним).
5. GNU Make программа управления компиляцией site:linux.yaroslavl.ru (руководство по программе make на русском языке).
6. Эффективное использование GNU Make site:linux.org.ru.
7. gccmakedep site:x.org.

Использование GNU Autotools. Создание своего скрипта configure и файла Makefile

Необходимые пакеты
autoconf
automake

Описание

  • В этой заметке описываются шаги, которые должен предпринять разработчик, желающий, чтобы его проект уровня “hello world!” использовал систему сборки autotools: создание своего скрипта configure для проекта,а также генерация Makefile.

Написание программы

Прежде чем разбираться с вопросом автоматизации сборки своей копии программы “hello, world!” будьте уверены, что вы можете её написать. В любом случае, вот вам пример этой программы на языке Си:

#include <stdio.h>
 
int main(void)
{
  printf("Hello, world!\n");
 
  return 0;
}

Создание configure.in

Нужно создать файл configure.in, поместив в него необходимые макросы autoconf. После создания этого файла необходимо запустить http://ru.wikipedia.org/wiki/Autoconf для того чтобы сгенерировать скрипт configure.

Те, кто внимательно прочитал всю, или хотя бы бОльшую часть мануала (см. раздел Ссылки), без особых усилий смогут самостоятельно создать configure.in. Для таких же новичков как мы была создана программа autoscan, которая сканирует текущий каталог и создаёт заготовку для будущего configure.in файла. После запуска autoscan найдите в текущем каталоге файл configure.scan

Вот пример configure.scan, который получился у меня:

#                                               -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME, VERSION, BUG-REPORT-ADDRESS)
AC_CONFIG_SRCDIR([hello.c])
AC_CONFIG_HEADER([config.h])

# Checks for programs.
AC_PROG_CC

# Checks for libraries.

# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics.

# Checks for library functions.
AC_OUTPUT

Переименуйте этот файл в configure.in и отредактируйте.

Все строчки, начинающиеся со знака # являются комментариями. Все комментарии такого вида попадут в генерируемый configure скрипт в неизменном виде. Если же вы хотите, чтобы ваши комментарии не встречались где-либо за рамками configure.in файла, то используйте встроенный макрос m4 — dnl, «который отбрасывает текст вплоть до начала новой строки».

Первым макросом идёт AC_PREREQ. Он указывает, что требуется autoconf версии 2.59 и никак не меньше. В случае, если мы попытаемся создать configure скрипт с помощью autoconf более младшей версии мы получим ошибку.

Любой configure.in должен начинаться с макроса AC_INIT и заканчиваться макросом AC_OUTPUT. В качестве аргументов AC_INIT принимает название программы, её версию, и, как необязательный аргумент, ваш email-адрес, куда пользователи смогут отправлять отчеты об ошибках.

Не забудьте изменить значения по умолчанию для этих параметров!

  • AC_CONFIG_SRCDIR принимает в качестве параметра путь к файлу, с которого начинается сборка. Т.к. в нашей программе файл пока всего один, то именно он и является аргументом этого макроса.

  • AC_CONFIG_HEADER можете смело удалить, т.к. для программы уровня “hello world!” он не нужен.( Использование файла config.h?)
  • AC_PROG_CC ищет компилятор для языка Си и выставляет переменную CC соответствующим образом.

  • AC_OUTPUT заканчивает файл configure.in и заставляет autoconf начать генерацию configure-скрипта.

Более подробное описание для всех этих макросов вы можете найти в разделе ссылок внизу 1).

После всех правок я получил следующий configure.in:

AC_PREREQ(2.59)
AC_INIT([hello], [1.0], [basinbug at yahoo.com])
AC_CONFIG_SRCDIR([hello.c])

# Checks compiler
AC_PROG_CC

AC_OUTPUT

Теперь запустите программу autoconf, а после получившийся configure скрипт:

[[email protected] ~/autotools-hello]$ ./configure
checking for gcc... gcc
checking for C compiler default output file name... a.out
checking whether the C compiler works... yes
checking whether we are cross compiling... no
checking for suffix of executables... 
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ANSI C... none needed
configure: creating ./config.status

Создание Makefile.am и src/Makefile.am

Но работающего скрипта configure недостаточно. Наша цель, чтобы программа также собиралась по команде make и устанавливалась по make install. За это отвечает уже automake. Для него нам потребуется создать два файла: корневой Makefile.am и Makefile.am для каталога src/, в котором и должен располагаться файл hello.c

Не забудьте его переместить.

Для нашей программы они очень простые:

Makefile.am

SUBDIRS = src

src/Makefile.am:

bin_PROGRAMS = hello
hello_SOURCES = hello.c

SUBDIRS сообщает make’у о каталоге src, в который обязательно необходимо «заглянуть»

bin_PROGRAMS задаёт имя нашей программы, а позже мы указываем какие исходные файлы нужно будет компилировать. Более нам ничего не нужно указывать — automake сам всё поймёт.
Некоторые изменения также нужно внести в configure.in, чтобы при вызове configure создавались необходимые Makefile’ы:

 AC_PREREQ(2.59)
 AC_INIT([hello], [1.0], [basinbug at yahoo.com])
-AC_CONFIG_SRCDIR([hello.c])
+AC_CONFIG_SRCDIR([src/hello.c])
 AM_INIT_AUTOMAKE
 
 # Checks compiler
 AC_PROG_CC
 
 AC_CONFIG_FILES([Makefile src/Makefile])
 AC_OUTPUT

Объясню подробнее назначение добавленных макросов: AM_INIT_AUTOMAKE сообщает autoconf о том, что мы намерены использовать automake. AC_CONFIG_FILES говорит, что из указанных файлов, с постфиксом .in, нужно создать результирующие файлы с приведёнными именами. Иными словами, во время вызова configure из файла Makefile.in будет создаваться Makefile. (А Makefile.in создаётся автоматически из Makefile.am)

  • использование дополнительных аргументов макроса AM_INIT_AUTOMAKE для передачи аргументов программе automake


Далее выполните:

aclocal
automake --foreign --add-missing
autoconf

После чего будут сгенерированы все нужные Makefile’ы, создан configure скрипт и наша программа готова к распространению. Остался лишь один штрих: make dist и вуаля — hello-1.0.tar.gz готов к использованию и распространению между пользователями.

Ссылки

Make: cтруктура Makefile | MainLoop

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

В этой заметке я попытаюсь рассказать как создать makefile.

По умолчанию правила сборки считываются из файла с именем Makefile.

Структуру Makefile можно представить так:

ЦЕЛЬ: ЗАВИСИМОСТЬ
[TAB]ДЕЙСТВИЕ

Но обычно используются более сложные правила, например:

ЦЕЛЬ: ЦЕЛЬ1  ЦЕЛЬ2
[TAB]ДЕЙСТВИЕ

ЦЕЛЬ1: ЗАВИСИМОСТЬ1
[TAB]ДЕЙСТВИЕ1

ЦЕЛЬ2: ЗАВИСИМОСТЬ2
[TAB]ДЕЙСТВИЕ2

ЦЕЛЬ — это то что мы получаем в результате ДЕЙСТВИЯ. Это может быть файл, директория или просто абстрактная ЦЕЛЬ не имеющая связи с каким-либо объектом на жестком диске. После имени цели ставится двоеточие. При запуске команды make без параметров выполнится первое найденное правило. Что бы выполнить другое правило надо указать его команде make

make ЦЕЛЬ2

ЗАВИСИМОСТЬ — это то, от чего зависит наша ЦЕЛЬ. Это могут быть файлы, каталоги или другие ЦЕЛИ. Make сравнивает дату и время изменения ЦЕЛИ и объектов о которых зависит цель. Если объекты от которых зависит цель были изменены позже чем создана цель, то будет выполнено ДЕЙСТВИЕ. ДЕЙСТВИЕ так же выполняется если ЦЕЛЬ не является именем файла или директории.

ДЕЙСТВИЕ — это набор команд которые надо выполнить. Перед командами должен быть введен символ табуляции. Если вместо символа табуляции будут введены пробелы то при компиляции будет выведено сообщение об ошибке:


Makefile:13: *** пропущен разделитель.  Останов.

или


Makefile:13: *** missing separator.  Stop.

Пример Makefile:

test.elf:  test.c
    gcc test.c -o test.elf

test.elf: test.c gcc test.c -o test.elf

Пример с абстрактной целью:

all: test.elf
 
test.elf: test1.o test2.o
    gcc -o test.elf test1.o test2.o
 
test1.o test1.c
    gcc -c test1.c -o test1.o
 
test2.o test2.c
    gcc -c test2.c -o test2.o

all: test.elf test.elf: test1.o test2.o gcc -o test.elf test1.o test2.o test1.o test1.c gcc -c test1.c -o test1.o test2.o test2.c gcc -c test2.c -o test2.o

Рассмотри последний пример:
Первым выполняется all т.к. находится в начале Makefile. all зависит от test.elf и файла или директории с именем all не существует, поэтому всегда будет происходить проверка цели с именем test.elf.

test.elf зависит от test1.o и test2.o, по этому сначала будет проверена цель test1.o затем test2.o

При проверке цели test1.o сравниваются дата и время изменения файла test1.o и test1.c. Если файл test1.o не существует или файл test1.c был изменены позднее чем test1.o то будет выполнена команда gcc -с test1.c -o test1.o.

Аналогично будет проверена цель test2.o.

После этого сравниваются дата и время изменения файла test.elf и файлов test1.o test2.o. Если test1.o или test2.o новее то будет выполнена команда gcc -o test.elf test1.o test2.o

Таким образом отслеживаются изменения в файлах test1.с и test2.c.

P/S надеюсь данная заметка упростит создание makefile, но если есть какие-то вопросы — напишите в комментарии, постараюсь ответить.

Как запустить makefile в Windows?

У меня есть несколько демо, которые я загрузил, и они поставляются с Makefile.win и Makefile.компания SGI. Как я могу запустить их в Windows для компиляции демонстраций?

129

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Theme: Overlay by Kaira Extra Text
Cape Town, South Africa