Как этот Makefile делает программу на C без указания компилятора?

41

Я использовал Makefile из книги " Advanced Linux Programming (2001)" [code] . Мне было странно видеть, что GNU make правильно компилирует код, даже не указав компилятор в Makefile. Это как выпечка без рецепта!

Это минимальная версия кода:

test.c

int main(){}

Makefile

all:            test

и сделать действительно работает! Это команда, которую он выполняет:

cc     test.c   -o test

Я не смог найти ничего полезного в документации. Как это возможно?


PS Еще одно примечание: даже язык не указан; Потому test.cчто доступно, GNU makeиспользует cc. Если существует test.cppили test.cc(когда нет test.c), он использует g++(а не c++).

HO1
источник
4
«Это как выпечка без рецепта!» Рецепт скажет вам кипятить воду, но не нужно ли вам кипятить воду, используя кастрюлю на газовой плите, кастрюлю на индукционной плите, электрический чайник или котел, поставленный на штатив над огнем. Он даже не скажет, где взять воду. Это все равно, что сказать makeкипятить воду, и, используя свои внутренние правила, makeпросто
поймет
1
@Rhymoid Это как кричать: я хочу торт! А потом робот по имени makeпроверяет ваш холодильник и узнает, что есть немного муки, а затем выпекает для вас торт по умолчанию из своего внутреннего рецепта. :-)
Ho1
@ Ho1: Робот может спросить, какой торт вы хотите, сэр? :): D
Туши

Ответы:

68

Make делает это, используя свои встроенные правила . В частности, они рассказывают, как компилировать код на C и как связывать однообъектные программы.

Вам даже не нужен Makefile:

make test

будет работать без одного.

Чтобы увидеть скрытые правила, которые делают все это возможным, используйте -pпараметр без Makefile:

make -p -f /dev/null

Как указывает alephzero , в Make очень давно были встроенные правила (если не всегда); Первая версия Стюарта Фельдмана в Unix V7 определяет ихfiles.c , и в его статье 1979 года упоминается о них. Они также являются частью спецификации POSIX . (Это не означает, что все реализации Make поддерживают их - старая Borland Make для DOS этого не делает, по крайней мере до версии 3.0.)

Стивен Китт
источник
2
Я так и думал, но POSIX их тоже указывает !
Стивен Китт
5
@KingZoingo Make фактически является своего рода механизмом логического вывода: он имеет набор правил (встроенных и из Makefile), существующих артефактов (файлов в текущем каталоге или именованных в Makefile) и запрошенных артефактов (целей в Make - файл); он просто пытается сопоставить правила и существующие артефакты, чтобы определить, может ли он использовать их для получения запрошенных артефактов. Встроенные правила говорят, что его test.cможно использовать для производства test. make -dподробно покажет вам процесс ...
Стивен Китт
4
@ Ho1 @StephenKitt Это было makeзадолго до того, как были изобретены GNU или POSIX. Первая версия была написана почти 40 лет назад, и до этого было несколько прототипов, созданных из сценариев оболочки.
Алефзеро
3
@jamesqf по- CPPпрежнему вызывает препроцессор ( cc -Eобычно); компилятор C ++ есть CXX.
Стивен Китт
3
@ Ho1 CXXв данном контексте - это переменная Make, а не команда - $(CXX)в Makefile будет заменена команда для запуска компилятора C ++.
Стивен Китт