Генерация зависимостей GCC для другого выходного каталога
-
01-07-2019 - |
Вопрос
Я использую 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
.
[GNU] make сердится, если вы не размещаете выходные данные в текущем каталоге.Вам действительно следует запустить make из каталога сборки и использовать переменную VPATH make для поиска исходного кода.Если вы лжете компилятору, рано или поздно он отомстит.
Если вы настаиваете на создании своих объектов и зависимостей в каком-либо другом каталоге, вам необходимо использовать
-o
аргумент, как ответил Эмиль.