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

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

Вопрос

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

gcc $(INCLUDES) -E -MM $(CFLAGS) $(SRC) >>$(DEP)
Это было полезно?

Решение

Ответ кроется в Руководство по GCC:используйте -MT Отметить.

-MT target

Измените цель правила, генерируемого при генерации зависимостей.По умолчанию CPP принимает имя основного входного файла, удаляет все компоненты каталога и любой суффикс файла, такой как .c, и добавляет обычный объектный суффикс платформы.Результат - это цель.

Ан -MT опция установит целевым объектом именно ту строку, которую вы укажете.Если вам нужно несколько целевых объектов, вы можете указать их в качестве одного аргумента для -MT, или использовать несколько -MT Опции.

Например, -MT '$(objpfx)foo.o' может дать

$(objpfx)foo.o: foo.c

Другие советы

Я предполагаю, что вы используете GNU Make и GCC.Сначала добавьте переменную для хранения вашего списка файлов зависимостей.Предполагая, что у вас уже есть файл, в котором перечислены все наши источники:

SRCS = \
        main.c \
        foo.c \
        stuff/bar.c

DEPS = $(SRCS:.c=.d)

Затем включите сгенерированные зависимости в makefile:

include $(DEPS)

Затем добавьте это шаблонное правило:

# automatically generate dependency rules

%.d : %.c
        $(CC) $(CCFLAGS) -MF"$@" -MG -MM -MP -MT"$@" -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 волноваться, если файл заголовка отсутствует.

Возможно, вам понравится эта более краткая версия Ответ Дона Маккахи:

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 $@

# -MD can be used to generate a dependency output file as a side-effect of the compilation process.

Детализация на Ответ DGentry, у меня это хорошо сработало:

.depend: $(SOURCES)
    $(CC) $(CFLAGS) -MM $(SOURCES) | sed 's|[a-zA-Z0-9_-]*\.o|$(OBJDIR)/&|' > ./.depend

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

Хорошо, просто чтобы убедиться, что я правильно понял вопрос:Я предполагаю, что у вас есть 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 содержит желаемый результат, как указано выше.

Если у GCC есть аргумент для этого, я не знаю, что это такое.В конечном итоге мы передаем выходные данные зависимости через сэд чтобы переписать все вхождения <blah>.o как ${OBJDIR}/<blah>.o.

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

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

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