Разное

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 $@
 

Теперь рассмотрим, что здесь произошло. В первой строке мы объявили переменную с именем 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 $@

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 $@

bar.o: bar.c
    cc -c $< -o $@

 

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

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

%.o: %.c
    cc -c $< -o $@
 

Неявные правила говорят о 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 отслеживает правила и другие цели). Правило — это просто обычная команда (вызов компилятора, копирование, удаление и проч.), выполняемая шеллом.
— Переменные $@, $< , $^ называются автоматическими (automatic variables).

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

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

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 $@
 
program: $(OBJECTS)
    gcc $(OBJECTS) -o $@
 
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 $@
 
.PRECIOUS: $(TARGET) $(OBJECTS)
 
$(TARGET): $(OBJECTS)
    $(CC) $(OBJECTS) -Wall $(LIBS) -o $@
 
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 скрипт:

[user@ubuntu ~/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

автор: 0x6B6F77616C74

8 ответов


Если у вас есть Visual Studio, Запустите командную строку Visual Studio из меню Пуск, перейдите в каталог, содержащий Makefile.win и типа этого:

nmake -f Makefile.win

вы также можете использовать обычную командную строку и запустите файл vsvars32.летучая мышь c:\Program файлы (x86)\Microsoft Visual Studio 9.0\Common7\Tools для VS2008). Это настроит среду для запуска nmake и поиска инструментов компилятора.

88

автор: Marcelo Cantos


проверить cygwin, среда Unix для Windows


проверить GnuWin ‘ s сделать, который предоставляет собственный порт для Windows (без необходимости полной среды выполнения, такой как Cygwin)

28

автор: Sean Lynch


вот мой быстрый и временный способ запустить Makefile

  • скачать сделать С SourceForge: gnuwin32
  • установки
  • перейдите в папку установки

C:\Program файлы (x86)\GnuWin32\bin

  • скопировать все файлы в мусорное ведро к папка, содержащая Makefile

libiconv2.файл DLL libintl3.dll make.exe

  • откройте cmd (вы можете сделать это с помощью щелкните правой кнопкой мыши с shift) в папке, содержащей Makefile и run

make.exe

сделано.

кроме того, вы можете добавить аргументы после команды, такие как

make.exe skel


С Visual Studio 2017 мне пришлось добавить эту папку в мою переменную env пути Windows 10:

C:\Program Files (x86)\Microsoft Visual Studio17\Professional\VC\Tools\MSVC.10.25017\bin\HostX64\x64

есть также HostX86


Если это» nmake Makefile», то есть синтаксис совместим с NMake, он будет работать.

часто предоставляются стандартные файлы Makefile Linux и NMake выглядит многообещающе. Однако следующая ссылка берет простой файл Makefile Linux и объясняет некоторые фундаментальные проблемы, с которыми можно столкнуться.

Makefiles в Windows


во-первых, добавьте путь к Visual studio common tools (c:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools) в системный путь. Чтобы узнать, как добавить путь в системный путь, проверьте этот веб-сайт:
http://www.computerhope.com/issues/ch000549.htm. Тебе просто нужно это один раз.

после этого, когда вам нужно, откройте командную строку и выполните vsvars32.bat чтобы добавить все необходимые пути visual studio tools в системный путь.

тогда вы можете позвонить nmake -f makefile.mak

PS: путь визуального studio common tools может отличаться в вашей системе. Пожалуйста, измените его соответствующим образом.

0

автор: Validus Oculus


возможно, вы можете попробовать IDE NetBeans.


Простой, универсальный Makefile — qaru.

Переполнение стека

  1. Около
  2. Продукты

  3. Для команд
  1. Переполнение стека
    Общественные вопросы и ответы

  2. Переполнение стека для команд
    Где разработчики и технологи делятся частными знаниями с коллегами

  3. Вакансии
    Программирование и связанные с ним технические возможности карьерного роста

  4. Талант
    Нанимайте технических специалистов и создавайте свой бренд работодателя

  5. Реклама
    Обратитесь к разработчикам и технологам со всего мира

  6. О компании

