我正在尝试使用混合的 C 和 Fortran 代码构建一个静态库。构建 fortran 文件时,我的每个 fortran 文件都会收到此错误,但 c 文件不会。
make: Circular file0.F90 <- file0.F90.o dependency dropped.
mpif90 -c -O2 -o "file0.F90.o" "file0.F90"
我正在使用的 Makefile 如下。我对 F90 文件的规则与对 c 文件的规则相同,所以我不确定为什么它应该有这种行为?
CC = mpicc
FC = mpif90
TARGET=libpxn
FCFLAGS = -O2 -fPIC
CFLAGS = -O2 -fPIC -lm -Wall
CPPFLAGS = $(CFLAGS)
SRCS = $(wildcard *.F90) $(wildcard *.c)
OBJS = $(patsubst %, %.o, $(SRCS))
# Rules
all: static
static: $(OBJS)
ar rcs $(TARGET).a $(OBJS)
%.c.o: %.c
$(CC) -c $(CFLAGS) -o "$@" "$<"
%.F90.o: %.F90
$(FC) -c $(FCFLAGS) -o "$@" "$<"
clean:
@printf "Cleaning: \n"
@find . -type f -name '*.o' -print0 | xargs -0 -I % sh -c 'printf "% "; rm -f %'
rm -f $(TARGET).so $(TARGET).a
我也尝试过使用 gnu 编译器,得到了相同的结果。有什么想法为什么会发生这种情况吗?
最佳答案
.c
是一个内置后缀,这意味着至少有一个内置规则定义为 %.c:
,它将阻止 make 应用将任何规则 (%:
) 与以 .c
结尾的文件匹配。
Make 不知道 .F90
,因此当它达到 %.F90.o
规则的先决条件时,它将尝试应用匹配任何规则 %: %.o
,结果为 file0.F90: file0.F90.o
和循环依赖。
快速但肮脏的解决方案是简单地为.F90添加一个空模式规则
%.F90:
处理这个问题的“正确”方法(恕我直言)是重写你的 makefile 以符合内置的隐式规则
TARGET := libpxn.a
CC := mpicc
FC := mpif90
FFLAGS := -O2 -fPIC
CFLAGS := -O2 -fPIC -Wall
ARFLAGS := rcs
CSRCS := $(wildcard *.c)
FSRCS := $(wildcard *.F90)
OBJS := $(CSRCS:.c=.o) $(FSRCS:.F90=.o)
.PHONY: all clean
all: $(TARGET)($(OBJS))
%.o: %.F90
$(COMPILE.F) $(OUPUT_OPTION) $<
%.F90:
clean:
$(info "Cleaning:")
$(RM) $(TARGET)
Make 有一个内置的存档规则,因此您只需指定 ARFLAGS
并使用 libname(objects)
作为先决条件(如果您使用的是 GNU ar
你不需要 s
因为它总是会创建索引)。
F90
配方是从 make 的 .F
内置规则复制的,事实上,如果您使用 .F
作为 Fortran 后缀如果不使用 .F90
,您甚至不需要此规则。
如果您有两个具有相同主干的源文件(例如 foo.c
和 foo.F90
),您必须将源文件拆分为两个子目录(推荐),或者返回原来的双后缀计划(在这种情况下,您需要再次提供这两个规则)。
我重写了clean
,因为对象现在是中间文件,在添加到存档后将自动删除。
关于循环依赖删除了: make, fortran和c构建静态库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37139512/