Если вы действительно новичок, часто бывает полезно начать с простых make-файлов, пока вам не понадобятся дополнительные функции.
main: main.c
gcc -O2 -o main -lwiringPi main.c
Обратите внимание, что пробел перед gcc
является одиночным символом табуляции.
Как только вы научитесь этому, вы можете заменять различные элементы, чтобы упростить копирование и поддержку ваших «правил создания». Например, %^
означает «каждый зависимый источник, поэтому переписывание правила будет
main: main.c
gcc -O2 -o main -lwiringPi $^
. Иногда вам может потребоваться простая реконфигурация компилятора, поэтому, если у вас есть дюжина правил, и хотел настроить компилятор в одном месте
CC=gcc
main: main.c
$(CC) -O2 -o main -lwiringPi $^
расширил бы переменную CC
до значения gcc
во время сборки. Существует верхний предел полезности этого расширения, например, если что-то является «одним из множества одинаковых элементов», возможно, вы не захотите объявлять переменную для этого отдельного элемента. Например, ваш WPIFLAG
, вероятно, всегда требуется и, вероятно, не очень удачно перенастраивается. Mabye переменная флагов загрузчика делает больше смысла.
LDFLAGS=-lwiringPi -lm -lwhatever
и переменная флагов компилятора
CFLAGS=-O2 -Werror -Wfatal-errors
Что приведет к более разумному
main: main.c
$(CC) $(CFLAGS) -o main $(LDFLAGS) $^
Наконец, вы можете заменить цель main
в данном случае с другой специальной переменной. $@
что означает «строится цель»
main: main.c
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $^
Обратите внимание, что для объектных файлов вы используете lis Считая все ваши объекты зависимыми от всех ваших источников. Если вы хотите поддерживать независимые правила для построения объекта, вам нужно сделать что-то другое
main: main.o
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $^
И вам понадобятся правила для каждого объекта.
main.o: main.c
$(CC) $(CFLAGS) -c -o $@ $(LDFLAGS) $^
, но он станет труд набирать это правило для каждого объекта Чтобы автоматизировать это правило, вы будете использовать шаблон, основанный на суффиксах файлов, и суффиксное правило.
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c $<
Обратите внимание, что приведенное выше правило основывается на поведении по умолчанию $ (CC), которое должно генерировать a something.o
, когда something.c
скомпилирован с флагом -c
. Если вы хотите сделать выходной файл явным,
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $@ $<
Это суффиксное правило действует как макрос. Когда кому-то понадобится thing.o
, он построит его из thing.c
, если thing.c
существует, даже если нет явного правила для thing.c
. С этим вы можете собрать весь свой объект. на исходной main
мишени. (Мы удалим CFLAGS, так как компиляция не будет происходить, а будет только связывание)
main: main.o other.o first.o list.o end.o
$(CC) -o $@ $(LDFLAGS) $^
Но некоторые считают, что перечисление объекта является проблемой, и любят помещать их в переменную
main: $(OBJS)
$(CC) -o $@ $(LDFLAGS) $^
, что означает, что вам нужно будет объявить и установить OBJS
OBJS = main.o other.o first.o list.o end.o
Но отслеживать промежуточные файлы довольно странно, так почему бы не отслеживать фактические источники
SOURCES = main.c other.c first.c list.c end.c
Хорошо, но как мы получим требуемый OBJS
от SOURCES
? Мы разобьем SOURCES
, изменив суффиксы на .o
OBJS = ${SOURCES:.c=.o}
Конечный результат
SOURCES = main.c other.c first.c list.c end.c
OBJS = ${SOURCES:.c=.o}
CC=gcc
CFLAGS=-O2 -Werror -Wfatal-errors
LDFLAGS=-lwiringPi -lm -lwhatever
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $@ $<
main: ${OBJS}
$(CC) -o $@ $(LDFLAGS) $^