.Учебное пособие по

Makefile на примере

Это руководство основано на темах из книги GNU Make. В этом руководстве используются в основном примеры, чтобы помочь быстро объяснить концепции, изложенные в книге.

Синтаксис Makefile
Makefile состоит из набора из правил . Обычно правило выглядит так:

  цели: предпосылки
   команда
   команда
   команда  
  • Цели — это имена файлов, разделенные пробелами.Обычно на каждое правило приходится только один.
  • Команды — это последовательность шагов, обычно используемых для создания цели (целей). Эти должны начинаться с символа табуляции , а не с пробелов.
  • Предварительные требования — это также имена файлов, разделенные пробелами. Эти файлы должны существовать до запуска команд для цели.

Обзор Make
Основное использование Make — перечислить набор инструкций по компиляции некоторых файлов c или c ++, хотя он может решить другие подобные проблемы.Пользователь ставит Make some goal , говорит «сгенерировать файл hello». Makefile указывает, как создать этот файл. Вот пример:

  # Поскольку цель blah является первой, это цель по умолчанию и будет запущена, когда мы запустим "make"
бла: бла.о
cc blah.o -o blah

blah.o: blah.c
cc -c blah.c -o blah.o

blah.c:
echo "int main () {return 0;}"> blah.c

чистый:
rm -f blah.o blah.c blah  

Выполнение примеров
Я сделал небольшое видео, чтобы показать, как запускать эти примеры.Вам понадобится терминал и установленная программа make. Для каждого примера поместите содержимое в файл с именем Makefile и в этом каталоге выполните команду make . Вот результат выполнения приведенного выше примера:

  $ марка
echo "int main () {return 0;}"> blah.c
cc -c blah.c -o blah.o
cc blah.o -o blah
  

В некоторых примерах, подобных приведенному выше, есть цель под названием «чистый». Запустите его через make clean , чтобы удалить файлы, которые сгенерировал make :

  $ очистить
rm -f бла.о бла. с бла
  

Простые примеры
Этот make-файл имеет единственную цель, которая называется some_file . Целью по умолчанию является первая цель, поэтому в этом случае будет запущен some_file .

  некоторый_файл:
echo «Эта строка всегда будет печатать»  

Этот файл сделает some_file в первый раз, а во второй раз заметит, что он уже создан, в результате чего make: 'some_file' будет актуальным.

  некоторый_файл:
echo "Эта строка будет напечатана только один раз"
touch some_file  

Альтернативный синтаксис: та же строка

  some_file:; touch some_file  

Символ обратной косой черты («\») дает нам возможность использовать несколько строк, когда команды слишком длинные

  некоторый_файл:
echo Эта строка слишком длинная, поэтому \
он разбит на несколько строк  

Здесь целевой some_file «зависит» от other_file .Когда мы запускаем make , будет вызвана цель по умолчанию ( some_file , так как она первая). Сначала он просматривает свой список из зависимостей , и, если какая-либо из них старше, он сначала запускает цели для этих зависимостей, а затем запускается сам. Во второй раз ни одна цель не будет запущена, потому что обе цели существуют.

  некоторый_файл: другой_файл
echo "Это будет выполняться вторым, потому что это зависит от other_file"
коснитесь some_file

другой_файл:
echo "Это запустится первым"
touch other_file  

Это всегда будет делать обе цели, потому что some_file зависит от other_file, который никогда не создается.

  некоторый_файл: другой_файл
коснитесь some_file

другой_файл:
echo «ничего»  

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

  some_file: чистый
коснитесь some_file

чистый:
rm -f some_file  

Добавление .PHONY к цели не позволит программе make запутать фальшивую цель с именем файла. В этом примере, если создается файл «clean», make clean все равно будет выполняться. .PHONY удобен в использовании, но я пропущу его в остальных примерах для простоты.

  некоторый_файл:
коснитесь some_file
прикоснуться к чистоте
 
.PHONY: чистый
чистый:
rm -f некоторый_файл
rm -f clean  

