Проблема с Makefile в каталоге верхнего уровня, исходники в подкаталогах - PullRequest
0 голосов
/ 23 августа 2009

У меня есть каталог с именем project.

Он содержит два подкаталога с именами client и server и make-файл с именем Makefile.

client и server получили исходные файлы с именами client.c и server.c соответственно.

У меня нет отдельных make-файлов в подкаталогах для источников, принадлежащих этому каталогу. Все сборки выполняются одним make-файлом. 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 / server.c and client / client.c` и вывести свои исполняемые файлы в соответствующие каталоги

Но поскольку у меня нет исполняемых файлов с именем svr, и `cnt проблема, с которой я столкнулся, не решена.

Если я изменю цель на ./client/client.out вместо cnt и затем позвоню make client/client.out, тогда все будет в порядке, именно то, что мне нужно, но я не хочу вводить длинную команду make client/client.out в моем терминале

Обходной путь, который я получил, выглядит следующим образом

cnt: $(CLI)
         cc $(FLAGS) $(CLI) -o cnt
         cp cnt ./client/client.out

Но не совсем доволен этим. Я уверен, что то, что я хочу сделать, действительно просто, и должен быть какой-то удобный способ сделать это. Так как я могу это сделать?

Ответы [ 2 ]

2 голосов
/ 23 августа 2009

Давайте сформулируем, что вы хотите. Вы хотите, чтобы цель с именем `cnt 'не была перестроена. Написанный вами make-файл ничего не знает о файле client.out, потому что он появляется только в командах оболочки внутри правила. Программа make не читает информацию из команд оболочки, она только выполняет подстановки и выполняет их.

Когда makefile выбирает цели, которые он будет перестраивать (cnt является одной из этих целей), он сравнивает время обновления целевого файла с временем обновления его предварительных требований. Поскольку во время запуска `` make cnt '' файл с именем cnt отсутствует , именованная цель так и считается требующей обновления. Таким образом, команды запускаются и не выдают файл с именем cnt , поэтому при следующем запуске make также будет учитывать его для обновления.

Есть два возможных решения. Первый - дать цели те же имена, что и у файла, который сгенерируют команды правила. Таким образом, вы можете в конечном итоге так:

client/client.out: $(CLI)
    cc $(FLAGS) $(CLI) -o ./client/client.out

Кстати, ваш вопрос не имеет ничего общего с каталогами. Вы также должны прочитать о директиве .PHONY, использовать $ (CC) вместо cc и прочитать gnu make manual , что может быть очень полезно.

0 голосов
/ 24 августа 2009

Попробуйте это:

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

...