## 
## Определим компилятор.
## 
CC=gcc

## 
## Зададим флаги стандарта языка
## Можно использовать `-std=c99`, но 89 строже.
## 
STD_FLAGS= -std=c89

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

## 
## Зададим общие флаги.
## 
FLAGS= -pedantic $(STD_FLAGS) $(WALL_FLAGS)

## 
## Зададим флаги для препроцессирования.
## 
CPP_FLAGS= -E $(FLAGS)

## 
## Зададим флаги для трансляции в ассемблер из препроцессированного кода.
## 
CPP2ASM_FLAGS= -S

## 
## Зададим флаги для получения объектного кода и ассемблера.
## 
ASM2OBJ_FLAGS= -c

## 
## Зададим флаги для получения исполняемого файла из объектного.
## 
OBJ2EXE_FLAGS= -lm

## 
## Зададим флаги для получения исполняемого файла с нуля.
## Ставим -v для "болтливого режима".
## 
CC_FLAGS=-v $(FLAGS)

## 
## Опишем суффиксы, которые используются в целях.
## 
.SUFIXES: .c .o

## 
## Цели, которые не создают одноименных файлов.
## 
.PHONY : all clean verbose

NAME=quadratic

SRC=$(NAME).c
CPP=$(NAME).prep.c
ASM=$(NAME).s
OBJ=$(NAME).o
EXE=$(NAME)

all: $(EXE)

##
## *.c -> *.prep.c
## Из исходного кода программы получается тоже код на Си,
## но с подстановкой всех define и включением всех заголовочных файлов.
##
с2cpp: $(CPP)

$(CPP): $(SRC)
	#
	# 	Препроцессирование.
	#
	$(CC) $(CPP_FLAGS) $< -o $@

##
## *.prep.c -> *.s
## Из препроцессированного кода на Си получается код ассемблера.
##
cpp2asm: $(ASM)

$(ASM): $(CPP)
	#
	# 	Трансляция в ассемблер.
	#
	$(CC) $(CPP2ASM_FLAGS) $< -o $@ 2> /dev/null

##
## *.s -> *.o
## Из кода ассемблера получается объектный файл.
## По сути он является исполняемым (в формате `ELF`, `COFF` или `MS EXE`), 
## но внешние библиотеки (например ввода-вывода) не подключены.
##
asm2obj: $(OBJ)

$(OBJ): $(ASM) 
	#
	# 	Aссемблирование (получение объектного кода).
	#
	$(CC) $(ASM2OBJ_FLAGS) $< -o $@

##
## *.o -> *.exe
## Внешние библиотеки линкуются с объектным файлом.
## На выходе получается исполняемая программа.
##	
obj2exe: $(EXE)

$(EXE):	$(OBJ)
	#
	# 	Компоновка (сборка, линковка).
	#
	$(CC) $(OBJ2EXE_FLAGS) $< -o $@


verbose: $(SRC) clean
	#
	#	Собираем все вместе но в "болтливом режиме".
	#
	$(CC) $(CC_FLAGS) $< -o $(EXE)


clean:
	rm -f $(CPP) $(ASM) $(OBJ) $(EXE)

