在 Fortran90 中,是否可以将文件中的模块与主程序一起使用?

问题描述

我继承了一些不想编辑的旧版 Fortran90 代码文件 main.f90一个模块,其中包含一些我想在我自己的程序中使用的子程序,但也有一个主程序。它看起来像这样:

module libmain
    implicit none
    contains
    subroutine dostuff
        print *,'m'
    end subroutine dostuff
end module libmain

program main
    use libmain
    implicit none
    call dostuff
end program main

我想在我自己的程序中的文件 libmain 中使用模块 myprogram.f90,如下所示:

program myprogram
    use libmain
    implicit none
    call dostuff
end program myprogram

我已经尝试了所有我能想到的方法来完成这项工作。例如:

>gfortran -c main.f90
>gfortran -c myprogram.f90
>gfortran -o myprogram main.o myprogram.o

失败并出现错误

duplicate symbol '_main' in:
    main.o
    myprogram.o
ld: 1 duplicate symbol for architecture x86_64
collect2: error: ld returned 1 exit status

我尝试将 main.o 排除在最终链接的参数之外,但也失败了:

>gfortran -o myprogram myprogram.f90
Undefined symbols for architecture x86_64:
  "___libmain_MOD_dostuff",referenced from:
      _MAIN__ in myprogram.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

有趣的是,如果我删除文件 main.olibmain.mod,,我会得到一个不同的错误

>rm main.o
>rm libmain.mod
>gfortran -o myprogram myprogram.f90
myprogram.f90:2:8:

     use libmain
        1
Fatal error: Can't open module file ‘libmain.mod’ for reading at (1): No such file or directory
compilation terminated.

所以 gfortran 知道它应该寻找 libmain.mod 文件,即使我在尝试链接 main 时没有在参数中包含任何关于 myprogram.内容.那么为什么 gfortran 找不到符号 dostuff?它显然知道在哪里可以找到文件 libmain.mod,这不是问题。

编辑:我又尝试了一些技巧,但都没有奏效。

我认为问题可能在于 gfortran 期望 .o.mod 文件具有相同的名称,因此我重命名

>mv main.o libmain.o
>gfortran -o myprogram myprogram.f90

Undefined symbols for architecture x86_64:
  "___libmain_MOD_dostuff",referenced from:
      _MAIN__ in ccmD6cx3.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

所以这也行不通。我也尝试过另一种方式,将 libmain.mod 移至 main.mod

>rm *.mod
>rm *.o
>gfortran -c main.f90
>gfortran -c myprogram.f90
>mv libmain.mod main.mod
>gfortran -o myprogram myprogram.o
Undefined symbols for architecture x86_64:
  "___libmain_MOD_dostuff",referenced from:
      _MAIN__ in myprogram.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

如果我在编译 myprogram.f90 之前进行重命名

>rm *.mod
>rm *.o
>gfortran -c main.f90
>mv libmain.mod main.mod
>gfortran -c myprogram.f90
myprogram.f90:2:8:

     use libmain
        1
Fatal error: Can't open module file ‘libmain.mod’ for reading at (1): No such file or directory
compilation terminated.

所以我也在 main 中更改了对 myprogram.f90 的引用:

program myprogram
    use main
    implicit none
    call dostuff
end program myprogram

同时保持 main.f90 不变。现在我执行以下步骤(从头开始):

>rm *.mod
>rm *.o
>gfortran -c main.f90
>mv libmain.mod main.mod
>gfortran -c myprogram.f90 
>gfortran -o myprogram myprogram.o
Undefined symbols for architecture x86_64:
  "___libmain_MOD_dostuff",referenced from:
      _MAIN__ in myprogram.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status

这样就修复了文件引用错误,但我仍然没有得到我需要的符号。

解决方法

你不能有两个程序。 Fortran 中不允许这样做。

如果您想使用该模块,您可以将其复制到不同的单独源文件中,不使用旧程序,或者在现有文件中注释掉旧程序。

您不能同时将两个程序链接在一起。

您尝试的那些技巧只是红鲱鱼,不要尝试使用 .mod 文件或任何东西。以某种方式从编译链中删除旧程序。

,

我理解你的痛苦,伙计。即使已经发布的答案是您可以获得的最佳建议,但如果您正在处理遗留代码,真正的遗留代码,它并不能解决您的问题。

让我们尝试破解它。假设您拥有旧代码(您可能处于无法访问源代码的情况)。

! a.f90
module libmain
    implicit none
    contains
    subroutine dostuff
        print *,'m'
    end subroutine dostuff
end module libmain

program main
    use libmain
    implicit none
    call dostuff
end program main

而且,假设这是您的全新 _main

! b.f90
program myprogram
    use libmain
    implicit none
    print *,'Hello from b'
    call dostuff
end program myprogram

现在,让我们解决您的问题,这些令人讨厌的 _main 符号遍布四周。

> gfortran-8.3.0 -c a.f90
> objcopy -W _main a.o  # Force symbol _main to be marked as a weak
> gfortran-8.3.0 -c b.f90
> gfortran-8.3.0 -o main a.o b.o
> ./main
 Hello from b
 m

瞧!

附言

请注意,这是一个 hack,您可能会遇到很多副作用,尤其是在您的原始代码设置了一些全局变量、进行了一些初始化等的情况下。因此,使用这种方法时要小心。