在 Fortran90 中,是否可以在主程序中使用文件中的模块?
In Fortran90, is it possible to use a module from a file with a main program?
我继承了一些我不想编辑的遗留 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
我想在文件 myprogram.f90
中的我自己的程序中使用模块 libmain
,如下所示:
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
排除在最终 linking 的参数之外,但这也失败了:
>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.o
和 libmain.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
文件,即使当我尝试 link myprogram.
。那么为什么 gfortran 找不到符号 dostuff
呢?它显然知道在哪里可以找到文件libmain.mod
,这不是问题。
编辑:我尝试了更多技巧,none 成功了。
我想也许问题是 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.
所以我也更改了 myprogram.f90
中对 main
的引用:
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 中是不允许的。
如果您想使用 module,您可以将它复制到一个不同的单独的源文件,没有旧程序,或者在现有文件中注释掉旧程序。
您不能link同时使用两个程序。
您尝试过的那些技巧只是转移注意力,请勿尝试使用 .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
瞧瞧!
P.S.
请注意,这是一个 hack,您可能会遇到很多副作用,尤其是在您的原始代码设置了一些全局变量、进行了一些初始化等的情况下。因此,请谨慎使用这种方法。
我继承了一些我不想编辑的遗留 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
我想在文件 myprogram.f90
中的我自己的程序中使用模块 libmain
,如下所示:
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
排除在最终 linking 的参数之外,但这也失败了:
>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.o
和 libmain.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
文件,即使当我尝试 link myprogram.
。那么为什么 gfortran 找不到符号 dostuff
呢?它显然知道在哪里可以找到文件libmain.mod
,这不是问题。
编辑:我尝试了更多技巧,none 成功了。
我想也许问题是 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.
所以我也更改了 myprogram.f90
中对 main
的引用:
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 中是不允许的。
如果您想使用 module,您可以将它复制到一个不同的单独的源文件,没有旧程序,或者在现有文件中注释掉旧程序。
您不能link同时使用两个程序。
您尝试过的那些技巧只是转移注意力,请勿尝试使用 .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
瞧瞧!
P.S.
请注意,这是一个 hack,您可能会遇到很多副作用,尤其是在您的原始代码设置了一些全局变量、进行了一些初始化等的情况下。因此,请谨慎使用这种方法。