генерация зависимостей gcc для другого выходного каталога - PullRequest
21 голосов
/ 19 сентября 2008

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

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

Ответы [ 7 ]

39 голосов
/ 12 января 2010

Я предполагаю, что вы используете 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"$@" -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. </p>

Хитрость в том, чтобы сгенерировать правило с двумя целями, дважды добавив -MT; это делает как файл .o, так и файл .d зависимым от исходного файла и его заголовков; таким образом, файл зависимостей автоматически восстанавливается при изменении любого из соответствующих файлов .c или .h.

Опции -MG и -MP не дают сойти с ума, если отсутствует заголовочный файл.

18 голосов
/ 19 сентября 2008

Ответ содержится в руководстве по GCC : используйте флаг -MT.

-MT target

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

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

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

$(objpfx)foo.o: foo.c
10 голосов
/ 06 июня 2013

Вам может понравиться эта более короткая версия ответа Дона МакКоги:

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.
3 голосов
/ 10 июня 2014

Детализация ответа DGentry для меня сработала:

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

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

1 голос
/ 19 сентября 2008

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

это то, что вы получаете прямо сейчас. Это верно?

Я не смог придумать простой способ сделать именно то, что вы просите. Однако, глядя на http://www.gnu.org/software/gcc/news/dependencies.html,, если вы хотите создать файл .d при создании файла .o, вы можете использовать

gcc $ (ВКЛЮЧАЕТ) -MMD $ (CFLAGS) $ (SRC) -o $ (SUBDIR) / $ (OBJ)

(учитывая SRC = test.c, SUBDIR = subdir и OBJ = test.o) Это создаст и subdir / test.o, и subdir / test.d, где subdir / test.d содержит желаемый вывод, как указано выше. , Надеюсь, это поможет.

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

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

0 голосов
/ 19 сентября 2008

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

...