Переменные (раздел 2.4)
Переменные могут быть только строками. Вот пример их использования:

  файлов = файл1 файл2
some_file: $ (файлы)
echo "Посмотрите на эту переменную:" $ (files)
коснитесь some_file

file1:
сенсорный файл1
файл2:
сенсорный файл2
 
чистый:
rm -f file1 file2 some_file  

Неявные команды Magic (раздел 2.5)
Вероятно, одна из самых запутанных частей Make — это скрытая связь между Make и GCC. Make в значительной степени был разработан для GCC, что делает компиляцию программ на C / C ++ «простой».

  # Неявная команда: "cc blah.o -o blah"
# Примечание: не помещайте комментарий внутри правила blah.o; неявное правило не будет работать!
мля:

# Неявная команда: "cc -c blah.c -o blah.o"
blah.o:

blah.c:
echo "int main () {return 0;}"> blah.c

чистый:
rm -f blah.o blah blah.c  

Использование подстановочных знаков (Раздел 4.2)
Мы можем использовать подстановочные знаки в цели, предварительных требованиях или командах.
Допустимые подстановочные знаки: *,?, [...]

  некоторый_файл: * .c
# создать двоичный файл

* .c:
коснитесь f1.c
коснитесь f2.c
 
чистый:
rm -f * .c  

Функция подстановочных знаков (раздел 4.2.3)
Мы НЕ МОЖЕМ использовать подстановочные знаки в других местах, таких как объявления переменных или аргументы функций
Используйте вместо них функцию подстановочных знаков.

  неправильно = * .o # Неправильно
объекты: = $ (подстановочный знак *.c) # Вправо
some_binary:
коснитесь f1.c
коснитесь f2.c
эхо $ (неверно)
echo $ (объекты)

чистый:
rm -f * .c  

Директива vpath (раздел 4.3.2)
Используйте vpath, чтобы указать, где существует некоторый набор предварительных требований. Формат: vpath <шаблон> <каталоги, разделенные пробелом / двоеточием>
<шаблон> может иметь % , что соответствует любому нулю или более символам.
Вы также можете сделать это глобально с помощью переменной VPATH

  vpath%.h ../headers ../other-directory

some_binary: ../headers blah.h
прикоснуться к некоторому_ двоичному

../headers:
mkdir ../headers

blah.h:
touch ../headers/blah.h

чистый:
rm -rf ../headers
rm -f some_binary  

Целевой объект all (раздел 4.4)
Создание нескольких целей, и вы хотите, чтобы все они выполнялись? Сделайте цель все и обозначьте ее как . PHONY

  все: один, два, три
.PHONY: все

один:
коснуться одного
два:
коснуться двух
три:
коснуться трех

чистый:
rm -f one two three  

Несколько целей (раздел 4.8)
Когда существует несколько целей для правила, команды будут выполняться для каждой цели
$ @ — автоматическая переменная , которая содержит имя цели.

  все: f1.o f2.o

f1.o f2.o:
эхо $ @
# Эквивалентно:
# f1.o
# echo $ @
# f2.o
# echo $ @  

Несколько целей через подстановочные знаки (раздел 4.8)
Мы можем использовать подстановочный знак% в целях, который захватывает ноль или более любых символов. Обратите внимание, что мы не используем * .o, потому что это просто строка *.o, который может быть полезен в командах
, но является только одной целью и не расширяется.

  все: f1.o f2.o
.PHONY: все

% .o:
echo $ @  

Правила статических шаблонов (раздел 4.10)
Сделайте компиляцию loves c. И каждый раз, когда он выражает свою любовь, все сбивается с толку. Вот синтаксис нового типа правила, называемого статическим шаблоном:

  цели ...: target-pattern: prereq-patterns ...
   команды  

Суть в том, что заданной цели соответствует целевой шаблон (через подстановочный знак % ).Все, что было подобрано, называется штоком . Затем основа подставляется в шаблон prereq, чтобы сгенерировать предварительные требования цели.

