Fortran Makefile - 循环依赖性下降和m2c

时间:2015-08-26 13:14:00

标签: makefile fortran

以下是工作制作;它是一个更复杂的简化版本,但它设法在我尝试一些更改时重现问题。文件" myobj.f"和" mymod.f"在文件夹" src1"和" src2"分别几乎为空(mymod是一个声明了变量的模块,myobj是一个初始化并打印该变量的子程序)。

我尝试使用谷歌搜索,但我发现的所有循环依赖错误似乎比这更明确。你能帮我辨别一下我的makefile有什么问题吗?

all : mylib.so
makefiles := Makefile
FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC

obj_path := obj
src_paths = src1 src2
vpath %.o   $(obj_path)
vpath %.mod $(obj_path)
vpath %.f   $(src_paths)

objects = myobj.o mymod.o
obj/myobj.o : obj/mymod.mod

mylib.so : $(objects:%.o=$(obj_path)/%.o)
        $(FC) $(LFLAGS) $^ $(LIBS) -o $@

$(obj_path)/%.mod : %.o
        @touch $@

$(obj_path)/%.o   : %.f   $(makefiles) |  $(obj_path)
        $(FC) $(FFLAGS) -c $< -o $@

$(obj_path) :
        mkdir -p $@

.PHONY: clean
clean:
        rm -rf mylib.so $(obj_path)

(1)我无法简化规则

拥有&#34; $(obj_path)&#34;显然在编译对象的规则中似乎是不必要的:我知道vpath不适用于在编译期间更改的文件,并且仅针对源设计,但是当我将对象列为依赖关系时,我不明白为什么要澄清路径图书馆不够。

mylib.so : $(objects:%.o=$(obj_path)/%.o)
        $(FC) $(LFLAGS) $^ $(LIBS) -o $@

%.mod : %.o
        @touch $@

%.o   : %.f   $(makefiles) |  $(obj_path)
        $(FC) $(FFLAGS) -c $< -o $@

但这不起作用;我得到一个循环依赖关系丢弃警告,并尝试使用m2c编译模块。为了以防万一,评论.o和.mod的vpath并不能解决这个问题。 make的输出--debug:

Reading makefiles...
Updating goal targets....
 File 'all' does not exist.
   File 'mylib.so' does not exist.
     File 'obj/myobj.o' does not exist.
make: Circular obj/myobj.mod <- obj/myobj.o dependency dropped.
       File 'obj/mymod.mod' does not exist.
         File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
        Must remake target 'obj/mymod.o'.
m2c    -o obj/mymod.o 
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127

(2)我无法为f90

添加规则

现在我希望能够将f90代码合并到我的库中。如果没有其他更改,添加规则似乎不会影响进程,但是当我将mymod.f的扩展名更改为mymod.f90时,它会返回与其他情况类似的错误。修改后的部分是:

$(obj_path)/%.mod : %.o
        @touch $@

$(obj_path)/%.o   : %.f   $(makefiles) |  $(obj_path)
        $(FC) $(FFLAGS) -c $< -o $@

$(obj_path)/%.o   : %.f90   $(makefiles) |  $(obj_path)
        $(FC) $(FFLAGS) -c $< -o $@

make --debug的输出是这样的:

Reading makefiles...
Updating goal targets....
 File 'all' does not exist.
   File 'mylib.so' does not exist.
     File 'obj/myobj.o' does not exist.
       File 'obj' does not exist.
      Must remake target 'obj'.
mkdir -p obj
      Successfully remade target file 'obj'.
       File 'obj/mymod.mod' does not exist.
         File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
        Must remake target 'obj/mymod.o'.
m2c    -o obj/mymod.o 
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127

COMPILATION CONFIG 1:

生成文件:

all : mylib.so
makefiles := Makefile
FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC

obj_path := obj
src_paths = src1 src2
#vpath %.o   $(obj_path)
#vpath %.mod $(obj_path)
vpath %.f   $(src_paths)

objects = myobj.o mymod.o
obj/myobj.o : obj/mymod.mod

mylib.so : $(objects:%.o=$(obj_path)/%.o)
        $(FC) $(LFLAGS) $^ $(LIBS) -o $@

%.mod : %.o
        @touch $@

%.o   : %.f   $(makefiles) |  $(obj_path)
        $(FC) $(FFLAGS) -c $< -o $@

$(obj_path) :
        mkdir -p $@

.PHONY: clean
clean:
        rm -rf mylib.so $(obj_path)

SRC1 / myobj.f:

       subroutine myobj
       use mymod
       implicit none
       mymodx=1
       print*,'mymod was included', mymodx
       return
       end subroutine

SRC2 / mymod.f:

       module mymod
       implicit none
       integer :: mymodx
       end module

