Генерация зависимостей GCC для другого выходного каталога
Я использую GCC для создания файла зависимостей, но мои правила сборки помещают вывод в подкаталог. Есть ли способ сказать GCC поместить мой префикс подкаталога в файл зависимостей, который он генерирует для меня?
gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
Ответы
Ответ 1
Ответ находится в руководстве GCC: используйте флаг -MT
.
-MT target
Измените цель правила, испускаемого генерацией зависимостей. По умолчанию CPP берет имя основного входного файла, удаляет любые компоненты каталога и любой суффикс файла, например .c
, и добавляет суффикс обычного объекта платформы. Результатом является цель.
Параметр -MT
задает цель как точно указанную вами строку. Если вам нужно несколько целей, вы можете указать их как один аргумент для -MT
или использовать несколько параметров -MT
.
Например, -MT '$(objpfx)foo.o'
может дать
$(objpfx)foo.o: foo.c
Ответ 2
Я предполагаю, что вы используете GNU Make и GCC. Сначала добавьте переменную для хранения списка файлов зависимостей. Предполагая, что у вас уже есть список, в котором перечислены все наши источники:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
Затем включите сгенерированные зависимости в make файле:
include $(DEPS)
Затем добавьте это правило шаблона:
# automatically generate dependency rules
%.d : %.c
$(CC) $(CCFLAGS) -MF"[email protected]" -MG -MM -MP -MT"[email protected]" -MT"$(<:.c=.o)" "$<"
# -MF write the generated dependency rule to a file
# -MG assume missing headers will be generated and don't stop with an error
# -MM generate dependency rule for prerequisite, skipping system headers
# -MP add phony target for each header to prevent errors when header is missing
# -MT add a target to the generated dependency
"$ @" - это цель (вещь в левой части:), "$ <" является предпосылкой (вещь на правой стороне:). Выражение "$ (<:. C =.o)" заменяет расширение .c на .o.
Трюк здесь состоит в том, чтобы сгенерировать правило с двумя целями, добавив -MT дважды; это делает файл .o и файл .d зависимыми от исходного файла и его заголовков; таким образом, файл зависимостей автоматически восстанавливается при каждом изменении любого из файлов .c или .h.
Параметры -MG и -MP сохраняют make от freaking, если отсутствует файл заголовка.
Ответ 3
Вам может понравиться эта более короткая версия ответа Дона МакКоги:
SRCS = \
main.c \
foo.c \
stuff/bar.c
DEPS = $(SRCS:.c=.d)
Добавьте -include $(DEPS)
обратите внимание на префикс -
, который заглушает ошибки, если файлы .d
еще не существуют.
Нет необходимости в отдельном шаблонном правиле для генерации файлов зависимостей. Просто добавьте -MD
или -MMD
в вашу обычную строку компиляции, и файлы .d
будут сгенерированы одновременно с вашими исходными файлами. Например:
%.o: %.c
gcc $(INCLUDE) -MMD -c $< -o [email protected]
# -MD can be used to generate a dependency output file as a side-effect of the compilation process.
Ответ 4
Детализируя ответ DGentry, это хорошо сработало для меня:
.depend: $(SOURCES)
$(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend
Это также работает в случае, когда существует только один файл зависимости, который содержит правила зависимости для всех исходных файлов.
Ответ 5
Хорошо, просто чтобы убедиться, что я правильно понял вопрос: я предполагаю, что у вас есть test.c
который включает test.h
, и вы хотите сгенерировать subdir/test.d
(не генерируя subdir/test.o
), где subdir/test.d
содержит
subdir/test.o: test.c test.h
скорее, чем
test.o: test.c test.h
это то, что вы получаете прямо сейчас. Это правильно?
Я не смог придумать простой способ сделать именно то, что вы просите. Однако, глядя на Улучшения генерации зависимостей, если вы хотите создать файл .d
при создании файла .o, вы можете использовать:
gcc $(INCLUDES) -MMD $(CFLAGS) $(SRC) -o $(SUBDIR)/$(OBJ)
(Учитывая SRC=test.c
, SUBDIR=subdir
и OBJ=test.o
) Это создаст и subdir/test.o, и subdir/test.d, где subdir/test.d
содержит желаемый вывод, как указано выше.
Ответ 6
Если у GCC есть аргумент, чтобы сделать это, я не знаю, что это такое. В итоге мы ${OBJDIR}/<blah>.o
вывод зависимостей через sed, чтобы переписать все вхождения <blah>.o
как ${OBJDIR}/<blah>.o
.
Ответ 7
-
[GNU] make сердится, если вы не поместите вывод в текущий каталог. Вы действительно должны запустить make из каталога сборки и использовать переменную make VPATH, чтобы найти исходный код. Если вы врете компилятору, рано или поздно он отомстит.
-
Если вы настаиваете на создании ваших объектов и зависимостей в каком-либо другом каталоге, вам нужно использовать аргумент -o
, как ответил Эмиль.