12.06.2009 20:01

chemikadzeВсе самое необходимое, что нужно знать о make

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



Мы остановимся на первом варианте, как на самом распространенном. Все, что нужно для работы make - файл с описанием правил сборки, находящийся в каталоге с исходным кодом - Makefile. Что же входит в состав Makefile?


Переменные

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

1
2
3
4
5
6
7
OBJ = main.o stuff_one.o stuff_two.o # обычный способ, при котором значение определяется при использовании

OBJ2 := main.o # здесь значение переменной определяется при присваивании, до использования

OBJ2 := $(OBJ2) stuff_one.o

OBJ2 += stuff_two.o # другая запись предыдущей строки



Обратите внимание на разницу в интерпритации. Если вы сделаете так:

1
2
3
OBJ3 = main.o

OBJ3 = $(OBJ3) stuff.o



make войдет в цикл, вычисляя значение переменной. Все дело в том, что при сипользовании = make хранит значение в виде, который присваивался, тоесть "$(OBJ3) stuff.o". Переменная замыкается сама на себя и вуаля: у нас есть нерабочий Makefile. Если же писать через := или =, значение после выполнения аналогичного кода будет "main.o stuff.o".
Правила

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

1
2
3
binary: main.o stuff_one.o stuff_two.o

g++ -o binary main.o stuff_one.o stuff_two.o



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

Более красиво это можно сделать, если у вас определены переменные со списком файлов:

1
2
3
binary: $(OBJS)

g++ -o binary $(OBJS)



Кроме файлов, целью может служить операция:

1
2
3
4
5
install:

install -m 744 binary /usr/bin

.PHONY: install



Так как у нас нет целевого файла install, мы вынуждены использовать директиву .PHONY, сообщающую make о том, что install - не имя файла.
Суффиксы

Применяются для автоматического составления зависимостей. Такие распространенные расширения как .c, .cpp make обрабатывает автоматически, создавая из них объектные файлы с тем же именем, а для нестандартных нам потребуется создание суффиксов. Вот вам стандартный пример:

1
2
3
4
5
.c.o:

$(CC) $(CFLAGS) $(CXXFLAGS) -o $@ $<

.SUFFIXES: .c .o



Здесь каждому файлу .o ставится в зависимость файл .c, который нужно обработать компилятором с соответствующими параметрами коммандной строки, причем $@ - подстановка имени выходного файла, а $< - шаблон подстановки первой зависимости (также есть $^ означающий все зависимости).

Кроме того, есть еще так называемые шаблонные правила, имеющие синтаксис сходный с обычными правилами:

1
2
3
%.c: %.o:

$(CC) $(CFLAGS) $(CXXFLAGS) -o $@ $&lt;





Еще стоит упомянуть об одной особенности обработки комманд make: каждая строка выполняется в собственном коммандном интерпритаторе, то есть после выполнения комманды cd в следующей строке текущий каталог не изменится. Для этого нужно использовать многострочные комманды:

1
2
3
4
5
6
7
8
9
cd dir1; \

command; \

if (условие); then \

dosomethingelse; \

fi



Вот в принципе и все, что нужно знать для создания небольших Makefile'ов, так что вот вам реальный примерчик:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# CXXFLAGS += -D DEBUG_BFVM

CXXFLAGS += -ggdb

# CXXFLAGS += -O2



CFLAGS = $(CXXFLAGS)



all: brainfuck



brainfuck: bfvm.o brainfuck.o

g++ $(CXXFLAGS) bfvm.o brainfuck.o -o brainfuck



clean:

rm -vf *.o

.PHONY: clean



clear:

rm -vf *.o brainfuck

.PHONY: clear



install:

install -o root -g root -m 0755 brainfuck /usr/bin/brainfuck

mkdir -p -m 0755 /usr/share/brainfuck

chown root:root /usr/share/brainfuck

install -o root -g root -m 0755 ./programs/helloworld.bf /usr/share/brainfuck/helloworld.bf

.PHONY: install



uninstall:

rm -vf /usr/bin/brainfuck

rm -rvf /usr/share/brainfuck

.PHONY: uninstall





PS: источник - "Разработка приложений в среде Linux" Майкл К. Джонсон, Эрик В. Троан, полезное чтиво.


Тэги: dev script консоль
+ 23 -
Похожие Поделиться

