Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit d724658

Browse files
authored
system: OS type query (#942)
2 parents d2767cf + fbaacc9 commit d724658

File tree

7 files changed

+366
-2
lines changed

7 files changed

+366
-2
lines changed

‎doc/specs/stdlib_system.md‎

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,85 @@ Returns a `logical` flag: `.true.` if the system is Windows, or `.false.` otherw
335335
```fortran
336336
{!example/system/example_process_1.f90!}
337337
```
338+
339+
## `get_runtime_os` - Determine the OS type at runtime
340+
341+
### Status
342+
343+
Experimental
344+
345+
### Description
346+
347+
`get_runtime_os` inspects the runtime environment to identify the current OS type. It evaluates environment variables (`OSTYPE`, `OS`) and checks for specific files associated with known operating systems.
348+
The supported OS types are `integer, parameter` variables stored in the `stdlib_system` module:
349+
350+
- **Linux** (`OS_LINUX`)
351+
- **macOS** (`OS_MACOS`)
352+
- **Windows** (`OS_WINDOWS`)
353+
- **Cygwin** (`OS_CYGWIN`)
354+
- **Solaris** (`OS_SOLARIS`)
355+
- **FreeBSD** (`OS_FREEBSD`)
356+
- **OpenBSD** (`OS_OPENBSD`)
357+
358+
If the OS cannot be identified, the function returns `OS_UNKNOWN`.
359+
360+
### Syntax
361+
362+
`os = [[stdlib_system(module):get_runtime_os(function)]]()`
363+
364+
### Class
365+
366+
Function
367+
368+
### Arguments
369+
370+
None.
371+
372+
### Return Value
373+
374+
Returns one of the `integer` `OS_*` parameters representing the OS type, from the `stdlib_system` module, or `OS_UNKNOWN` if undetermined.
375+
376+
### Example
377+
378+
```fortran
379+
{!example/system/example_get_runtime_os.f90!}
380+
```
381+
382+
---
383+
384+
## `OS_TYPE` - Cached OS type retrieval
385+
386+
### Status
387+
388+
Experimental
389+
390+
### Description
391+
392+
`OS_TYPE` provides a cached result of the `get_runtime_os` function. The OS type is determined during the first invocation and stored in a static variable.
393+
Subsequent calls reuse the cached value, making this function highly efficient.
394+
395+
This caching mechanism ensures negligible overhead for repeated calls, unlike `get_runtime_os`, which performs a full runtime inspection.
396+
397+
### Syntax
398+
399+
`os = [[stdlib_system(module):OS_TYPE(function)]]()`
400+
401+
### Class
402+
403+
Function
404+
405+
### Arguments
406+
407+
None.
408+
409+
### Return Value
410+
411+
Returns one of the `integer` `OS_*` parameters representing the OS type, from the `stdlib_system` module, or `OS_UNKNOWN` if undetermined.
412+
413+
---
414+
415+
### Example
416+
417+
```fortran
418+
{!example/system/example_os_type.f90!}
419+
```

‎example/system/CMakeLists.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
ADD_EXAMPLE(get_runtime_os)
2+
ADD_EXAMPLE(os_type)
13
ADD_EXAMPLE(process_1)
24
ADD_EXAMPLE(process_2)
35
ADD_EXAMPLE(process_3)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
! Demonstrate usage of (non-cached) runtime OS query
2+
program example_get_runtime_os
3+
use stdlib_system, only: OS_NAME, get_runtime_os
4+
implicit none
5+
6+
! Runtime OS detection (full inspection)
7+
print *, "Runtime OS Type: ", OS_NAME(get_runtime_os())
8+
9+
end program example_get_runtime_os

‎example/system/example_os_type.f90‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
! Demonstrate OS detection
2+
program example_os_type
3+
use stdlib_system, only: OS_TYPE, OS_NAME
4+
implicit none
5+
6+
integer :: current_os
7+
8+
! Cached OS detection
9+
current_os = OS_TYPE()
10+
print *, "Current OS Type: ", OS_NAME(current_os)
11+
12+
end program example_os_type

‎src/stdlib_system.F90‎

Lines changed: 190 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,70 @@ module stdlib_system
55
private
66
public :: sleep
77

8+
!! version: experimental
9+
!!
10+
!! Cached OS type retrieval with negligible runtime overhead.
11+
!! ([Specification](../page/specs/stdlib_system.html#os_type-cached-os-type-retrieval))
12+
!!
13+
!! ### Summary
14+
!! Provides a cached value for the runtime OS type.
15+
!!
16+
!! ### Description
17+
!!
18+
!! This function caches the result of `get_runtime_os` after the first invocation.
19+
!! Subsequent calls return the cached value, ensuring minimal overhead.
20+
!!
21+
public :: OS_TYPE
22+
23+
!! version: experimental
24+
!!
25+
!! Determine the current operating system (OS) type at runtime.
26+
!! ([Specification](../page/specs/stdlib_system.html#get_runtime_os-determine-the-os-type-at-runtime))
27+
!!
28+
!! ### Summary
29+
!! This function inspects the runtime environment to identify the OS type.
30+
!!
31+
!! ### Description
32+
!!
33+
!! The function evaluates environment variables (`OSTYPE` or `OS`) and filesystem attributes
34+
!! to identify the OS. It distinguishes between several common operating systems:
35+
!! - Linux
36+
!! - macOS
37+
!! - Windows
38+
!! - Cygwin
39+
!! - Solaris
40+
!! - FreeBSD
41+
!! - OpenBSD
42+
!!
43+
!! Returns a constant representing the OS type or `OS_UNKNOWN` if the OS cannot be determined.
44+
!!
45+
public :: get_runtime_os
46+
47+
!> Version: experimental
48+
!>
49+
!> Integer constants representing known operating system (OS) types
50+
!> ([Specification](../page/specs/stdlib_system.html))
51+
integer, parameter, public :: &
52+
!> Represents an unknown operating system
53+
OS_UNKNOWN = 0, &
54+
!> Represents a Linux operating system
55+
OS_LINUX = 1, &
56+
!> Represents a macOS operating system
57+
OS_MACOS = 2, &
58+
!> Represents a Windows operating system
59+
OS_WINDOWS = 3, &
60+
!> Represents a Cygwin environment
61+
OS_CYGWIN = 4, &
62+
!> Represents a Solaris operating system
63+
OS_SOLARIS = 5, &
64+
!> Represents a FreeBSD operating system
65+
OS_FREEBSD = 6, &
66+
!> Represents an OpenBSD operating system
67+
OS_OPENBSD = 7
68+
69+
!! Helper function returning the name of an OS parameter
70+
public :: OS_NAME
71+
872
!> Public sub-processing interface
973
public :: run
1074
public :: runasync
@@ -218,7 +282,6 @@ module logical function process_is_running(process) result(is_running)
218282
end function process_is_running
219283
end interface is_running
220284

221-
222285
interface is_completed
223286
!! version: experimental
224287
!!
@@ -397,7 +460,11 @@ subroutine process_callback(pid,exit_state,stdin,stdout,stderr,payload)
397460
class(*), optional, intent(inout) :: payload
398461
end subroutine process_callback
399462
end interface
400-
463+
464+
!! Static storage for the current OS
465+
logical :: have_os = .false.
466+
integer :: OS_CURRENT = OS_UNKNOWN
467+
401468
interface
402469

403470
!! version: experimental
@@ -430,4 +497,125 @@ end function process_get_ID
430497

431498
end interface
432499

500+
contains
501+
502+
integer function get_runtime_os() result(os)
503+
!! The function identifies the OS by inspecting environment variables and filesystem attributes.
504+
!!
505+
!! ### Returns:
506+
!! - **OS_UNKNOWN**: If the OS cannot be determined.
507+
!! - **OS_LINUX**, **OS_MACOS**, **OS_WINDOWS**, **OS_CYGWIN**, **OS_SOLARIS**, **OS_FREEBSD**, or **OS_OPENBSD**.
508+
!!
509+
!! Note: This function performs a detailed runtime inspection, so it has non-negligible overhead.
510+
511+
! Local variables
512+
character(len=255) :: val
513+
integer :: length, rc
514+
logical :: file_exists
515+
516+
os = OS_UNKNOWN
517+
518+
! Check environment variable `OSTYPE`.
519+
call get_environment_variable('OSTYPE', val, length, rc)
520+
521+
if (rc == 0 .and. length > 0) then
522+
! Linux
523+
if (index(val, 'linux') > 0) then
524+
os = OS_LINUX
525+
return
526+
527+
! macOS
528+
elseif (index(val, 'darwin') > 0) then
529+
os = OS_MACOS
530+
return
531+
532+
! Windows, MSYS, MinGW, Git Bash
533+
elseif (index(val, 'win') > 0 .or. index(val, 'msys') > 0) then
534+
os = OS_WINDOWS
535+
return
536+
537+
! Cygwin
538+
elseif (index(val, 'cygwin') > 0) then
539+
os = OS_CYGWIN
540+
return
541+
542+
! Solaris, OpenIndiana, ...
543+
elseif (index(val, 'SunOS') > 0 .or. index(val, 'solaris') > 0) then
544+
os = OS_SOLARIS
545+
return
546+
547+
! FreeBSD
548+
elseif (index(val, 'FreeBSD') > 0 .or. index(val, 'freebsd') > 0) then
549+
os = OS_FREEBSD
550+
return
551+
552+
! OpenBSD
553+
elseif (index(val, 'OpenBSD') > 0 .or. index(val, 'openbsd') > 0) then
554+
os = OS_OPENBSD
555+
return
556+
end if
557+
end if
558+
559+
! Check environment variable `OS`.
560+
call get_environment_variable('OS', val, length, rc)
561+
562+
if (rc == 0 .and. length > 0 .and. index(val, 'Windows_NT') > 0) then
563+
os = OS_WINDOWS
564+
return
565+
end if
566+
567+
! Linux
568+
inquire (file='/etc/os-release', exist=file_exists)
569+
570+
if (file_exists) then
571+
os = OS_LINUX
572+
return
573+
end if
574+
575+
! macOS
576+
inquire (file='/usr/bin/sw_vers', exist=file_exists)
577+
578+
if (file_exists) then
579+
os = OS_MACOS
580+
return
581+
end if
582+
583+
! FreeBSD
584+
inquire (file='/bin/freebsd-version', exist=file_exists)
585+
586+
if (file_exists) then
587+
os = OS_FREEBSD
588+
return
589+
end if
590+
591+
end function get_runtime_os
592+
593+
!> Retrieves the cached OS type for minimal runtime overhead.
594+
integer function OS_TYPE() result(os)
595+
!! This function uses a static cache to avoid recalculating the OS type after the first call.
596+
!! It is recommended for performance-sensitive use cases where the OS type is checked multiple times.
597+
if (.not.have_os) then
598+
OS_CURRENT = get_runtime_os()
599+
have_os = .true.
600+
end if
601+
os = OS_CURRENT
602+
end function OS_TYPE
603+
604+
!> Return string describing the OS type flag
605+
pure function OS_NAME(os)
606+
integer, intent(in) :: os
607+
character(len=:), allocatable :: OS_NAME
608+
609+
select case (os)
610+
case (OS_LINUX); OS_NAME = "Linux"
611+
case (OS_MACOS); OS_NAME = "macOS"
612+
case (OS_WINDOWS); OS_NAME = "Windows"
613+
case (OS_CYGWIN); OS_NAME = "Cygwin"
614+
case (OS_SOLARIS); OS_NAME = "Solaris"
615+
case (OS_FREEBSD); OS_NAME = "FreeBSD"
616+
case (OS_OPENBSD); OS_NAME = "OpenBSD"
617+
case default ; OS_NAME = "Unknown"
618+
end select
619+
end function OS_NAME
620+
433621
end module stdlib_system

‎test/system/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
ADDTEST(os)
12
ADDTEST(sleep)
23
ADDTEST(subprocess)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /