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

Използвах qmake и CMake в миналото без проблем, за да генерирам моите make-файлове. Наскоро обаче разбрах, че на някои от клъстерите, които изпълнявам с кодовете си, тези инструменти са по-трудни за намиране/инсталиране, така че реших да пиша голи Makefiles. Освен това мога да науча нещо или две за 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. Това трябва ли да се случи в този makefile? Как мога да направя all правилото по подразбиране? 2) Как мога да направя файловете за зависимости невидими? Опитах DEPS := $(patsubst %,$(OBJS_DIR)/.%,$(SRCS:.cpp=.d)), но това не помогна 3) Има ли някакво конкретно предложение, което можете да ми дадете, ако смятате, че този Makefile може да бъде подобрен по друг начин?

РЕДАКТИРАНЕ: Честно казано, дори не съм сигурен как 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