chemikadze 12.06.2009 20:07 #
опс, забыл cut добавить
Minoru 12.06.2009 21:43 #
С позиции новичка, ничего не смыслящего в make, заявляю: отличное введение! Правда, про переменные как-то не очень хорошо объяснено - я так и непонял, чем ":=" отличается от "=".
И ещё одно: стоило бы указать источник с более подробными сведениями по теме. Почти уверен, что им будет "Разработка приложений в Linux" Джонсона и Троана, но всё же... :)
За статью плюс однозначно.
chemikadze 12.06.2009 21:45 #
угадал, спасибо за +
меня уже про make спрашивали, помню как сам искал, вот и написал =)
chemikadze 12.06.2009 21:50 #
спасибо, поправил
predator 13.06.2009 20:08 #
спасибо что помог, не знал что почитать о программировании в линуксе
Minoru 13.06.2009 23:50 #
Все спасибы chemikadze - я сам про эту книгу услышал всего два дня назад именно от него :)
bobry 12.06.2009 22:16 #
полезно, в который раз жалею что "закладки" еще (?) не реализованы
Username 13.06.2009 00:06 #
если честно, лучше б описал как правильно пользоваться make'ом, про наиболее частые встречаемые фичи типа флагов j, и префиксов а-ля
make -j3 --prefix=/usr

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

ЗЫ Кстати весьма низкий процент людей знает о make clean например.
chemikadze 13.06.2009 00:28 #
Хм, хотел написать пост именно о создании Makefile, показалось что будет полезным для тех, кто начинает писать что-то в linux. По моей личной статистике это было более востребовано, не думал что все настолько плохо... %)
Username 13.06.2009 00:29 #
новичкам бы скомпилить что-то, а не самим писать :)
но начинающим программистам это конечно подмога
chemikadze 13.06.2009 00:32 #
их читать сначала научить, этих новичков, разрешит примерно 60-70% всех проблем)
DOOMer 13.06.2009 01:16 #
Большей части нынешних новичков лучше бы научиться нормально пользоваться манами, гуглом и хелпом к пакетному менеджеру используемого ими дистра.

А уж потом пытаться что-то компилить...хотя если не научатся вниматкльно читать консольный вывод при ошибках компиляции -- то уж лучше и не пытаться.

А статья хорошая -- как раз для начинающих программировать в Linux (типа меня).
Kraplax 13.06.2009 10:53 #
Я что-то не понимаю - чего налетели-то? Неплохая статья для начинающих программистов. Мы же не говорим даже о том, что они обязательно должны быть линуксоидами - не так ли? Все это неплохо подошло бы и мне, человеку с Windows, если бы я пользовался makefile'ами напрямую. Однако я пользуюсь cmake, и все реже qmake (работа с последним все чаще сводится к qmake -poject && qmake). Поэтому надеюсь что автор еще напишет статью по CMake - система гибкая, кроссплатформенная, но довольно запутанная, так что есть о чем писать. Особенно, если писать о том, как обычный Makefile подстроить под другую систему сборки (qmake или cmake), или как файлы .pro (от qmake) правильно переделывать в CMakeLists.txt (для CMake). Вот такую бы статью я почитал с удовольствием и забукмаркил бы тут же.
Сейчас только пробежал глазами, плюсанул, ибо понял что статья неплохая, подход верный, правда, для начинающих.
chemikadze 13.06.2009 12:37 #
Если честно, то cmake для меня самого тайна за семью печатями, qmake покахватало за глаза. Вот сдам сессию - буду пробовать cmake, а пока повременю.
Kraplax 13.06.2009 15:17 #
я еще в личку тебе отпишусь, если сам надумаю что-то о cmake писать, ок? чтобы не делать нам вдвоем одну работу. Ну и у меня тоже диплом счас - мало на что времени хватает. Но ежели что - скоординируемся, так что время от времени поглядывай, не мигает ли у тебя конвертик ЛС =)
chemikadze 13.06.2009 19:58 #
служу отечеству =)
DuoV 13.06.2009 11:26 #
Отличная статья. Спасибо. Сам только начал прогать в линуксе. И makefile для меня оставались немного загадочной штукой.
xdemon 13.06.2009 11:30 #
Великолепная статья.
alt 15.06.2009 17:36 #
В 14й строке опечатка, должно быть:
.PHONY: clean
chemikadze 15.06.2009 17:38 #
ух, спасибо
idler 21.10.2009 02:51 #
Спасибо. А вот бы еще материальчик про automake/autoconf.
Возможно?
chemikadze 17.11.2009 21:21 #
К сожалению не работал.