Типичным вариантом использования является компиляция файлов .c в файлы .o . Вот ручной способ :

  все: foo.o bar.o
.PHONY: все

# Автоматическая переменная $ @ соответствует цели, а $ <соответствует предварительному условию
foo.o: foo.c
echo "Вызов gcc для генерации $ @ из $ <"

bar.o: bar.c
echo "Вызовите gcc для создания бара.o из bar.c "

# Соответствует всем файлам .c и создает их, если они не существуют
% .c:
 

.

Что такое Makefile и как он работает?

Если вы хотите запустить или обновить задачу при обновлении определенных файлов, вам может пригодиться утилита make . Утилите make требуется файл Makefile (или makefile ), который определяет набор задач, которые должны быть выполнены. Возможно, вы использовали make для компиляции программы из исходного кода. Большинство проектов с открытым исходным кодом используют make для компиляции окончательного исполняемого двоичного файла, который затем может быть установлен с помощью make install .

В этой статье мы рассмотрим make и Makefile , используя базовые и расширенные примеры. Перед тем как начать, убедитесь, что make установлен в вашей системе.

Базовые примеры

Начнем с печати классического «Hello World» на терминале. Создайте пустой каталог myproject , содержащий файл Makefile со следующим содержимым:

 

say_hello:
echo "Hello World"

Теперь запустите файл, набрав make в каталоге myproject .На выходе будет:

 

$ сделать
echo "Hello World"
Hello World

В приведенном выше примере say_hello ведет себя как имя функции, как и в любом языке программирования. Это называется целью . Предпосылки или зависимости следуют цели. Для простоты в этом примере мы не определили никаких предварительных условий. Команда echo "Hello World" называется рецептом .В рецепте используются предпосылки для создания цели . Цель, предпосылки и рецепты вместе составляют правило .

Подводя итог, ниже приведен синтаксис типичного правила:

 

цель: предварительные условия
рецепт

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

 final_target: sub_target final_target.c 
Recipe_to_create_final_target

sub_target: sub_target.c
Recipe_to_create_sub_target

Целевой объект не обязательно должен быть файлом; это может быть просто название рецепта, как в нашем примере. Мы называем это «фальшивыми целями».

Возвращаясь к приведенному выше примеру, при выполнении make отображалась вся команда echo «Hello World» , за которой следовал фактический вывод команды. Мы часто этого не хотим. Чтобы подавить эхо фактической команды, нам нужно запустить echo с @ :

 

say_hello:
@echo "Hello World"

Теперь попробуйте запустить и сделайте снова.Вывод должен отображать только это:


 

Давайте добавим еще несколько фальшивых целей: сгенерировать и очистить в Makefile :

 say_hello: 
@echo "Hello World"

generate:
@echo "Создание пустых текстовых файлов ..."
touch file- {1..10} .txt

clean:
@echo "Очистка ..."
rm * .txt

Если мы попытаемся запустить make после изменений, будет выполнена только цель say_hello .Это потому, что только первая цель в make-файле является целью по умолчанию. Часто называемая целью по умолчанию , по этой причине вы будете видеть все в качестве первой цели в большинстве проектов. все обязаны вызывать другие цели. Мы можем изменить это поведение, используя специальную фальшивую цель с именем .DEFAULT_GOAL .

Давайте включим это в начало нашего make-файла:

  .DEFAULT_GOAL: = создать  

Это запустит цель сгенерировать по умолчанию:

 

$ make
Создание пустых текстовых файлов...
сенсорный файл - {1..10} .txt

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

Давайте включим в ложную цель все и удалим .DEFAULT_GOAL :

 all: say_hello generate 

say_hello:
@echo "Hello World"

generate:
@echo "Создание пустых текстовых файлов... "
touch file- {1..10} .txt

clean:
@echo" Очистка ... "
rm * .txt

Перед запуском make давайте включим еще одну специальную цель-подделку, .PHONY , где мы определим все цели, не являющиеся файлами. make запустит свой рецепт независимо от того, существует ли файл с таким именем или каково время его последнего изменения. Вот полный make-файл:

 .PHONY: all say_hello генерировать чистый 

