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

如何为同一库/可执行文件的多个变体编写makefile?,makefile,fortran,target,fortran90,Makefile,Fortran,Target,Fortran90,我正在使用Intel的iPort和GNU make在linux机器上构建我的项目。 库依赖于源目录中的源文件a.f90、b.f90和c.f90 我正在调用make via make FLAG 其中,这些标志在我的makefile中定义,并对应于编译器的不同优化标志 我希望我的makefile为每个标志创建一个新的子目录,这样我就可以一次或一次又一次地编译不同的目标,而不必先删除另一个目标。如何做到这一点 稍后,在我的库被编译之后,我想将我的可执行文件链接到该库的一个特定变量,因此我必须告诉可执

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

我正在调用make via

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

  • 我希望我的makefile为每个标志创建一个新的子目录,这样我就可以一次或一次又一次地编译不同的目标,而不必先删除另一个目标。如何做到这一点

  • 稍后,在我的库被编译之后,我想将我的可执行文件链接到该库的一个特定变量,因此我必须告诉可执行文件的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)
    #
    
    #
    #包含系统特定的Include.mk文件。
    #这将设置正确的编译器和前缀路径。
    #
    #例如:
    #前缀=~/local
    #FC=ifort
    #LDR=$(FC)
    #
    include.mk
    #
    #
    #用于优化、调试和样式的额外标志。
    #
    检查员:=-O0-g-检查无-fPIC
    O1:=-O1-fPIC
    O2:=-O2-fPIC
    选项:=-O3-fPIC-快速
    学究式:=-fPIC-警告所有-警告错误
    调试:=-g-fPIC-回溯-调试-检查-fpe0
    #
    #.o、.mod和lib的目录
    #
    DOC_DIR:=DOC
    BUILD_DIR:=.BUILD
    INSTALL_LIB:=$(addprefix$(PREFIX),/LIB)
    INSTALL_INC:=$(addprefix$(PREFIX),/mod)
    #
    #来源
    #
    SRC_DIR:=SRC
    vpath%.f90$(SRC\u目录)
    基本对象:=a.o b.o c.o
    对象:=$(addprefix$(BUILD\u DIR)/,$(BASIC\u OBJ))
    MOD_LIST:=a_MOD.MOD b_MOD.MOD c_MOD.MOD
    MODLIST:=$(addprefix$(INSTALL\u INC)/,$(MOD\u LIST))
    # 
    #规则
    #
    .虚假:清洁检查员o1 o2选择迂腐调试
    全部:$(BUILD_DIR)/libmyexample.so
    #
    检查员:
    @额外=“$(检查员)”制造
    #
    o1:
    @额外=“$(O1)”制造
    #
    氧气:
    @额外=“$(O2)”制造
    #
    选择:
    @额外=“$(选择)”制造
    #
    迂腐的:
    @额外=“$(选择)$(迂腐)”制造
    #
    调试:
    @额外=“$(调试)”生成
    #
    install:$(install_LIB)$(install_INC)$(install_LIB)/libmyexample.so
    #
    卸载:
    rm$(安装库)/libmyexample.so
    rm$(MODLIST)
    #
    重新安装:卸载安装
    #
    文档:$(构建目录)
    doxygen$(SRC_DIR)/myexample.dxy
    mv warnlog.dxy$(构建目录)/
    #
    $(INSTALL_LIB)/libmyexample.so:
    cp$(BUILD\u DIR)/libmyexample.so$(INSTALL\u LIB)/
    #
    $(BUILD_DIR)/libmyexample.so:$(对象)
    $(LDR)-共享-o$@$(对象)$(INCDIRS)$(LDFLAGS)
    #
    清洁:
    rm-f$(构建目录)/*.o$(构建目录)/*.mod
    rm-rf$(构建目录)
    rm-rf$(文档目录)/html$(文档目录)/latex
    #
    $(构建目录)/%.o:%.f90
    $(FC)-o$@-c$(额外)$(增量)$(MODDIR)$<
    #
    $(对象):|$(构建目录)$(安装库)$(安装公司)
    #
    $(构建目录):
    mkdir-p$(构建目录)
    #
    $(安装库):
    mkdir-p$(安装库)
    #
    $(安装公司):
    mkdir-p$(安装公司)
    #
    
    关于makefile的一些清理说明

    如果对目标名称使用
    O1/etc.而不是
    O1
    /etc.(或对变量名称使用
    O1`/etc.),则可以将这些目标清理为:

    PEDANTIC: EXTRA = $(PEDANTIC)
    
    O1 O2 OPT DEBUG PEDANTIC INSPECTOR:
            @$(MAKE) EXTRA="$(EXTRA) $($@)"
    
    这还允许您在原始
    make
    调用上手动传递额外的
    EXTRA
    标志(例如
    EXTRA=-newoption make O1

    此外,底部的所有
    mkdir
    目标可以组合成一个目标:

    $(BUILD_DIR) $(INSTALL_LIB) $(INSTALL_INC):
            mkdir -p $@
    
    至于你问题的主旨,如果你根据标志级别(或其他)设置
    BUILD\u DIR
    ,那么你就可以得到你想要的,并且在以后的应用程序链接过程中也可以使用正确的目录

    类似这样的东西(不是我实际会怎么做,但对于一个简单的例子来说是可行的):

    这将用目标值覆盖
    BUILD\u DIR
    的文件内定义,并将其内置


    应用程序目标只需在链接时将
    -L$@
    (或任何内容)添加到相应的标志。

    感谢您的想法!所以,
    @$(MAKE)
    本质上是我在单个目标中进行的递归调用的替代品?我发现这真的很有用,因为我尝试了类似的方法,解析了更多的变量,但没有成功,它退出时出现了一个
    @STH=“…”notfound
    错误。这是因为这真的是一个命令行调用,而你的建议做了一些更有趣的事情吗?你没有写我实际上会怎么做,你能详细说明一下吗?我对学习很感兴趣!使用
    $(MAKE)
    触发MAKE的特殊处理。手册中谈到了这一点,我不会像在命令行中那样重写
    BUILD\u DIR
    ,我可能会在makefile本身中使用条件来自动控制define。我还可能使用
    OPTLEVEL
    (或其他)变量来选择要使用的标志,而不是触发递归make调用。
    O1 O2 OPT DEBUG PEDANTIC INSPECTOR:
            @$(MAKE) EXTRA="$(EXTRA) $($@)" BUILD_DIR=.$@
    
    .O1 .O2 .OPT .DEBUG .PEDANTIC .INSPECTOR:
            mkdir $@