Простой ответ - поведение make
.Но это не дает понимания, как это работает, поэтому давайте углубимся.
Мы начнем с первого Makefile.Поскольку в моем каталоге есть только один файл fizzbuzz.s
, переменная BIN
будет равна fizzbuzz
.Make
ищет цель fizzbuzz
, но цели нет.По этой причине make
обрабатывает встроенные правила.Он ищет файлы с расширением, добавленным к цели fizzbuzz
, и, если он искал файлы, он обрабатывает собственные правила.Я попытался удалить Makefile и запустить команду: make fizzbuzz
, и она запускает другую
cc fizzbuzz.s -o fizzbuzz
.
Он равен первому Makefile.
Теперь мы будем использовать второй Makefile.Когда я изменил расширение .s
на .asm
, это сработало.Интересное поведение, потому что make
не имеет встроенных правил для расширения .asm
.Я хотел получить понимание, поэтому я вернулся .asm
к .s
назад.Мой второй Makefile имеет правило для цели без расширения:
%: %.o
$(LNK) -melf_i386 $< -o $@
Но он не работает должным образом и работает как без Makefile.Это происходит, я полагаю, потому что %
имеет последний приоритет выполнения после встроенных правил.Мы можем изменить поведение, добавив MAKEFLAGS += --no-builtin-rules
в Makefile, и все работает отлично.
Но я заметил одну странную вещь без опции.Я выполнил команду make fizzbuzz.o
, и она была построена fizzbuzz.o
(она обрабатывает команду из моего Makefile).Итак, ок.Давайте снова запустим make
.Я запускаю его, и он построил мне окончательную цель fizzbuzz
.Сюрприз!
Так что правило
%: %.o
$(LNK) -melf_i386 $< -o $@
работает, когда в текущем каталоге есть объектные файлы (.o).Я не знаю, что это, ошибка или функция (ИМХО странная функция), но она работает так.
Наконец, у нас есть два решения, чтобы заставить работать второй Makefile, и они следующие:
- опустите встроенные правила, заменив расширение
.s
на .asm
или любое другое, которое не имеет встроенных правил, в make
- отключите встроенные правиладобавив в Makefile параметр
MAKEFLAGS += --no-builtin-rules
или запустите с make -R
или make -r