all: say_hello генерировать

say_hello:
@echo "Hello World"

generate:
@echo "Создание пустых текстовых файлов... "
touch file- {1..10} .txt

clean:
@echo" Очистка ... "
rm * .txt

make должен вызвать say_hello , а сгенерирует :

 

$ make
Hello World
Создание пустых текстовых файлов ...
touch file- {1..10} .txt

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

 

$ очистить
Очистить...
RM * .txt

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

Дополнительные примеры

Переменные

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

Самый простой способ определить переменную в make-файле - использовать оператор = . Например, чтобы присвоить команду gcc переменной CC :

  CC = gcc
  

Это также называется рекурсивной расширенной переменной и используется в правиле, как показано ниже:

 

привет: привет.c
$ {CC} hello.c -o привет

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

  gcc hello.c -o привет
  

И $ {CC} , и $ (CC) являются действительными ссылками для звонка gcc . Но если кто-то попытается переназначить переменную самой себе, это вызовет бесконечный цикл. Проверим это:

 CC = gcc 
CC = $ {CC}

все:
@echo $ {CC}

Запуск make приведет к:

 

$ make
Makefile: 8: *** Рекурсивная переменная CC ссылается на себя (в конце концов).Стоп.

Чтобы избежать этого сценария, мы можем использовать оператор : = (он также называется просто расширенной переменной ). У нас не должно возникнуть проблем с запуском make-файла ниже:

 CC: = gcc 
CC: = $ {CC}

все:
@echo $ {CC}

Узоры и функции

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

 # Использование: 
# make # скомпилировать весь двоичный код
# очистить # удалить ВСЕ двоичные файлы и объекты

.PHONY = all clean

CC = gcc # компилятор для использования

LINKERFLAG = -lm

SRCS: = $ (подстановочный знак * .c)
BINS: = $ (SRCS:%. C =%)

all: $ {BINS}

%:% .o
@echo "Checking .."
$ {CC} $ {LINKERFLAG} $ <-o $ @

% .o:% .c
@echo "Создание объекта .. "
$ {CC} -c $ <

clean:
@echo" Очистка ... "
rm -rvf * .o $ {BINS}

  • Строки, начинающиеся с # , являются комментариями.

  • Строка .PHONY = all clean определяет поддельные цели все и чистые .

  • Переменная LINKERFLAG определяет флаги, которые будут использоваться с gcc в рецепте.

  • SRCS: = $ (подстановочный знак * .c) : $ (подстановочный знак) - одна из функций для имен файлов . В этом случае все файлы с расширением .c будут храниться в переменной SRCS .

  • BINS: = $ (SRCS:%. C =%) : Это называется ссылкой на подстановку . В этом случае, если SRCS имеет значения 'foo.c bar.c' , BINS будет иметь 'foo bar' .

  • Строка все: $ {BINS} : Фальшивая цель все вызывает значения в $ {BINS} как отдельные цели.

  • Правило:

     

    %:% .o
    @echo "Проверка.. "
    $ {CC} $ {LINKERFLAG} $ & lt; -o $ @

    Давайте рассмотрим пример, чтобы понять это правило. Предположим, что foo - одно из значений в $ {BINS} . Тогда % будет соответствовать foo (% может соответствовать любому целевому имени). Ниже представлено правило в развернутом виде:

     

    foo: foo.o
    @echo "Проверка .."
    gcc -lm foo.o -o foo

    Как показано, % заменяется на foo . $ < заменяется на foo.o . $ < формируется в соответствии с предварительными условиями, а $ @ соответствует целевому. Это правило будет вызываться для каждого значения в $ {BINS}

  • Правило:

     

    % .o:% .c
    @echo "Создание объекта .."
    $ {CC} -c $ & lt;

    Каждое предварительное условие в предыдущем правиле считается целью для этого правила. Ниже представлено правило в развернутом виде:

     

    foo.o: foo.c
    @echo "Создание объекта.. "
    gcc -c foo.c

  • Наконец, мы удаляем все двоичные файлы и объектные файлы в цели clean .

