Если вы используете make, вам следует придерживаться его основного принципа, который мы можем обобщить следующим образом:
FILE-to-create: files-used-to-create-FILE
shell-commands-that-create-FILE
Это чрезвычайно важно, потому что make сравнивает время последнего изменения файлов, чтобы определить, что устарело и чтодо даты.Это не формальность, и это меняет функциональность.Итак, в вашем случае вы должны иметь:
bar.o: bar.c
cc -c -g -o bar.o bar.c
baz.o: baz.c
cc -c -g -o baz.o baz.c
foo.o: foo.c
cc -c -g -Wno-implicit-function-declaration -o foo.o foo.c
barbaz.so: bar.o baz.o
ld -shared -o barbaz.so bar.o baz.o
bbfoo: barbaz.so foo.o
ld -lc --entry=main -o bbfoo barbaz.so foo.o
Обратите внимание, что у make есть несколько полезных функций, которые могут помочь в разложении такого простого набора правил.Например, автоматические переменные ($@
, $^
...), неявные правила (например, для создания *.o
объектных файлов из *.c
исходных файлов), неявные переменные, используемые неявными правилами (CFLAGS
, LD
...), значения переменных, специфичных для цели (см. Объявление CFLAGS
для foo.o
) и многое другое.Пример:
CFLAGS := -g
foo.o: CFLAGS += -Wno-implicit-function-declaration
barbaz.so: bar.o baz.o
$(LD) -shared -o $@ $^
bbfoo: barbaz.so foo.o
$(LD) -lc --entry=main -o $@ $^
Да, для объектных файлов вообще нет правил, make уже знает, как их создавать.