Loading...
Searching...
No Matches
os.f90
Go to the documentation of this file.
1!> @file
2!! @defgroup group_os OS
3!! Operating system detection utilities for the fpx preprocessor
4!! This lightweight module provides reliable runtime detection of the current operating
5!! system on Unix-like platforms (Linux, macOS, FreeBSD, OpenBSD, Solaris) and Windows
6!! (including Cygwin, MSYS, and native Windows). Detection is performed only once per
7!! thread (using OpenMP threadprivate storage) and then cached for fast subsequent calls.
8!! The implementation first checks common environment variables (`OSTYPE`, `OS`),
9!! then falls back to the presence of OS-specific files. This makes it robust across
10!! native systems, containers, WSL, Cygwin, and cross-compilation environments.
11!!
12!! <h2 class="groupheader">Examples</h2>
13!!
14!! 1. Basic OS detection:
15!! @code{.f90}
16!! integer :: my_os
17!! my_os = get_os_type()
18!! print *, 'Running on: ', OS_NAME(my_os)
19!! !> prints e.g. 'Running on: Linux'
20!! @endcode
21!!
22!! 2. Conditional compilation based on OS:
23!! @code{.f90}
24!! !platform specific system call
25!! if (os_is_unix()) then
26!! call system('gcc --version')
27!! else
28!! call execute_command_line('gfortran --version')
29!! end if
30!! ...
31!! @endcode
32!!
33!! 3. Using the cached value explicitly:
34!! @code{.f90}
35!! integer :: os_type
36!! os_type = get_os_type() ! detects and caches
37!! print *, os_is_unix(os_type) ! fast, no re-detection
38!! ...
39!! @endcode
40module fpx_os
41 implicit none; private
42
43 public :: get_os_type, &
45
46 public :: os_name
47 !> @brief Unknown / undetected operating system
48 !! @ingroup group_os
49 integer, parameter, public :: os_unknown = 0
50 !> @brief Linux (any distribution, including GNU/Linux)
51 !! @ingroup group_os
52 integer, parameter, public :: os_linux = 1
53 !> @brief macOS (Darwin-based Apple operating system)
54 !! @ingroup group_os
55 integer, parameter, public :: os_macos = 2
56 !> @brief Microsoft Windows (native, 32-bit or 64-bit)
57 !! @ingroup group_os
58 integer, parameter, public :: os_windows = 3
59 !> @brief Cygwin POSIX environment on Windows
60 !! @ingroup group_os
61 integer, parameter, public :: os_cygwin = 4
62 !> @brief Oracle Solaris / OpenSolaris derivatives
63 !! @ingroup group_os
64 integer, parameter, public :: os_solaris = 5
65 !> @brief FreeBSD and its direct derivatives
66 !! @ingroup group_os
67 integer, parameter, public :: os_freebsd = 6
68 !> @brief OpenBSD
69 !! @ingroup group_os
70 integer, parameter, public :: os_openbsd = 7
71 !> @brief Microsoft Windows — explicitly 32-bit (x86) architecture.
72 !!
73 !! Mainly useful when different behavior is needed between 32-bit and 64-bit Windows
74 !! @ingroup group_os
75 integer, parameter, public :: os_windowsx86 = 8
76
77contains
78
79 !> Return a human-readable string describing the OS type flag
80 !! Converts any of the OS_* integer constants into its corresponding name.
81 !! Useful for logging, error messages, or user output.
82 !! @param[in] os OS identifier from get_os_type()
83 !! @return Allocated character string with the OS name
84 !!
85 !! @b Remarks
86 !! @ingroup group_os
87 pure function os_name(os) result(res)
88 integer, intent(in) :: os
89 character(:), allocatable :: res
90
91 select case (os)
92 case (os_linux); res = 'Linux'
93 case (os_macos); res = 'macOS'
94 case (os_windows); res = 'Windows'
95 case (os_cygwin); res = 'Cygwin'
96 case (os_solaris); res = 'Solaris'
97 case (os_freebsd); res = 'FreeBSD'
98 case (os_openbsd); res = 'OpenBSD'
99 case (os_unknown); res = 'Unknown'
100 case default ; res = 'UNKNOWN'
101 end select
102 end function
103
104 !> Determine the current operating system type
105 !! Returns one of the OS_* constants. Detection is performed only on the first call
106 !! and cached in threadprivate storage for subsequent fast access.
107 !!
108 !! Detection strategy:
109 !! 1. Environment variable `OSTYPE` (common on Unix-like systems)
110 !! 2. Environment variable `OS` (set on Windows)
111 !! 3. Presence of OS-specific files (/etc/os-release, /usr/bin/sw_vers, etc.)
112 !!
113 !! Returns OS_UNKNOWN if no reliable indicator is found.
114 !!
115 !! @return OS identifier (OS_LINUX, OS_MACOS, OS_WINDOWS, ...)
116 !!
117 !! @b Remarks
118 !! @ingroup group_os
119 integer function get_os_type() result(r)
120 character(len=255) :: val
121 integer :: length, rc
122 logical :: file_exists
123 logical, save :: first_run = .true.
124 integer, save :: ret = os_unknown
125 !$omp threadprivate(ret, first_run)
126
127 if (.not. first_run) then
128 r = ret
129 return
130 end if
131
132 first_run = .false.
133 r = os_unknown
134
135 ! Check environment variable `OSTYPE`.
136 call get_environment_variable('OSTYPE', val, length, rc)
137
138 if (rc == 0 .and. length > 0) then
139 ! Linux
140 if (index(val, 'linux') > 0) then
141 r = os_linux
142 ret = r
143 return
144 end if
145
146 ! macOS
147 if (index(val, 'darwin') > 0) then
148 r = os_macos
149 ret = r
150 return
151 end if
152
153 ! Windows, MSYS, MinGW, Git Bash
154 if (index(val, 'win') > 0 .or. index(val, 'msys') > 0) then
155 r = os_windows
156 ret = r
157 return
158 end if
159
160 ! Cygwin
161 if (index(val, 'cygwin') > 0) then
162 r = os_cygwin
163 ret = r
164 return
165 end if
166
167 ! Solaris, OpenIndiana, ...
168 if (index(val, 'SunOS') > 0 .or. index(val, 'solaris') > 0) then
169 r = os_solaris
170 ret = r
171 return
172 end if
173
174 ! FreeBSD
175 if (index(val, 'FreeBSD') > 0 .or. index(val, 'freebsd') > 0) then
176 r = os_freebsd
177 ret = r
178 return
179 end if
180
181 ! OpenBSD
182 if (index(val, 'OpenBSD') > 0 .or. index(val, 'openbsd') > 0) then
183 r = os_openbsd
184 ret = r
185 return
186 end if
187 end if
188
189 ! Check environment variable `OS`.
190 call get_environment_variable('OS', val, length, rc)
191
192 if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then
193 r = os_windows
194 ret = r
195 call get_environment_variable('PROCESSOR_ARCHITECTURE', val, length, rc)
196 if (rc == 0 .and. length > 0 .and. index(val, 'x86') > 0) then
197 r = os_windowsx86
198 ret = r
199 end if
200 return
201 end if
202
203 ! Linux
204 inquire(file='/etc/os-release', exist=file_exists)
205
206 if (file_exists) then
207 r = os_linux
208 ret = r
209 return
210 end if
211
212 ! macOS
213 inquire(file='/usr/bin/sw_vers', exist=file_exists)
214
215 if (file_exists) then
216 r = os_macos
217 ret = r
218 return
219 end if
220
221 ! FreeBSD
222 inquire(file='/bin/freebsd-version', exist=file_exists)
223
224 if (file_exists) then
225 r = os_freebsd
226 ret = r
227 return
228 end if
229 end function
230
231 !> Return .true. if the current (or supplied) OS is Unix-like
232 !! Convenience wrapper that returns .true. for any non-Windows platform.
233 !! Useful for writing portable code that needs different handling on Windows.
234 !! @param[in] os Optional OS identifier; if absent get_os_type() is called
235 !! @return .true. if OS is not Windows, .false. otherwise
236 !!
237 !! @b Remarks
238 !! @ingroup group_os
239 logical function os_is_unix(os)
240 integer, intent(in), optional :: os
241 integer :: build_os
242 if (present(os)) then
243 build_os = os
244 else
245 build_os = get_os_type()
246 end if
247 os_is_unix = build_os /= os_windows
248 end function
249end module
integer, parameter, public os_windowsx86
Microsoft Windows — explicitly 32-bit (x86) architecture.
Definition os.f90:75
integer, parameter, public os_solaris
Oracle Solaris / OpenSolaris derivatives.
Definition os.f90:64
integer, parameter, public os_windows
Microsoft Windows (native, 32-bit or 64-bit)
Definition os.f90:58
integer, parameter, public os_linux
Linux (any distribution, including GNU/Linux)
Definition os.f90:52
integer, parameter, public os_openbsd
OpenBSD.
Definition os.f90:70
integer, parameter, public os_freebsd
FreeBSD and its direct derivatives.
Definition os.f90:67
integer, parameter, public os_macos
macOS (Darwin-based Apple operating system)
Definition os.f90:55
integer, parameter, public os_unknown
Unknown / undetected operating system.
Definition os.f90:49
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:240
integer function, public get_os_type()
Determine the current operating system type Returns one of the OS_* constants. Detection is performed...
Definition os.f90:120
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:88
integer, parameter, public os_cygwin
Cygwin POSIX environment on Windows.
Definition os.f90:61