终端输出:

make --debug
GNU Make 4.1
Built for x86_64-unknown-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
 File 'all' does not exist.
   File 'mylib.so' does not exist.
     File 'obj/myobj.o' does not exist.
make: Circular obj/myobj.mod <- obj/myobj.o dependency dropped.
       File 'obj/mymod.mod' does not exist.
         File 'obj/mymod.o' does not exist.
make: Circular obj/mymod.o <- obj/mymod.mod dependency dropped.
        Must remake target 'obj/mymod.o'.
m2c    -o obj/mymod.o 
make: m2c: Command not found
<builtin>: recipe for target 'obj/mymod.o' failed
make: *** [obj/mymod.o] Error 127

1 个答案:

答案 0 :(得分:1)

您的方法存在一些问题。 vpath搜索仅适用于先决条件而非目标,因此像

这样的规则
%.o: %.f

会在$(src_paths)搜索来源,但不会尝试匹配$(obj_path)中的目标。这导致了下一个问题,即由于将对象放入中间目录,您的规则需要考虑到这一点,因为vpath无法提供帮助。构建库的主要目标取决于$(obj_path)/blah.f之类的内容,因此您希望使用如下规则:

$(obj_path)/%.o: %.f

匹配对象。可能有一种更清洁的方法,但我不知道它们。

同样,具有%.mod目标的规则与对象目录中的要求不匹配,并且看起来正在调用默认隐式规则来处理它们,尝试调用m2c。 /> 具体来说,make尝试将mod文件编译为modula-2源,并将其自动规则与您的%.o:%.mod规则冲突,并产生循环依赖关系。 通过修改该规则以正确匹配mod文件,可以避免这种混乱。

此外,不要忘记为vpath添加%.f90,以便您的规则可以找到这些源文件。

我可以使用这个稍微修改过的Makefile成功构建您的测试项目。我还使用了名为.f90的文件来表明它也解决了你的第二个问题。

FC = gfortran
FFLAGS = -I$(obj_path) -J$(obj_path) -fPIC
LFLAGS = -shared -fPIC

src_paths = src1 src2
obj_path := obj
vpath %.o $(obj_path)
vpath %.mod $(obj_path)
vpath %.f90 $(src_paths)
vpath %.f $(src_paths)

mylib_objects = myobj.o mymod.o
mylib_target = mylib.so

all: $(mylib_target)

$(mylib_target) : $(mylib_objects:%.o=$(obj_path)/%.o)
    $(FC) $(LFLAGS) $^ $(LIBS) -o $@

$(obj_path)/myobj.o: myobj.f90 $(obj_path)/mymod.mod

$(obj_path) :
    mkdir -p $@

$(obj_path)/%.mod : %.o $(obj_path)
    @true

$(obj_path)/%.o: %.f | $(obj_path)
    $(FC) $(FFLAGS) -c $< -o $@

$(obj_path)/%.o: %.f90 | $(obj_path)
    $(FC) $(FFLAGS) -c $< -o $@

clean:
    rm -rf $(mylib_target) $(obj_path) 

从一个干净的开始,make --debug的输出是:

% make --debug
GNU Make 4.1
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
 File 'all' does not exist.
   File 'mylib.so' does not exist.
     File 'obj/myobj.o' does not exist.
       File 'obj' does not exist.
      Must remake target 'obj'.
mkdir -p obj
      Successfully remade target file 'obj'.
       File 'obj/mymod.mod' does not exist.
         File 'obj/mymod.o' does not exist.
        Must remake target 'obj/mymod.o'.
gfortran -Iobj -Jobj -fPIC -c src2/mymod.f90 -o obj/mymod.o
        Successfully remade target file 'obj/mymod.o'.
      Must remake target 'obj/mymod.mod'.
      Successfully remade target file 'obj/mymod.mod'.
    Must remake target 'obj/myobj.o'.
gfortran -Iobj -Jobj -fPIC -c src1/myobj.f90 -o obj/myobj.o
    Successfully remade target file 'obj/myobj.o'.
  Must remake target 'mylib.so'.
gfortran -shared -fPIC obj/myobj.o obj/mymod.o  -o mylib.so
  Successfully remade target file 'mylib.so'.
Must remake target 'all'.
Successfully remade target file 'all'.

另请注意,您可以通过在另一个中保留必要的mod文件生成的目标文件来处理模块依赖性。例如,更改

objects = myobj.o mymod.o

objects = mymod.o myobj.o

使得涉及mod文件的规则和先决条件不必要,因为这将导致mymod.o(以及副产品mymod.mod)在尝试myobj.o之前构建。这个解决方案可能会在并行构建中中断,因此我保持了对象的排序并确保规则按预期工作。