我正在尝试从 Fortran 源代码构建两个不同的库,一个支持 OMP,另一个不支持。因此,来自同一源的 %.o 文件根据编译器标志的不同而有所不同。当更改/重新编译一个源文件时,ar 仍然需要所有 o 文件来重建库。为了避免重新编译所有源文件,我想将未更改的源文件中的 o 文件存储在两个不同的目录中,一个目录包含 omp 支持的 o 文件,另一个目录不包含 omp 支持。我很高兴必须在库最终所在的目录中生成文件。
但是,由于 vpath 变量行为,我无法在单个命令中重建库。这是制作文件:
SRC :=
FORTRAN = ifort
OPTSSEQ = -mkl=sequential -DThreadUnSafe -warn nounused -warn declarations -O3 -DTIMEDETAIL
DRVOPTS = $(OPTS)
NOOPT =
LOADER = ifort
LOADOPTS =
kernel=$(shell uname -r)
ARCH = ar
ARCHFLAGS= cr
RANLIB = ranlib
LibName=Lib_LM_$(FORTRAN)_$(kernel)_1.0.a
.SUFFIXES:
.SUFFIXES: .f90 .o
include Moduls.mk
vpath %.f90 src/
vpath %.o NoOMP/
OBJS = $(patsubst %.f90,%.o,$(SRC))
$(LibName): $(OBJS)
$(ARCH) $(ARCHFLAGS) $@ $?
$(RANLIB) $@
%.o : %.f90
$(FORTRAN) $(OPTSSEQ) -c $? -o $(addprefix NoOMP/,$@)
clean:
-rm *.mod
-rm NoOMP/*.o
-rm *.smod
-rm $(LibName)
这会导致在“make clean”后成功构建所有 %.o 文件,因为所有 %.f90 文件均从 src/ 读取,并且所有 %.o 文件均写入 NoOMP/。但是,构建存档失败,因为 %.o 文件上的“NoOMP”前缀被删除。因此,ar 抱怨它找不到 %.o 文件。仅当我再次运行“make”时,才会构建存档,因为 %.o 文件具有 NoOMP 前缀。如果从头开始构建,向存档构建行添加前缀命令效果很好。但是,如果仅更改了单个文件,则未更改的文件具有“NoOMP/NoOMP/”前缀,从而导致再次中止。
虽然这非常烦人,但据我了解,这是 GNU make 的默认行为的手册。如果我错了,我该如何修复makefile,如果我是对的,我该如何规避这个问题。
答案1
解决了
这些示例在更改线路时有效
$(ARCH) $(ARCHFLAGS) $@ $?
到
$(ARCH) $(ARCHFLAGS) $@ $(addprefix NoOMP/,$?)
上面我已经排除了这个解决方案,但我的试验是基于$^
而不是$?
。虽然第一个将从旧的和新的 %.o 文件重建整个存档,但最后一个只会使用新的 %.o 文件更新现有存档。当从旧的和新的 %.o 文件重建整个存档时,旧的 %.o 文件将具有错误的前缀,新的则正确。因此,通过使用新编译的 %.o 文件更新存档来排除旧的 %.o 文件可以避免该问题。
干杯