Подтвердить что ты не робот

Генерация зависимостей GCC для другого выходного каталога

Я использую GCC для создания файла зависимостей, но мои правила сборки помещают вывод в подкаталог. Есть ли способ сказать GCC поместить мой префикс подкаталога в файл зависимостей, который он генерирует для меня?

gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
4b9b3361

Ответ 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

  1. [GNU] make сердится, если вы не поместите вывод в текущий каталог. Вы действительно должны запустить make из каталога сборки и использовать переменную make VPATH, чтобы найти исходный код. Если вы врете компилятору, рано или поздно он отомстит.

  2. Если вы настаиваете на создании ваших объектов и зависимостей в каком-либо другом каталоге, вам нужно использовать аргумент -o, как ответил Эмиль.