Я новичок в make-файлах и пытаюсь написать файл, который компилирует файлы из разных папок. Вы можете увидеть распределение моих файлов в выводе команды дерева, которую я добавил в пост: Я хочу, чтобы мои файлы заголовков находились в папке include, некоторые файлы библиотек — в srclib, мои основные исходные файлы — в src, а сгенерированные файлы .o — в lib. Для начала я попробовал рекурсивные make-файлы, но не могу скомпилировать tcp.c, потому что компилятор не может найти tcp.h, я застрял.
.
|-- includes
| `-- tcp.h
|-- lib
|-- makefile
|-- src
| |-- cliente.c
| `-- servidor_preforked.c
`-- srclib
`-- tcp.c





нужно указать где найти заголовок вашему компилятору, для gcc это делается опцией -I
Например, если вы создаете a.out в библиотека, ваш make-файл может быть:
lib/a.out:
gcc -o lib/a.out -I includes srclib/tcp.c src/cliente.c src/servidor_preforked.c
Чтобы также создавать объекты в библиотека :
all::lib/a.out
GCC = gcc -ansi -pedantic -Wextra
lib/tcp.o : srclib/tcp.c includes/tcp.h
$(GCC) -c -o lib/tcp.o -I includes srclib/tcp.c
lib/cliente.o : src/cliente.c includes/tcp.h
$(GCC) -c -o lib/cliente.o -I includes src/cliente.c
lib/servidor_preforked.o : src/servidor_preforked.c includes/tcp.h
$(GCC) -c -o lib/servidor_preforked.o -I includes src/servidor_preforked.c
lib/a.out : lib/tcp.o lib/cliente.o lib/servidor_preforked.o
$(GCC) -o lib/a.out -I includes lib/tcp.o lib/cliente.o lib/servidor_preforked.o
Пример :
pi@raspberrypi:/tmp/d $ rm lib/*
pi@raspberrypi:/tmp/d $ make
gcc -ansi -pedantic -Wextra -c -o lib/tcp.o -I includes srclib/tcp.c
gcc -ansi -pedantic -Wextra -c -o lib/cliente.o -I includes src/cliente.c
gcc -ansi -pedantic -Wextra -c -o lib/servidor_preforked.o -I includes src/servidor_preforked.c
gcc -ansi -pedantic -Wextra -o lib/a.out -I includes lib/tcp.o lib/cliente.o lib/servidor_preforked.o
pi@raspberrypi:/tmp/d $ ls -l lib
total 24
-rwxr-xr-x 1 pi pi 8208 févr. 23 18:15 a.out
-rw-r--r-- 1 pi pi 956 févr. 23 18:15 cliente.o
-rw-r--r-- 1 pi pi 856 févr. 23 18:15 servidor_preforked.o
-rw-r--r-- 1 pi pi 840 févr. 23 18:15 tcp.o
@moliverac8 почему ты говоришь can't use -c and -o at the same time ?
Компиляторы говорят так: gcc -ansi -pedantic -g -Wall -c -o lib/tcp -I include srclib/tcp.c include/tcp.h gcc: фатальная ошибка: нельзя указать -o с -c, -S или - E с прекращением компиляции нескольких файлов. make: *** [makefile:11: lib/tcp] Ошибка 1
@moliverac8 это очень странно, какая у тебя версия gcc и на какой ОС?. Я отредактировал свой ответ, чтобы показать второй пример
Я использую Ubuntu 18.10 и gcc 8.2.0.
@moliverac8 хорошо, теперь я вижу, это потому, что вы ставите srclib/tcp.c includes/tcp.h, а не просто srclib/tcp.c, не даете заголовочный файл
Да, вы можете явно добавлять имена папок к целям и командам как @bruno, но это немного похоже на жесткое кодирование, а также добавляет немного дублирования. Способ улучшить это — использовать VPATH или функция vpath, которые подходят для этого случая:
vpath %.h includes
vpath %.c src:srclib
vpath %.o lib
Это говорит, в каком каталоге искать файлы определенного типа. Для файлов .c он будет искать как «src», так и «srclib».
Теперь правила могут выглядеть проще:
cliente.o : cliente.c tcp.h
$(GCC) -c -o lib/$@ -I includes $<
Обратите внимание на использование $@ и $<автоматические переменные. В этом случае $< будет расширяться до первого необходимого пути с каталогом — «lib/cliente.c», а $@ — это просто целевое имя — «cliente.o».
Если вы напишете правила таким образом, вы можете в конечном итоге сделать так, чтобы все ваши правила выглядели одинаково, и подумайте о дальнейшем рефакторинге всего лишь одного правила неявного шаблона %.o: %.c.
Спасибо, мне нужно сгенерировать tcp.o в lib, но я не могу использовать -c и -o одновременно, поэтому я не знаю, как установить объектный файл в нужную папку. Я пробовал это: lib/tcp: gcc -ansi -pedantic -g -c -o lib/tcp -I include srclib/tcp.c include/tcp.h