Проблема с Makefile в каталоге верхнего уровня, исходники в подкаталогах
-
19-09-2019 - |
Вопрос
У меня есть каталог под названием project
.
Он содержит два подкаталога, называемых client
и server
, и makefile , вызываемый Makefile
.
client
и server
у вас есть исходные файлы под названием client.c
и server.c
, соответственно.
У меня нет никаких отдельных make-файлов в подкаталогах для источников, принадлежащих этому каталогу.Все сборки выполняются с помощью одного makefile.Тот самый Makefile
код - это
FLAGS = -W -Wall -g -pthread
SERV =./server/server.c #My server code
CLI =./client/client.c #My client code
build:svr cnt
svr: $(SERV)
cc $(FLAGS) $(SERV) -o ./server/server.out
cnt: $(CLI)
cc $(FLAGS) $(CLI) -o ./client/client.out
Теперь я побежал make cnt
и оно ответило
cc -W -Wall -g -pthread ./client/client.c -o ./client/client.out
Проблема заключается во всех последующих make cnt
команды в конечном итоге компилируют его снова и выводят приведенный выше текст, хотя я ничего не меняю ./client/client.c
Я застрял здесь.Не знаю, что мне делать.
То, что я хочу сделать, это:
- С
make cnt
, скомпилироватьclient/client.c
и выведите его исполняемый файл вclient/
каталог - С
make svr
, скомпилироватьserver/server.c
и выведите его исполняемый файл вserver/
справочник. - И с
make, compile both
сервер/server.cand
client/client.c` и выводят свои исполняемые файлы в соответствующие каталоги
Но поскольку у меня нет вызываемых исполняемых файлов svr
и потому проблема, с которой я столкнулся, не решена.
Если я изменю цель на ./client/client.out
вместо того , чтобы cnt
а потом позвони make client/client.out
тогда это было бы прекрасно, именно то, что мне нужно, но я не хочу вводить длинную команду make client/client.out
в моем терминале
Обходной путь, который у меня есть, заключается в следующем
cnt: $(CLI)
cc $(FLAGS) $(CLI) -o cnt
cp cnt ./client/client.out
Но не совсем доволен этим.Я уверен, что то, что я хочу сделать, действительно просто, и должен быть какой-то удобный способ сделать это.Так как же я могу это сделать?
Решение
Давайте сформулируем, чего вы хотите.Вы хотите, чтобы цель с именем "cnt" не перестраивалась.makefile, который вы написали, ничего не знает о файле client.out, потому что он появляется только в командах командной строки в рамках правила.Программа Make не считывает информацию из команд оболочки, она только делает там замены и выполняет их.
Когда makefile выбирает целевые объекты, которые он будет перестраивать (`cnt' является одной из этих целевых объектов), он сравнивает время обновления целевого объекта файл со временем обновления своих предварительных запросов.Поскольку в то время, когда вы запускаете `make cnt" файл с именем cnt отсутствует, целевой объект, названный таким образом, считается требующим обновления.Таким образом, команды выполняются и не дают результата. файл с именем cnt, поэтому следующий make run также рассмотрит его для обновления.
Есть два возможных решения.Первый - присвоить целевым объектам те же имена, что и файлу, который будут генерировать команды правил.Итак, вы можете закончить вот так:
client/client.out: $(CLI)
cc $(FLAGS) $(CLI) -o ./client/client.out
Кстати, ваш вопрос не имеет никакого отношения к каталогам.Вам также следует прочитать об этом .ФАЛЬШИВАЯ директива, используйте $(CC) вместо cc и прочитайте руководство по созданию gnu, что может быть очень полезно.
Другие советы
Попробуй это:
SERVO =./server/server.out CLIO =./client/client.out .PHONY: srv cnt build build: svr cnt svr: $(SERVO) cnt: $(CLIO) $(SERVO) $(CLIO): %.out : %.c cc $(FLAGS) $^ -o $@
Теперь вы можете сделать srv, производить УНТ, или просто сделать.
Есть несколько более сложные вещи, которые вы можете сделать, но на данный момент этого должно быть достаточно.