Проблема с Makefile в каталоге верхнего уровня, исходники в подкаталогах

StackOverflow https://stackoverflow.com/questions/1319175

  •  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.candclient/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, производить УНТ, или просто сделать.
Есть несколько более сложные вещи, которые вы можете сделать, но на данный момент этого должно быть достаточно.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top