Loading...
Searching...
No Matches
compiler.f90
Go to the documentation of this file.
1!> @file
2!! @defgroup group_fpx_compiler Compiler
3!! Retrieves compiler information at run time as the compiler's name
4!! and version. It uses the intrinsic
5!! functions `compiler_options` and `compiler_version` from the
6!! module `iso_fortran_env`
7module fpx_compiler
8 use, intrinsic :: iso_fortran_env, only: compiler_version, compiler_options
9 use fpx_os, only: get_os_type, os_linux, os_macos, os_windows
10 use fpx_string, only: lowercase
11
12 implicit none; private
13
14 public :: get_compiler
15
16contains
17
18 function get_compiler(is_standalone) result(res)
19 logical, intent(in) :: is_standalone
20 character(:), allocatable :: res
21 !private
22 integer :: ios, l
23
24 if (is_standalone) then
25 call get_environment_variable('FC', length=l, status = ios, trim_name = .true.)
26 select case (ios)
27 case(1)
28 res = get_caller_name()
29 case(2)
30 res = ''
31 case default
32 allocate(character(len=max(l, 1)) :: res)
33 call get_environment_variable('FC', res, status = ios, trim_name = .true.)
34 if (ios /= 0) res = ''
35 end select
36 else
37 res = get_compilerinfo()
38 end if
39 end function
40
41 !> Detects current compiler and prints name, vendor, and version
42 !! @ingroup group_steps_compiler
43 !! @b Remarks
44 function get_compilerinfo() result(res)
45 character(:), allocatable :: res
46 !private
47 integer :: os
48 character(:), allocatable :: version
49
50 os = get_os_type()
51 version = lowercase(compiler_version())
52
53 if (index(version, 'gcc') > 0) then
54 res = 'gfortran'
55 else if (index(version, 'intel') > 0) then
56 if (index(version, 'classic') > 0) then
57 if (os == os_linux) then
58 res = 'ifort'
59 elseif (os == os_windows) then
60 res = merge('ia32 ', 'ifort', index(version, 'IA-32') > 0)
61 elseif (os == os_macos) then
62 res = 'ifort'
63 end if
64 else
65 if (os == os_linux) then
66 res = 'ifx'
67 elseif (os == os_windows) then
68 res = 'ifx'
69 else
70 res = 'ifx'
71 end if
72 end if
73 else if (index(version, 'nvfortran') > 0) then
74 res = 'nvhpc'
75 else if (index(version, 'nag fortran') > 0) then
76 res = 'nagfor'
77 else if (index(version, 'flang') > 0) then
78 res = 'flang'
79 else if (index(version, 'ibm xl') > 0) then
80 res = 'xlf90'
81 else if (index(version, 'lahey/fujitsu') > 0) then
82 res = 'lf90'
83 else if (index(version, 'lfortran') > 0) then
84 res = 'lfortran'
85 end if
86 end function
87
88 function get_caller_name() result(res)
89#ifdef _WIN32
90 use fpx_process_windows, only: get_parent_pid_windows, get_process_name_windows
91 character(:), allocatable :: res
92 !private
93 integer :: pid
94
95 pid = 1
96
97 do while (pid > 0)
98 pid = get_parent_pid_windows()
99 if (pid <= 1) then
100 res = ''
101 exit
102 end if
103 res = get_process_name_windows(pid)
104 if (is_compiler(res)) exit
105 end do
106#else
107 use fpx_process_posix, only: get_parent_pid_posix, get_process_name_posix
108 !private
109 character(:), allocatable :: res
110 !private
111 integer :: pid
112
113 pid = 1
114
115 do while (pid > 0)
117 if (pid <= 1) then
118 res = ''
119 exit
120 end if
121 res = get_process_name_posix(pid)
122 if (is_compiler(res)) exit
123 end do
124#endif
125 end function
126
127 !> Return a normalized executable name.
128 !!
129 !! The returned name is lowercase, platform-independent and stripped of
130 !! common executable suffixes. Equivalent compiler executables are mapped
131 !! to a canonical name.
132 !!
133 !! Examples:
134 !! - `gfortran.exe` to `gfortran`
135 !! - `ifx.exe` to `ifx`
136 !! - `flang-new` to `flang`
137 !! - `NVFORTRAN.EXE` to `nvfortran`
138 !!
139 !! @return Canonical executable name.
140 !! @ingroup group_process
141 function normalized_name(name) result(res)
142 character(:), allocatable, intent(in) :: name
143 character(:), allocatable :: res
144 !private
145 integer :: pos
146
147 if (.not. allocated(name)) then
148 res = ''
149 return
150 end if
151 pos = index(name, '.')
152
153 if (pos > 0) then
154 res = name(:pos-1)
155 else
156 res = name
157 end if
158 res = lowercase(res)
159 end function
160
161
162 !> Determine whether the executable is a known Fortran compiler.
163 !!
164 !! The comparison is performed using the normalized executable name.
165 !!
166 !! @return `.true.` if the executable corresponds to a supported Fortran
167 !! compiler.
168 !! @ingroup group_process
169 logical function is_compiler(name)
170 character(:), allocatable, intent(in) :: name
171 !private
172 character(:), allocatable :: exe
173
174 exe = normalized_name(name)
175
176 select case (exe)
177 case ('gfortran', &
178 'caf', &
179 'ifort', &
180 'ifx', &
181 'ia32', &
182 'pgfortran', &
183 'nvfortran', &
184 'f95', &
185 'f18', &
186 'flang-new', &
187 'flang', &
188 'lfortran', &
189 'nagfor', &
190 'xlf90', &
191 'lf95', &
192 'crayftn')
193
194 is_compiler = .true.
195 case default
196 is_compiler = .false.
197 end select
198 end function
199end module
integer, parameter, public os_windows
Microsoft Windows (native, 32-bit or 64-bit).
Definition os.f90:89
integer, parameter, public os_linux
Linux (any distribution, including GNU/Linux).
Definition os.f90:83
integer, parameter, public os_macos
macOS (Darwin-based Apple operating system)
Definition os.f90:86
integer function, public get_os_type()
Determine the current operating system type Returns one of the OS_* constants.
Definition os.f90:189
integer function, public get_parent_pid_posix()
Return parent PID (PPID) on POSIX systems.
pure character(len_trim(str)) function, public lowercase(str)
Convert string to lower case (respects contents of quotes).
Definition string.f90:852
Locate the position of a substring.
Definition string.f90:395