Как разрешить GNU make, создающую "круговую ошибку main. c" - PullRequest
1 голос
/ 07 мая 2020

// makefile.conf

.SUFFIXES : .c .o

cc = gcc
CFLAG = -c
OFLAG = -o
O2FLAG = -O2
WPIFLAG = -lwringPi
RM = rm -rf

TARGET_SRCS = main.c
TARGET_OBJS = $(TARGET_SRCS:$.c=$.o)
TARGET_NAMES = $(TARGET_SRCS:$.c=$)
BINARY_NAME = LED_TEST

// makefile

include makefile.conf

$(TARGET_OBJS) : $(TARGET_SRCS)
        $(CC) $(O2FLAG) $(CFLAG) $(OFLAG) $^

Я пытаюсь понять, как работает gnu make и как ее использовать. Тем не менее, я новичок.

Я пытаюсь использовать make в своем задании (не обязательно, просто моя страсть) для запуска простого кода, который загорается светодиодом с помощью wiringpi.

На самом деле есть только один main. c, и я хочу создать make-файл, который запускает

gcc -O2 -c -o main.o main.c

gcc -o main main.o -lwiringPi

Поскольку мой последний код не работал, (постоянно получаю циклический main. c <- main . c ошибка отказа от зависимости) </p>

Я пытался создать код, который запускает только

gcc -O2 -c -o main.o main.c

, но все равно получаю круговую ошибку main. c, и я не знаю, что это означает.

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

Итак, я пытаюсь увидеть коды и создать один из того, что я видел.

Я думаю, что понимаю концепцию makefile.conf, но все еще не понимаю функцию of .SUFFIXES.

Я понял, что заметил make, что я создам правило с. c и .o, коды после этого в makefile.conf определяют переменные, которые будут использоваться в makefile.

Как я могу исправить код? Когда фактическое «назначение» заняло всего пять минут, включая добавление комментариев.

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

Первый make-файл:

main:
    gcc -O2 -c -o main.o main.c
    gcc -o main main.o -lwiringPi

Когда это работает идеально, второй make-файл:

main: main.o
    gcc -o main main.o -lwiringPi

main.o: main.c
    gcc -O2 -c -o main.o main.c

Когда это работает отлично, третий make-файл:

main: main.o
    gcc -o $@ $^ -lwiringPi

main.o: main.c
    gcc -O2 -c -o $@ $<

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

1 голос
/ 07 мая 2020

Если вы действительно новичок, часто бывает полезно начать с простых 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) $^
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...