ターゲット
fortranのプログラムのコンパイル時に
- `MAIN__' が重複して定義されています
- `main' が重複して定義されています
とか出てきてコンパイルができずに困っている人
原因
メインプログラムが複数あるFortranプログラムを1つのオブジェクトファイルにしようとしているため,コンパイラに怒られています
検証
コンパイラ
- gfortran : GNU Fortran (GCC) 4.8.5 20150623
- ifort : 18.0.5 20180823
プログラム例
main.f90
program main
implicit none
write(*,*) 'main'
end program main
sub.f90
program sub
implicit none
write(*,*) 'sub'
end program sub
この環境で
(gfortran)
gfortran main.f90 sub.f90
(ifort)
ifort main.f90 sub.f90
と実行して,a.outを作ろうとすると
gfortranでは
/tmp/ccpYzODA.o: 関数 `main' 内:
sub.f90:(.text+0x6d): `main' が重複して定義されています
/tmp/ccfZ2hhv.o:main.f90:(.text+0x6d): ここで最初に定義されています
ifortでは
/tmp/ifortQAup3r.o: 関数 `MAIN__' 内:
sub.f90:(.text+0x0): `MAIN__' が重複して定義されています
/tmp/ifortP0sgiZ.o:main.f90:(.text+0x0): ここで最初に定義されています
という風にコンパイラに怒られることが確認できました
解決策
- プログラムを分割実行していいならコンパイルも分割させる
- 1つの実行可能ファイルから実行させたいならいずれかのプログラムをsubroutineかfunctionに変える
とコンパイル・実行できるようになるはずです
プログラムを分割実行していい場合
コンパイル時に,例えば
(gfortran)
gfortran main.f90 -o main.o
gfortran sub.f90 -o sub.o
./main.o && ./sub.o
(ifort)
ifort main.f90 -o main.o
ifort sub.f90 -o sub.o
./main.o && ./sub.o
とすればコンパイル・実行できて,標準出力に
main
sub
と出力されます
分割したくない場合
1つのメインプログラムを実行して
main
sub
と標準出力に出力させたいなら,今回のプログラム例の場合
main.f90
program main
implicit none
write(*,*) 'main'
call sub()
end program main
sub.f90
subroutine sub
implicit none
write(*,*) 'sub'
end subroutine sub
として
(gfortran)
gfortran main.f90 sub.f90
./a.out
(ifort)
ifort main.f90 sub.f90
./a.out
とすれば
main
sub
と出力されます
結論
programを重複定義しないように気を付けよう!