Ниже приведена перезапись вышеуказанного make-файла при условии, что он помещен в каталог, содержащий единственный файл foo.c:

 # Использование: 
# make # скомпилировать весь двоичный код
# очистить # удалить ВСЕ двоичные файлы и объекты

.PHONY = все очистить

CC = gcc # компилятор использовать

LINKERFLAG = -lm

SRCS: = foo.c
BINS: = foo

all: foo

foo: foo.o
@echo "Проверка .."
gcc -lm foo.o -o foo

foo.o: foo.c
@echo "Создание объект .. "
gcc -c foo.c

clean:
@echo" Очистка ... "
rm -rvf foo.o foo

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

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

.

Пример простых файлов Makefile для C (или C ++)

Самый простой Makefile для компиляции программы на C (или C ++)
из одного файла .c с правилами make и make clean,
выглядит примерно так (не забудьте добавить символ TAB перед
командная часть):

  # создать исполняемый файл с именем myprog из myprog.c
  все: myprog.c
 gcc -g -Wall -o myprog myprog.c

  чистый:
$ (RM) myprog
 

немного более общий простой make-файл

Чуть более общая версия make-файла выше,
использует переменные makefile
(просто измените определения переменных для создания исполняемых файлов в разных сетях
или с разными компиляторами или флагами компилятора):

  # компилятор: gcc для программы C, определите как g ++ для C ++
  CC = gcc

  # флаги компилятора:
  # -g добавляет отладочную информацию в исполняемый файл
  # -Wall включает большинство, но не все предупреждения компилятора
  CFLAGS = -g -Стена

  # исполняемый файл целевой сборки:
  TARGET = myprog

  все: $ (TARGET)

  $ (ЦЕЛЬ): $ (ЦЕЛЬ).c
  $ (CC) $ (CFLAGS) -o $ (TARGET) $ (TARGET) .c

  чистый:
  $ (RM) $ (ЦЕЛЬ)
 

Пример создания исполняемого файла из нескольких файлов .o:

#
# Это пример Makefile для программы countwords. Эта
# программа использует как модуль сканера, так и модуль счетчика.
# Ввод "make" или "make count" создаст исполняемый файл.
#

# определить некоторые переменные Makefile для компилятора и флагов компилятора
# для использования переменных Makefile позже в Makefile: $ ()
#
# -g добавляет отладочную информацию в исполняемый файл
# -Wall включает большинство, но не все предупреждения компилятора
#
# для C ++ определить CC = g ++
CC = gcc
CFLAGS = -g -Стена

# ввод 'make' вызовет первую целевую запись в файле
# (в данном случае целевая запись по умолчанию)
# вы можете назвать эту целевую запись как угодно, кроме "default" или "all"
# - это наиболее часто используемые имена по соглашению
#
по умолчанию: count

# Для создания счетчика исполняемых файлов нам понадобятся объектные файлы
# countwords.o, counter.o и scanner.o:
#
count: countwords.o counter.o scanner.o
$ (CC) $ (CFLAGS) -o count countwords.o counter.o scanner.o

# Для создания объектного файла countwords.o нам понадобится исходный код
# файлы countwords.c, scanner.h и counter.h:
#
countwords.o: countwords.c scanner.h counter.h
$ (CC) $ (CFLAGS) -c countwords.c

# Для создания объектного файла counter.o нам понадобятся исходные файлы
# counter.c и counter.h:
#
counter.o: counter.c counter.h
$ (CC) $ (CFLAGS) -c counter.c

# Создать сканер объектных файлов.о, нам нужны исходные файлы
# scanner.c и scanner.h:
#
scanner.o: scanner.c scanner.h
$ (CC) $ (CFLAGS) -c scanner.c

# Чтобы начать с нуля, наберите 'make clean'. Эта
# удаляет исполняемый файл, а также старый объект .o
# файлы и * ~ файлы резервных копий:
#
чистый:
$ (RM) count * .o * ~
 

.

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

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