Makefile останавливает сборку файлов после First .o При сборке вне исходного кода

#c #makefile

#c #makefile

Вопрос:

У меня есть немного огромный Makefile, который в основном работает так, как я хочу.

Проблема: Проблема, с которой я сталкиваюсь, заключается в том, что makefile проверяет только, нуждается ли в обновлении первый .o , а не какие-либо другие. Я не уверен, в какой части моего makefile ошибка.

Контекст: у меня есть структура проекта, подобная этой:

 quendor
  src
    main.c
    options.c
    quendor.h
Makefile
  

Когда мой Makefile собирается, он создает build каталог, и все выглядит следующим образом:

 quendor
  build
    src
      main.d
      main.o
      options.d
      options.o
  src
    main.c
    options.c
    quendor.h
Makefile
  

Чтобы увидеть проблему: Теперь предположим, что я не меняю свой main.c , но я меняю свой options.c файл. В этом случае, когда я снова запускаю make, я получаю это:

 make: 'build/./src/main.o' is up to date.
  

Я не уверен, связано ли это с тем, что он создается в build/src каталог, а не просто build так, как я предполагал.

Вот полный Makefile, и я включаю его весь только потому, что я не уверен, в чем может быть проблема, и я не хочу делать необоснованных предположений.

 .PHONY : all clean

NAME := quendor
PLATFORM := windows

CC := gcc
LINK := gcc

BUILD_DIR ?= ./build
SRC_DIR ?= ./src

ifeq ($(PLATFORM), windows)
    TARGET ?= quendor.exe
else
    TARGET ?= quendor
endif

ifeq ($(CC), gcc)
    CFLAGS  = -std=c11 -Wall -Wextra -Wpedantic -Wconversion -Wmissing-prototypes -Wshadow -MMD -MP
    LDFLAGS  =
    OPT  =
endif

SRCS := $(wildcard $(SRC_DIR)/*.c)
OBJS := $(SRCS:%.c=$(BUILD_DIR)/%.o)
DEPS := $(OBJS:%.o=%.d)

MKDIR_P ?= @mkdir -p $(dir $@)

-include $(DEPS)

all : $(TARGET)
    @echo "Building $(TARGET)"

$(TARGET) : $(OBJS)
    $(LINK) $(OPT) -o $@ $^ $(LDFLAGS)

$(BUILD_DIR)/%.o : %.c
    $(MKDIR_P)
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    $(RM) $(TARGET) -r $(BUILD_DIR)
  

Это может быть результатом того, как StackOverflow анализирует мой Makfile, но я замечаю, что после этой строки он показывает другую подсветку синтаксиса:

 SRCS := $(wildcard $(SRC_DIR)/*.c)
  

Комментарии:

1. Вы уже пытались удалить начало ./ в своих определениях BUILD_DIR и SRC_DIR ?

2. Я этого не делал, но я только что попробовал это, и я получаю точно такую же проблему. Чтобы было понятно, что я пробовал, я использовал BUILD_DIR ?= build и SRC_DIR ?= src . Но при этом все равно отображается то же поведение.

3. Можете ли вы попробовать переместить -include $(DEPS) в конец вашего makefile (или, по крайней мере, в точку после all целевого правила). В качестве альтернативы попробуйте вызвать make as make all явно.

4. Извините, я слишком быстро прочитал ваш вопрос. Итак, make сообщает вам, что main.o обновлено. Угадайте, что? make — это правильно. Поскольку вы не вносили изменений main.c , нет необходимости перекомпилировать его. Однако вы должны увидеть, что option.c выполняется перекомпиляция и quendor.exe повторная компоновка. Это то, что вы видите?

5. @RenaudPacalet Правильно, я не вижу options.c перекомпиляции, даже когда она изменена. Он просто останавливается на main.c , потому что видит, что он обновлен. Я был уверен, что это связано с тем, что одно из моих правил не допускало чего-либо рекурсивного.

Ответ №1:

Проблема в том, что вы включаете зависимости перед определением all правила:

 -include $(DEPS)

all : $(TARGET)
  

Если вы не указываете конкретную цель для сборки в командной строке (например, если вы не запускаете make all ), то make выбирает первую явную цель в makefile (и все включенные makefile-ы!!) в качестве цели для сборки.

Я предполагаю, что определения зависимостей в $(DEPS) переменной определяют main.o как цель, и поскольку это происходит раньше all , это единственное, что выполняется по умолчанию.

Переместите -include инструкцию позже в makefile (обычно я помещаю их все в конец makefile), и это сработает.

Комментарии:

1. АХ! Это было все! Я не могу поверить, что я этого не понял. Я читал так много источников по Makefiles и просто не понимал, что расположение здесь имеет значение. Это полностью решило проблему, и я благодарю вас.