我正在使用Intel的ifort和GNU make在linux机器上构建我的项目。 lib依赖于源目录中的源文件a.f90,b.f90和c.f90。
我正在通过
调用makemake FLAG
这些FLAGS在我的makefile中定义,并对应于编译器的不同优化标志。
我希望我的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)
#
答案 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$@
(或其他)添加到相应的标记中。