Автоматическое разрешение зависимостей GNU Makefile

В прошлом я без проблем использовал qmake и CMake для создания make-файлов. Однако недавно я понял, что на некоторых кластерах, в которых я запускаю свои коды, эти инструменты сложнее найти/установить, поэтому я решил написать голые файлы Makefile. Кроме того, я мог бы также узнать кое-что о Makefiles;)

Мой проект включает в себя несколько каталогов с исходными файлами/заголовочными файлами внутри и чаще всего перекрестными зависимостями между ними. С помощью SO я научился использовать флаг -MM для автоматического создания информации о зависимости. Мои Makefiles выглядят так

include $(HEAD_DIR)/common.mk

OBJS_DIR = objs
LIBS_DIR = libs

SRCS  = Matrix.cpp MatrixFull.cpp
OBJS  = $(patsubst %,$(OBJS_DIR)/%,$(SRCS:.cpp=.o))
LIB_0 = $(patsubst %, $(LIBS_DIR)/%,libalgebra.a)

DEPS := $(patsubst %,$(OBJS_DIR)/%,$(SRCS:.cpp=.d))
-include $(DEPS)

.PHONY: all
all:    
    @echo   " ===== Building dependencies in lib/algebra ===== "
    @$(MKDIR) $(OBJS_DIR)
    @$(MAKE)  $(OBJS)
    @$(MKDIR) $(LIBS_DIR)
    @$(MAKE)  $(LIB_0)
    @echo   " ===================== done ===================== "

$(OBJS_DIR)/%.o: %.cpp
    @echo " compiling source file:   $< ..."
    $(CXX) -c $(CXXFLAGS) -I$(INCLUDE_PATH) -MM $< -o $@

$(LIB_0): $($(OBJS_DIR)/%.o)
    @echo " generating library file: $(@F) ..."
    @$(AR) $(AR_FLAGS) $@ $^

.PHONY: clean
clean:
    @$(RM) $(OBJS_DIR) $(LIBS_DIR)

Обычно это работает нормально, но я хотел бы улучшить несколько моментов: 1) Когда я изменяю заголовочный файл и выдаю make, почему-то компилятор не выбирает all и, по-видимому, по умолчанию использует DEPS. Это должно происходить в этом make-файле? Как сделать all правилом по умолчанию? 2) Как сделать файлы зависимостей невидимыми? Я попробовал DEPS := $(patsubst %,$(OBJS_DIR)/.%,$(SRCS:.cpp=.d)), но это не помогло 3) Можете ли вы дать мне какое-нибудь конкретное предложение, если вы считаете, что этот Makefile можно улучшить каким-либо другим способом?

EDIT: Честно говоря, я даже не уверен, как make вызывает компилятор для создания зависимостей: p ... Я не вижу для этого явного правила. Это как-то скрыто в DEPS := $(patsubst %,$(OBJS_DIR)/%,$(SRCS:.cpp=.d)) ?


person mmirzadeh    schedule 05.09.2012    source источник


Ответы (1)


1) Переместите -include $(DEPS) ниже правила all. Первое правило является правилом по умолчанию (если только вы специально не задали какую-то специальную переменную), поэтому, если include извлекает правило выше all:, это будет правило по умолчанию.

2) Я предполагаю, что под «сделать их невидимыми» вы подразумеваете, что хотите .foo.d вместо foo.d. Вы должны изменить правило, которое делает их:

$(OBJS_DIR)/%.o: %.cpp
    @echo " compiling source file:   $< ..."
    $(CXX) -c $(CXXFLAGS) -I$(INCLUDE_PATH) -MM $< -o $@
    @mv $(OBJS_DIR)/$*.d $(OBJS_DIR)/.$*.d

а затем переменная, которая их находит:

DEPS := $(patsubst %.cpp,$(OBJS_DIR)/.%.d,$(SRCS))

3) Я бы избавился от рекурсивных вызовов ($(MAKE) ...), но сначала вы должны убедиться, что все остальное работает правильно. И я удивлен, что правило $(OBJS_DIR)/%.o не входит в common.mk. Кроме этого, это выглядит довольно хорошо.

4(?)) Команда компилятора в правиле $(OBJS_DIR)/%.o использует флаг -MM, поэтому компилятор генерирует файлы зависимостей как побочный эффект.

person Beta    schedule 05.09.2012