问题描述
我继承了一些不想编辑的旧版 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.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
文件,即使我在尝试链接 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,您可能会遇到很多副作用,尤其是在您的原始代码设置了一些全局变量、进行了一些初始化等的情况下。因此,使用这种方法时要小心。