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

Почему этот make файл выполняет цель на "make clean"

Это мой текущий make файл.

CXX      = g++
CXXFLAGS = -Wall -O3
LDFLAGS  =

TARGET = testcpp
SRCS   = main.cpp object.cpp foo.cpp
OBJS   = $(SRCS:.cpp=.o)
DEPS   = $(SRCS:.cpp=.d)


.PHONY: clean all

all: $(TARGET)

$(TARGET): $(OBJS)
    $(CXX) $(CXXFLAGS) $(LDFLAGS) $(OBJS) -o $(TARGET)

.cpp.o:
    $(CXX) $(CXXFLAGS) -c $< -o [email protected]

%.d: %.cpp
    $(CXX) -M $(CXXFLAGS) $< > [email protected]

clean:
    rm -f $(OBJS) $(DEPS) $(TARGET)

-include $(DEPS)

Он отлично работает с одним исключением. Если каталог уже чист (нет *.d, *.o), и я запускаю "make clean", он повторно создает зависимости, а затем сразу же удаляет их:

[[email protected] proj]$ make
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
g++ -Wall -O3 -c main.cpp -o main.o
g++ -Wall -O3 -c object.cpp -o object.o
g++ -Wall -O3 -c foo.cpp -o foo.o
g++ -Wall -O3  main.o object.o foo.o -o testcpp
[[email protected] proj]$ make clean
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[[email protected] proj]$ make clean
g++ -M -Wall -O3 foo.cpp > foo.d
g++ -M -Wall -O3 object.cpp > object.d
g++ -M -Wall -O3 main.cpp > main.d
rm -f main.o object.o foo.o main.d object.d foo.d testcpp
[[email protected] proj]$

Я не понимаю, почему вторая "make clean" будет повторно генерировать файлы зависимостей. Как я могу избежать этого? Это не очень важно для этого надуманного примера, но для большого проекта это может быть довольно трудоемким.

Спасибо.

4b9b3361

Ответ 1

Это потому, что файлы .d имеют -include d безоговорочно. Насколько известно make, они могут добавлять зависимости или команды к цели clean. По этой причине сначала создаются все файлы include d, иначе вы можете получить неправильную или неудачную сборку. Чтобы отключить это, вы хотите условно включить файлы зависимостей:

ifneq ($(MAKECMDGOALS),clean)
-include $(DEPS)
endif

Альтернативное решение - генерировать файлы зависимостей с помощью touch и заменять их фактическими данными как побочным эффектом компиляции. Это то, как automake отслеживает зависимость, поскольку он делает одноразовые сборки быстрее. Просмотрите параметры -MD и -MMD до gcc, если вы хотите пройти этот маршрут. Используйте правило шаблона, например:

%.d:
    @touch [email protected]

Первоначально создавать файлы зависимостей.

Ответ 2

Он хочет восстановить файлы зависимостей, потому что он всегда пытается восстановить все make файлы, в том числе -include'd make файлы, прежде чем делать что-либо еще. (Ну, на самом деле, для меня это не так - у меня есть GNU Make 3.81 - так что, возможно, это ошибка в вашей версии, которая была исправлена, или оптимизация, которая у меня есть и у вас нет, но в любом случае.)

Самый простой способ - написать свои правила, чтобы они генерировали файлы .d как побочный эффект обычной компиляции, а не давали явные правила для их создания. Таким образом, когда их там нет, Make не знает, как их сгенерировать, чтобы он не пытался (в чистом дереве достаточно правил .cpp.o, вам не нужны зависимости в заголовке), Посмотрите на созданный Automake makefile - простой - чтобы посмотреть, как это делается.

Ответ 3

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

MAKEFILE_TARGETS_WITHOUT_INCLUDE := clean distclean doc

# Include only if the goal needs it
ifeq ($(filter $(MAKECMDGOALS),$(MAKEFILE_TARGETS_WITHOUT_INCLUDE)),)
  -include $(DEPS)
endif

Ответ 4

Ведущий - в -include означает, что make не будет жаловаться на отсутствие зависимостей и не может быть переделан, но это не значит, что он не будет пытаться сделать их первыми (и, в этом случае преуспеют) - в конце концов, что-то интересное или важное может быть во включенных файлах, откуда их пытаются попробовать. Я не думаю, что есть способ остановить это.

Для документов в include и -include см. здесь.