Скажем, у меня есть make-файл с правилом
%.o: %.c
gcc -Wall -Iinclude ...
Я хочу, чтобы * .o перестраивался при изменении файла заголовка. Вместо того, чтобы составлять список зависимостей, всякий раз, когда /include
изменяется какой-либо файл заголовка , все объекты в каталоге должны быть перестроены.
Я не могу придумать хороший способ изменить правило, чтобы учесть это, я открыт для предложений. Бонусные баллы, если список заголовков не нужно жестко задавать
Ответы:
Если вы используете компилятор GNU, он может составить для вас список зависимостей. Фрагмент Makefile:
или
где
SRCS
- переменная, указывающая на весь ваш список исходных файлов.Есть еще инструмент
makedepend
, но он мне никогда не нравился так сильно, какgcc -MM
источник
depend
запустить его только тогда, когда исходные файлы изменились? Кажется, он запускается каждый раз, несмотря ни на что ...build/file.o
?Большинство ответов на удивление сложны или ошибочны. Однако простые и надежные примеры были опубликованы в другом месте [ codereview ]. По общему признанию, параметры, предоставляемые препроцессором GNU, немного сбивают с толку. Однако удаление всех каталогов из целевой сборки с помощью
-MM
задокументировано и не является ошибкой [ gpp ]:-MMD
Возможно, вам нужен вариант (несколько более новый) . Для полноты картины приведен пример файла makefile, который поддерживает несколько директорий src и директории сборки с некоторыми комментариями. Простую версию без директорий сборки см. В [ codereview ].Этот метод работает, потому что, если существует несколько строк зависимостей для одной цели, зависимости просто объединяются, например:
эквивалентно:
как упоминалось в: Makefile нескольких строк зависимостей для одной цели?
источник
CPP
должно читатьсяCPPS
a.cpp
,b.cpp
)./src/
, не сделает$(OBJ)=./build/src/a.o ./build/src/b.o
ли эта замена ?Как я писал здесь, gcc может одновременно создавать зависимости и компилировать:
Параметр -MF указывает файл, в котором будут храниться зависимости.
Тире в начале '-include' говорит Make продолжить, когда файл .d не существует (например, при первой компиляции).
Обратите внимание, что в gcc есть ошибка в отношении параметра -o. Если вы установите имя файла объекта как obj / _file__c.o, тогда сгенерированный файл .d по-прежнему будет содержать файл .o, а не obj / _file__c.o.
источник
man gcc
говорит-MM
подразумевает-E
, что "останавливается после предварительной обработки".-MMD
Вместо этого вам нужно : stackoverflow.com/a/30142139/895245Как насчет чего-то вроде:
Вы также можете использовать подстановочные знаки напрямую, но я часто обнаруживаю, что они мне нужны более чем в одном месте.
Обратите внимание, что это хорошо работает только в небольших проектах, поскольку предполагает, что каждый объектный файл зависит от каждого файла заголовка.
источник
make clean all
.gcc
Линия не выполняется вообще, но встроенный в правиле (%o: %.c
правило) выполняется вместо.Приведенное выше решение Martin отлично работает, но не обрабатывает файлы .o, которые находятся в подкаталогах. Годрик указывает, что флаг -MT решает эту проблему, но одновременно предотвращает правильную запись файла .o. Обе эти проблемы решаются следующим образом:
источник
Это отлично справится со своей задачей и даже обработает указанные подкаталоги:
протестировал его с помощью gcc 4.8.3
источник
Вот двухстрочный вариант:
Это работает с рецептом make по умолчанию, если у вас есть список всех ваших объектных файлов в
OBJS
.источник
Я предпочитаю это решение, а не принятый ответ Майкла Уильямсона, он улавливает изменения в источниках + встроенных файлах, затем в источниках + заголовках и, наконец, только в источниках. Преимущество здесь в том, что вся библиотека не перекомпилируется, если внесены только несколько изменений. Не слишком большое значение для проекта с парой файлов, но если у вас есть 10 или 100 источников, вы заметите разницу.
источник
Для меня работает следующее:
источник
Слегка измененная версия ответа Софи, которая позволяет выводить файлы * .d в другую папку (я вставлю только ту интересную часть, которая генерирует файлы зависимостей):
Обратите внимание, что параметр
используется для обеспечения того, чтобы цели (т. е. имена объектных файлов) в сгенерированных файлах * .d содержали полный путь к файлам * .o, а не только имя файла.
Я не знаю, почему этот параметр НЕ нужен при использовании -MMD в сочетании с -c (как в версии Софи ). В этой комбинации кажется, что полный путь к файлам * .o записывается в файлы * .d. Без этой комбинации -MMD также записывает только чистые имена файлов без каких-либо компонентов каталога в файлы * .d. Может быть, кто-нибудь знает, почему -MMD записывает полный путь в сочетании с -c. Я не нашел никаких подсказок на странице руководства g ++.
источник