Я работал над этим make-файлом часами. Он продолжает получать сообщение об ошибке: make: *** Нет правила для создания цели 'hangman. c', которая требуется для hangman.o. Стоп - PullRequest
1 голос
/ 02 мая 2020
CFLAGS=-std=c99 -Wall
CC=gcc

hangman: hangman.o hangman.c
    $(CC) $(CFLAGS) hangman.o hangman.c -o hangman

hangman.o: hangman.c
    $(CC) $(CFLAGS) -c hangman.c

clean:
    rm -f hangman *.o

1 Ответ

0 голосов
/ 04 мая 2020

Ну, hangman (двоичный файл программы) зависит только от hangman.o, но не от hangman.c, который уже был скомпилирован в hangman.o (на этапе компиляции).

In Makefile, вы только указываете прямые зависимости, в то время как make(1) выполняет всю остальную работу.

Я использую для обозначения всех объектов в программе в переменной, так как они будут использоваться несколько раз. Таким образом:

# Makefile -- make file for hangman.

targets = hangman

hangman_objs = hangman.o

hangman: $(hangman_objs)
       $(CC) $(LDFLAGS) -o hangman $(hangman_objs)

и ничего больше, поскольку make(1) имеет правило c для автоматов, то есть

.c.o:
       $(CC) $(CFLAGS) -o $@ -c $<

, которое эквивалентно этому правилу:

hangman.o: hangman.c
       $(CC) $(CFLAGS) -o hangman.o -c hangman.c

(и то же самое для каждого файла .c и .o, который вы можете иметь.)

Кстати, ошибка, которую вы получаете, заключается в том, что make нашла зависимость от hangman.c, но не находит ни одного файла с именем hangman.c, поэтому он должен его собрать, но вы не предоставляете этот файл. Вы, вероятно, стерли файл hangman.c (что иногда случается, если вы неправильно вводите файлы в Makefile, заканчиваете стиранием файлов, которые важны для вас) В этом случае он пытается собрать handman, который зависит от handman.o, который зависит от handman.c, так что отсутствие handman.c не дает make(1) сказать, что у меня есть зависимость от handman.c, но такой файл не найден (и у меня нет зависимости, которая позволяет мне строить it)

Если ваш проект является проектом с одним исходным кодом, тогда вы можете избежать генерации hangman.o и создать Makefile следующим образом:

hangman: hangman.c
        $(CC) $(CFLAGS) $(LDFLAGS) -o hangman hangman.c

, который утверждает явное, прямая ссылка из двоичного файла на исходный код. В этом случае вы не используете флаг -c для компилятора, чтобы просто компилировать, не связываете и не собираете свой исполняемый файл напрямую с помощью одной команды. Это не используется в больших проектах, так как обычно вы хотите просто скомпилировать источники, которые изменились. Как в этом примере:

hangman_objs = hang.o man.o foo.o bar.o a.o b.o c.o

hangman: $(hangman_objs)
        $(CC) $(LDFLAGS) -o hangman $(hangman_objs)

если вы развернете переменную, вы получите это правило:

hangman: hang.o man.o foo.o bar.o a.o b.o c.o
        cc  -o hangman hang.o man.o foo.o bar.o a.o b.o c.o

#all this are automatic dependencies generated from
#  .c.o:
#       $(CC) $(CFLAGS) -c $< -o $@
# for the files hang.o man.o foo.o bar.o a.o b.o c.o

hang.o: hang.c
        cc -O2 -pipe -c hang.c -o hang.o
man.o: man.c
        cc -O2 -pipe -c man.c -o man.o
foo.o: foo.c
        cc -O2 -pipe -c foo.c -o foo.o
bar.o: bar.c
        cc -O2 -pipe -c bar.c -o bar.o
a.o: a.c
        cc -O2 -pipe -c a.c -o a.o
b.o: b.c
        cc -O2 -pipe -c b.c -o b.o
c.c: c.c
        cc -O2 -pipe -c c.c -o c.o

, но вы не должны использовать как объектный код, так и исходный код на этапе связывания вашей программы. Компилятор свяжет предоставленный вами файл hangman.o и скомпилирует его (который генерирует новый hangman.o), и попытается связать обе (две версии одного и того же кода), что может привести к новым ошибкам.

Мой подход к вашей программе будет:

# main targets to build (programs)
targets     =    hangman

# toclean maintains everything must be erased on clean.
toclean     = $(targets)

# object files of hangman target
hangman_objs = hangman.o foo.o

# add all those objects to the toclean variable.
toclean += $(hangman_objs)

# libraries
hangman_ldflags = -L path/to/libbar
hangman_libs = -lbar

# main target all
all: $(targets)
# ... and clean
clean:
        rm -f $(toclean)

# just the link phase, the compiling is automatically done.
hangman: $(hangman_objs)
        $(CC) $(LDFLAGS) $($@_ldflags) -o $@ $($@_objs) $($@_libs)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...