使用 makefile 将多个可执行文件从多个源目录编译到单个 bin 目录
Compile multiple executables from multiple source directories to single bin directory using makefile
我正在尝试为我正在处理的一套程序创建一个联编文件。这些程序都是用 fortran 编写的,源文件包含在不同的目录中。我似乎无法弄清楚如何让事情正常进行。我当前的 sumfile 是
#Compiler and compiler flag variables
FCOMP=/usr/local/bin/gfortran
F_FLAGS=-O2 -fbounds-check -Wall
F_FLAGSDB=-g -fbounds-check -Wall
#paths to libraries
COMMON_LIB=/usr/local/lib/libspc_common.a
SPICE_LIB=/usr/local/lib/spicelib.a
# Paths to directories
BIN_DIR=BIN
# Get file names of component source files
#get names of files in src1
FORT_FILES=$(wildcard ./SRC1/*.f)
#get names of files in src2
FORTFILES+=$(wildcard ./SRC2/*.f)
#get names of files in src3
FORTFILES+=$(wildcard ./SRC3/*.f)
#get file names for output
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
# make commands
# Set the default option to compile the library with optimization
default: all
# create all command
all: $(EXE_FILES)
@echo toolkit has been built with optimization
#If compiling for debugging replace the compiler flags to remove optimization and add debugging
debug: F_FLAGS=$(F_FLAGSDB)
#Run compiler with debugging flags
debug: $(EXE_FILES)
@echo toolkit has been built with debugging
# Compile all of the source files into executables
$(EXE_FILES): % : %.f
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$@
# install the library in /usr/local/lib
install:
cp -p $(BIN_DIR)* /usr/local/bin/toolkit/
# remove executable files for a clean build
clean:
rm $(BIN_DIR)*
我 运行 遇到的问题是当我尝试 运行 make:
时出现以下错误
make: *** No rule to make target `Display.f', needed by `Display'. Stop.
我假设这是因为我丢失了源文件所在的目录。有人可以帮我吗?我完全卡住了,不知道如何继续。
此外(这是关于 make 的更普遍的问题),如果 COMMON_LIB 发生变化,有没有办法告诉 make 重新编译所有内容?
感谢您的帮助!
假设您的源文件是
SRC1/alpha.f
SRC1/beta.f
SRC2/gamma.f
SRC3/delta.f
1)这里有个漏洞:
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
这将产生
BINalpha BINbeta BINgamma BINdelta
当我认为你打算
BIN/alpha BIN/beta BIN/gamma BIN/delta
一个简单的修复:
EXE_FILES=$(addprefix $(BIN_DIR)/,$(notdir $(patsubst %.f, % , $(FORTFILES))))
2)现在看静态模式规则:
$(EXE_FILES): % : %.f
...
所以要构建 BIN/alpha
,Make 必须首先找到 BIN/alpha.f
,它不存在。要使其查找 alpha.f
,请执行以下操作:
$(EXE_FILES): $(BIN_DIR)/% : %.f
...
3) 如何找到资源?
你可以做一些精细的编码来帮助 Make 记住它在哪里找到 alpha.f
,但是当我们可以使用 the vpath directive:
时就没有必要了
vpath %.f SRC1 SRC2 SRC3
4) 最后看一下该规则:
这个命令:
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$@
将产生例如BIN/BIN/alpha
,这很愚蠢。 A non-PHONY Make rule should produce a file whose name is the target of the rule. 避免了很多麻烦。
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $@
一旦您完美运行,可能还可以进行一些进一步的改进。
我正在尝试为我正在处理的一套程序创建一个联编文件。这些程序都是用 fortran 编写的,源文件包含在不同的目录中。我似乎无法弄清楚如何让事情正常进行。我当前的 sumfile 是
#Compiler and compiler flag variables
FCOMP=/usr/local/bin/gfortran
F_FLAGS=-O2 -fbounds-check -Wall
F_FLAGSDB=-g -fbounds-check -Wall
#paths to libraries
COMMON_LIB=/usr/local/lib/libspc_common.a
SPICE_LIB=/usr/local/lib/spicelib.a
# Paths to directories
BIN_DIR=BIN
# Get file names of component source files
#get names of files in src1
FORT_FILES=$(wildcard ./SRC1/*.f)
#get names of files in src2
FORTFILES+=$(wildcard ./SRC2/*.f)
#get names of files in src3
FORTFILES+=$(wildcard ./SRC3/*.f)
#get file names for output
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
# make commands
# Set the default option to compile the library with optimization
default: all
# create all command
all: $(EXE_FILES)
@echo toolkit has been built with optimization
#If compiling for debugging replace the compiler flags to remove optimization and add debugging
debug: F_FLAGS=$(F_FLAGSDB)
#Run compiler with debugging flags
debug: $(EXE_FILES)
@echo toolkit has been built with debugging
# Compile all of the source files into executables
$(EXE_FILES): % : %.f
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$@
# install the library in /usr/local/lib
install:
cp -p $(BIN_DIR)* /usr/local/bin/toolkit/
# remove executable files for a clean build
clean:
rm $(BIN_DIR)*
我 运行 遇到的问题是当我尝试 运行 make:
时出现以下错误make: *** No rule to make target `Display.f', needed by `Display'. Stop.
我假设这是因为我丢失了源文件所在的目录。有人可以帮我吗?我完全卡住了,不知道如何继续。
此外(这是关于 make 的更普遍的问题),如果 COMMON_LIB 发生变化,有没有办法告诉 make 重新编译所有内容?
感谢您的帮助!
假设您的源文件是
SRC1/alpha.f
SRC1/beta.f
SRC2/gamma.f
SRC3/delta.f
1)这里有个漏洞:
EXE_FILES=$(addprefix $(BIN_DIR),$(notdir $(patsubst %.f, % , $(FORTFILES))))
这将产生
BINalpha BINbeta BINgamma BINdelta
当我认为你打算
BIN/alpha BIN/beta BIN/gamma BIN/delta
一个简单的修复:
EXE_FILES=$(addprefix $(BIN_DIR)/,$(notdir $(patsubst %.f, % , $(FORTFILES))))
2)现在看静态模式规则:
$(EXE_FILES): % : %.f
...
所以要构建 BIN/alpha
,Make 必须首先找到 BIN/alpha.f
,它不存在。要使其查找 alpha.f
,请执行以下操作:
$(EXE_FILES): $(BIN_DIR)/% : %.f
...
3) 如何找到资源?
你可以做一些精细的编码来帮助 Make 记住它在哪里找到 alpha.f
,但是当我们可以使用 the vpath directive:
vpath %.f SRC1 SRC2 SRC3
4) 最后看一下该规则:
这个命令:
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $(BIN_DIR)/$@
将产生例如BIN/BIN/alpha
,这很愚蠢。 A non-PHONY Make rule should produce a file whose name is the target of the rule. 避免了很多麻烦。
$(FCOMP) $(F_FLAGS) $^ $(COMMON_LIB) $(SPICE_LIB) -o $@
一旦您完美运行,可能还可以进行一些进一步的改进。