Makefile с файлами в разных папках

Я новичок в 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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

нужно указать где найти заголовок вашему компилятору, для 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

Спасибо, мне нужно сгенерировать tcp.o в lib, но я не могу использовать -c и -o одновременно, поэтому я не знаю, как установить объектный файл в нужную папку. Я пробовал это: lib/tcp: gcc -ansi -pedantic -g -c -o lib/tcp -I include srclib/tcp.c include/tcp.h

moliverac8 23.02.2019 18:06

@moliverac8 почему ты говоришь can't use -c and -o at the same time ?

bruno 23.02.2019 18:07

Компиляторы говорят так: 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 23.02.2019 18:09

@moliverac8 это очень странно, какая у тебя версия gcc и на какой ОС?. Я отредактировал свой ответ, чтобы показать второй пример

bruno 23.02.2019 18:18

Я использую Ubuntu 18.10 и gcc 8.2.0.

moliverac8 23.02.2019 18:19

@moliverac8 хорошо, теперь я вижу, это потому, что вы ставите srclib/tcp.c includes/tcp.h, а не просто srclib/tcp.c, не даете заголовочный файл

bruno 23.02.2019 18:23

Да, вы можете явно добавлять имена папок к целям и командам как @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.

Другие вопросы по теме