如何为同一个库/可执行文件的多个变体编写makefile?

时间:2015-05-06 13:22:55

标签: makefile fortran target fortran90

我正在使用Intel的ifort和GNU make在linux机器上构建我的项目。 lib依赖于源目录中的源文件a.f90,b.f90和c.f90。

我正在通过

调用make
make FLAG

这些FLAGS在我的makefile中定义,并对应于编译器的不同优化标志。

  1. 我希望我的makefile为每个标志创建一个新的子目录,这样我就可以一次或另一次编译不同的目标,而不必先删除另一个。怎么办呢?

  2. 后来,在我的库被编译之后,我想将我的可执行文件链接到该库的特定变体,所以我必须告诉可执行文件的makefile,它应该采用哪种变体。我该如何以可维护的方式做到这一点?

  3. 到目前为止我的makefile示例:

    #
    # Include system specific include.mk file.
    # This sets the correct compiler and PREFIX path.
    #
    # sth like:
    # PREFIX=~/local
    # FC=ifort
    # LDR=$(FC)
    #
    include include.mk
    #
    #
    # Extra Flags for optimization, debug and style.
    #
    INSPECTOR   := -O0 -g -check none -fPIC
    O1          := -O1 -fPIC
    O2          := -O2 -fPIC
    OPT         := -O3 -fPIC -fast
    PEDANTIC    := -fPIC -warn all -warn errors
    DEBUG       := -g -fPIC -traceback -debug -check -fpe0
    
    #
    # Dircetories for .o, .mod and lib
    #
    DOC_DIR     := doc
    BUILD_DIR   := .build
    INSTALL_LIB := $(addprefix $(PREFIX),/lib)
    INSTALL_INC := $(addprefix $(PREFIX),/mod)
    #
    # SOURCE
    #
    SRC_DIR     := src
    vpath %.f90 $(SRC_DIR)
    
    BASIC_OBJ  := a.o b.o c.o
    
    OBJECTS     := $(addprefix $(BUILD_DIR)/,$(BASIC_OBJ) )
    
    MOD_LIST := a_mod.mod b_mod.mod c_mod.mod
    
    MODLIST := $(addprefix $(INSTALL_INC)/,$(MOD_LIST) )
    
    
    # 
    # RULES
    #
    .PHONY: clean inspector o1 o2 opt pedantic debug
    
    all: $(BUILD_DIR)/libmyexample.so
    
    #
    inspector:
        @EXTRA="$(INSPECTOR)" make
    
    #
    o1:
        @EXTRA="$(O1)" make
    
    #
    o2:
        @EXTRA="$(O2)" make
    #
    opt:
        @EXTRA="$(OPT)" make
    
    #
    pedantic:
        @EXTRA="$(OPT) $(PEDANTIC)" make
    #
    debug:
        @EXTRA="$(DEBUG)" make
    #
    install: $(INSTALL_LIB) $(INSTALL_INC) $(INSTALL_LIB)/libmyexample.so
    
    #
    uninstall:
        rm $(INSTALL_LIB)/libmyexample.so
        rm $(MODLIST)
    #
    reinstall: uninstall install
    #
    doc: $(BUILD_DIR)
        doxygen $(SRC_DIR)/myexample.dxy
        mv warnlog.dxy $(BUILD_DIR)/
    #
    $(INSTALL_LIB)/libmyexample.so:
        cp $(BUILD_DIR)/libmyexample.so $(INSTALL_LIB)/
    
    #
    $(BUILD_DIR)/libmyexample.so: $(OBJECTS)
        $(LDR) -shared -o $@ $(OBJECTS) $(INCDIRS) $(LDFLAGS) 
    #
    clean:
        rm -f $(BUILD_DIR)/*.o $(BUILD_DIR)/*.mod 
        rm -rf $(BUILD_DIR)
        rm -rf $(DOC_DIR)/html $(DOC_DIR)/latex
    #
    $(BUILD_DIR)/%.o : %.f90
        $(FC) -o $@ -c $(EXTRA) $(INCDIRS) $(MODDIR) $<
    #
    $(OBJECTS): | $(BUILD_DIR) $(INSTALL_LIB) $(INSTALL_INC)
    #
    $(BUILD_DIR):
        mkdir -p $(BUILD_DIR)
    #
    $(INSTALL_LIB):
        mkdir -p $(INSTALL_LIB)
    #
    $(INSTALL_INC):
        mkdir -p $(INSTALL_INC)
    #
    

1 个答案:

答案 0 :(得分:1)

关于makefile的一些清理笔记。

如果您使用O1/etc. instead of o1 /etc. for the target names (or o1` / etc。对于变量名称),那么你可以将这些目标清理为:

PEDANTIC: EXTRA = $(PEDANTIC)

O1 O2 OPT DEBUG PEDANTIC INSPECTOR:
        @$(MAKE) EXTRA="$(EXTRA) $($@)"

这也允许您手动传递原始EXTRA调用的其他make标记(例如EXTRA=-newoption make O1)。

此外,底部的所有mkdir目标都可以合并为一个目标:

$(BUILD_DIR) $(INSTALL_LIB) $(INSTALL_INC):
        mkdir -p $@

关于问题的主旨,如果你根据标志级别(或其他)设置BUILD_DIR,那么你得到了你想要的东西,并且可以在以后的应用程序链接中使用正确的目录。< / p>

这样的事情(不是我实际上会这样做但是会为一个简单的例子工作):

O1 O2 OPT DEBUG PEDANTIC INSPECTOR:
        @$(MAKE) EXTRA="$(EXTRA) $($@)" BUILD_DIR=.$@

.O1 .O2 .OPT .DEBUG .PEDANTIC .INSPECTOR:
        mkdir $@

这将使用目标值覆盖BUILD_DIR的文件内定义并构建到它们中。

应用程序目标只需在链接时将-L$@(或其他)添加到相应的标记中。