Что не так с файлом make - PullRequest
0 голосов
/ 26 июня 2019

Я пытаюсь сделать компиляцию объектных файлов makefile в obj dir, а затем связать скомпилированный код и превратить его в исполняемый файл, вот он

CC=gcc
CFLAGS=-Iinclude.
OBJ = obj/main.o obj/print.o

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

prog: $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS)

и ошибка: Нет правила для создания цели 'obj / main.o', необходимой для 'prog'. Стоп. Это чистая копия, которую я сделал из учебника по makefile, просто чтобы убедиться, что он не работает.

Так почему эта линия не работает

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

1 Ответ

1 голос
/ 26 июня 2019

Правило такого рода ...

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

прекрасно (с GNU make - не так много с другими make реализациями). Он создает файл .o из соответствующего файла .c, где «соответствующий» означает наличие имени, образованного путем изменения конечного .o на .c. Это на самом деле не нужно, потому что make имеет встроенное правило, которое делает практически то же самое.

Сообщение

Нет правила для создания цели 'obj / main.o', необходимой для 'prog'. Стоп.

Идентифицирует obj/main.o как необходимое условие для цели prog, которая не существует и для которой нет [применимого] правила. Приведенное выше правило шаблона будет применимо, если существует соответствующий источник (в смысле, описанном выше), но, очевидно, его нет.

Чтобы быть абсолютно ясным: соответствующий источник, образованный заменой .o в obj/main.o на .c, равен obj/main.c. Если такой файл не существует, представленное вами правило шаблона не применимо для сборки obj/main.o. Сама программа make не знает и не заботится о каталогах. Команды, которые он выполняет, выполняют, но для самого make целевые и обязательные идентификаторы являются просто плоскими последовательностями символов.

Моя первая рекомендация для таких вещей - перестать пытаться быть милыми. Проще всего и чаще всего создавать объектные файлы в том же каталоге, что и их источники. Предположим, что ваши исходники C находятся в подкаталоге src/ относительно make-файла, этого make-файла будет достаточно (полагаясь на встроенное правило .c.o):

CC=gcc
CFLAGS=-Iinclude.

prog: src/main.o src/print.o
    $(CC) -o $@ $^ $(CFLAGS)

Но если вы настаиваете на компиляции объектов в отдельном каталоге, тогда ваше шаблонное правило должно отражать это:

CC=gcc
CFLAGS=-Iinclude.
OBJ = obj/main.o obj/print.o

obj/%.o: src/%.c 
    $(CC) -c -o $@ $< $(CFLAGS)

prog: $(OBJ)
    $(CC) -o $@ $^ $(CFLAGS)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...