Loading...
Searching...
No Matches
os.f90
Go to the documentation of this file.
1!> @file
2!! @defgroup group_os OS
3!! This module provides portable runtime operating-system detection
4!! facilities used throughout the fpx preprocessor.
5!!
6!! Supported platforms include:
7!! - Linux distributions
8!! - macOS
9!! - Native Microsoft Windows
10!! - Cygwin
11!! - Solaris/OpenSolaris
12!! - FreeBSD
13!! - OpenBSD
14!!
15!! Detection is performed lazily on first use and cached using
16!! OpenMP threadprivate storage, ensuring negligible overhead for
17!! repeated queries.
18!!
19!! The implementation relies primarily on environment variables,
20!! with fallback detection through the presence of well-known
21!! operating-system specific files.
22!!
23!! This strategy is designed to work reliably in native
24!! installations, containers, WSL environments, and most
25!! cross-compilation setups.
26!!
27!! @par Detection Model
28!! OS identification is attempted in the following order:
29!! 1. Environment variable `OSTYPE`
30!! 2. Environment variable `OS`
31!! 3. Operating-system specific filesystem probes
32!! 4. Fallback to OS_UNKNOWN
33!!
34!! @section os_examples Examples
35!!
36!! 1. Basic OS detection:
37!! @code{.f90}
38!! integer :: my_os
39!! my_os = get_os_type()
40!! print *, 'Running on: ', os_name(my_os)
41!! !> prints e.g. 'Running on: Linux'
42!! @endcode
43!!
44!! 2. Conditional compilation based on OS:
45!! @code{.f90}
46!! !platform specific system call
47!! if (os_is_unix()) then
48!! call system('gcc --version')
49!! else
50!! call execute_command_line('gfortran --version')
51!! end if
52!! ...
53!! @endcode
54!!
55!! 3. Using the cached value explicitly:
56!! @code{.f90}
57!! integer :: os_type
58!! os_type = get_os_type() ! detects and caches
59!! print *, os_is_unix(os_type) ! fast, no re-detection
60!! ...
61!! @endcode
62!!
63!! 4. Module constants
64!!
65!! @code{.f90}
66!! if (get_os_type() == OS_WINDOWS) then
67!! ...
68!! end if
69!! ...
70!! @endcode
71module fpx_os
72 implicit none; private
73
74 public :: get_os_type, &
75 os_is_unix, &
77
78 !> @brief Unknown / undetected operating system
79 !! @ingroup group_os
80 integer, parameter, public :: os_unknown = 0
81 !> @brief Linux (any distribution, including GNU/Linux)
82 !! @ingroup group_os
83 integer, parameter, public :: os_linux = 1
84 !> @brief macOS (Darwin-based Apple operating system)
85 !! @ingroup group_os
86 integer, parameter, public :: os_macos = 2
87 !> @brief Microsoft Windows (native, 32-bit or 64-bit)
88 !! @ingroup group_os
89 integer, parameter, public :: os_windows = 3
90 !> @brief Cygwin POSIX environment on Windows
91 !! @ingroup group_os
92 integer, parameter, public :: os_cygwin = 4
93 !> @brief Oracle Solaris / OpenSolaris derivatives
94 !! @ingroup group_os
95 integer, parameter, public :: os_solaris = 5
96 !> @brief FreeBSD and its direct derivatives
97 !! @ingroup group_os
98 integer, parameter, public :: os_freebsd = 6
99 !> @brief OpenBSD
100 !! @ingroup group_os
101 integer, parameter, public :: os_openbsd = 7
102 !> @brief Native Microsoft Windows running on 32-bit x86 architecture.
103 !!
104 !! This value is returned when the operating system is identified
105 !! as Windows and the PROCESSOR_ARCHITECTURE environment variable
106 !! indicates an x86 target.
107 !!
108 !! It can be used when architecture-specific behavior is required.
109 !!
110 !! @ingroup group_os
111 integer, parameter, public :: os_windowsx86 = 8
112
113contains
114
115 !> Return a human-readable string describing the OS type flag
116 !! Converts any of the OS_* integer constants into its corresponding name.
117 !! Accepted values include:
118 !! - OS_UNKNOWN
119 !! - OS_LINUX
120 !! - OS_MACOS
121 !! - OS_WINDOWS
122 !! - OS_WINDOWSx86
123 !! - OS_CYGWIN
124 !! - OS_SOLARIS
125 !! - OS_FREEBSD
126 !! - OS_OPENBSD
127 !! Useful for logging, error messages, or user output.
128 !! @param[in] os OS identifier from get_os_type()
129 !! @return Allocated character string with the OS name
130 !!
131 !! @b Examples
132 !!
133 !! @code{.f90}
134 !! print *, os_name(OS_LINUX)
135 !! !> prints: Linux
136 !! ...
137 !! @endcode
138 !!
139 !! @ingroup group_os
140 pure function os_name(os) result(res)
141 integer, intent(in) :: os
142 character(:), allocatable :: res
143
144 select case (os)
145 case (os_linux); res = 'Linux'
146 case (os_macos); res = 'macOS'
147 case (os_windows); res = 'Windows'
148 case (os_cygwin); res = 'Cygwin'
149 case (os_solaris); res = 'Solaris'
150 case (os_freebsd); res = 'FreeBSD'
151 case (os_openbsd); res = 'OpenBSD'
152 case (os_unknown); res = 'Unknown'
153 case default ; res = 'UNKNOWN'
154 end select
155 end function
156
157 !> Determine the current operating system type
158 !! Returns one of the OS_* constants.
159 !!
160 !! @par Thread Safety
161 !! The detected value is cached independently for each OpenMP thread
162 !! using threadprivate storage. Concurrent calls therefore incur no
163 !! synchronization overhead after the first query on each thread.
164 !!
165 !! Detection strategy:
166 !! 1. Environment variable `OSTYPE` (common on Unix-like systems)
167 !! 2. Environment variable `OS` (set on Windows)
168 !! 3. Presence of OS-specific files (/etc/os-release, /usr/bin/sw_vers, etc.)
169 !!
170 !! Returns OS_UNKNOWN if no reliable indicator is found.
171 !!
172 !! @return OS identifier (OS_LINUX, OS_MACOS, OS_WINDOWS, ...)
173 !!
174 !!
175 !! @b Examples
176 !!
177 !! @code{.f90}
178 !! select case (get_os_type())
179 !! case (OS_WINDOWS)
180 !! print *, 'Windows'
181 !! case (OS_LINUX)
182 !! print *, 'Linux'
183 !! end select
184 !! ...
185 !! @endcode
186 !!
187 !! @ingroup group_os
188 integer function get_os_type() result(r)
189 character(len=255) :: val
190 integer :: length, rc
191 logical :: file_exists
192 logical, save :: first_run = .true.
193 integer, save :: ret = os_unknown
194 !$omp threadprivate(ret, first_run)
195
196 if (.not. first_run) then
197 r = ret
198 return
199 end if
200
201 first_run = .false.
202 r = os_unknown
203
204 ! Check environment variable `OSTYPE`.
205 call get_environment_variable('OSTYPE', val, length, rc)
206
207 if (rc == 0 .and. length > 0) then
208 ! Linux
209 if (index(val, 'linux') > 0) then
210 r = os_linux
211 ret = r
212 return
213 end if
214
215 ! macOS
216 if (index(val, 'darwin') > 0) then
217 r = os_macos
218 ret = r
219 return
220 end if
221
222 ! Windows, MSYS, MinGW, Git Bash
223 if (index(val, 'win') > 0 .or. index(val, 'msys') > 0) then
224 r = os_windows
225 ret = r
226 return
227 end if
228
229 ! Cygwin
230 if (index(val, 'cygwin') > 0) then
231 r = os_cygwin
232 ret = r
233 return
234 end if
235
236 ! Solaris, OpenIndiana, ...
237 if (index(val, 'SunOS') > 0 .or. index(val, 'solaris') > 0) then
238 r = os_solaris
239 ret = r
240 return
241 end if
242
243 ! FreeBSD
244 if (index(val, 'FreeBSD') > 0 .or. index(val, 'freebsd') > 0) then
245 r = os_freebsd
246 ret = r
247 return
248 end if
249
250 ! OpenBSD
251 if (index(val, 'OpenBSD') > 0 .or. index(val, 'openbsd') > 0) then
252 r = os_openbsd
253 ret = r
254 return
255 end if
256 end if
257
258 ! Check environment variable `OS`.
259 call get_environment_variable('OS', val, length, rc)
260
261 if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then
262 r = os_windows
263 ret = r
264 call get_environment_variable('PROCESSOR_ARCHITECTURE', val, length, rc)
265 if (rc == 0 .and. length > 0 .and. index(val, 'x86') > 0) then
266 r = os_windowsx86
267 ret = r
268 end if
269 return
270 end if
271
272 ! Linux
273 inquire(file='/etc/os-release', exist=file_exists)
274
275 if (file_exists) then
276 r = os_linux
277 ret = r
278 return
279 end if
280
281 ! macOS
282 inquire(file='/usr/bin/sw_vers', exist=file_exists)
283
284 if (file_exists) then
285 r = os_macos
286 ret = r
287 return
288 end if
289
290 ! FreeBSD
291 inquire(file='/bin/freebsd-version', exist=file_exists)
292
293 if (file_exists) then
294 r = os_freebsd
295 ret = r
296 return
297 end if
298 end function
299
300 !> Return .true. if the current (or supplied) OS is Unix-like
301 !! Convenience wrapper that returns .true. for any non-Windows platform.
302 !! Useful for writing portable code that needs different handling on Windows.
303 !! @param[in] os Optional OS identifier; if absent get_os_type() is called
304 !! @return .true. if OS is not Windows, .false. otherwise
305 !!
306 !! @b Examples
307 !!
308 !! @code{.f90}
309 !! if (os_is_unix()) then
310 !! call execute_command_line('uname -a')
311 !! end if
312 !! ...
313 !! @endcode
314 !!
315 !! @ingroup group_os
316 logical function os_is_unix(os)
317 integer, intent(in), optional :: os
318 integer :: build_os
319 if (present(os)) then
320 build_os = os
321 else
322 build_os = get_os_type()
323 end if
324 os_is_unix = build_os /= os_windows
325 end function
326end module
integer, parameter, public os_windowsx86
Native Microsoft Windows running on 32-bit x86 architecture.
Definition os.f90:111
integer, parameter, public os_solaris
Oracle Solaris / OpenSolaris derivatives.
Definition os.f90:95
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_openbsd
OpenBSD.
Definition os.f90:101
integer, parameter, public os_freebsd
FreeBSD and its direct derivatives.
Definition os.f90:98
integer, parameter, public os_macos
macOS (Darwin-based Apple operating system)
Definition os.f90:86
integer, parameter, public os_unknown
Unknown / undetected operating system.
Definition os.f90:80
logical function, public os_is_unix(os)
Return .true. if the current (or supplied) OS is Unix-like Convenience wrapper that returns ....
Definition os.f90:317
integer function, public get_os_type()
Determine the current operating system type Returns one of the OS_* constants.
Definition os.f90:189
pure character(:) function, allocatable, public os_name(os)
Return a human-readable string describing the OS type flag Converts any of the OS_* integer constants...
Definition os.f90:141
integer, parameter, public os_cygwin
Cygwin POSIX environment on Windows.
Definition os.f90:92