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