j3-fortran / fortran_proposals

Proposals for the Fortran Standard Committee
175 stars 14 forks source link

A set of `get_platform` intrinsics #284

Open 14NGiestas opened 1 year ago

14NGiestas commented 1 year ago

A set of intrinsics to identify the platform the code is executing. (I bet there was one proposal like this already but I couldn't find)

program main
print*, get_platform_system() ! linux, windows, darwin, freebsd, other-aix, other-os2
print*, get_platform_relase() ! 2.2.0, NT
print*, get_platform_posix() ! Return POSIX version if it supports it, empty string otherwise.
print*, get_platform_arch() ! Returns the architecture of the processor
end program

There is a GNU gfortran issue open about 10 years where common macros used to detect the platform in a C environment aren't available on the Fortran side. Implementing an intrinsic function that returns a name identifying the platform the executable is supposed to be running would be trivial for Fortran Processors in their supported platforms.

The lack of this feature holds back Fortran with respect to code portability and it makes it harder for the community to come up with workarounds.

The only dangling point would be the string content itself, in order to restrict variations, the standard could cherry-pick the most popular platforms supported among compilers (Linux, Windows, Darwin, Freebsd) and just let the Fortran Processor decide the rest (maybe prepending an "other-" extra identifier).

Later standards could trivially include a new OS if there is enough buzz around to support it.


Q: But C standard doesn't have this either! R: Fortran is not C, it could be the first one to have it.

Q: But there's not only Linux and Windows! R: Yeah, that's why the standard would let the vendor handle how to identify other not specified platforms and users of such platforms would not be let down.

Q: Not every OS is POSIX! R: The point is to have a standard way to detect if it is POSIX or not.

certik commented 1 year ago

C might not have it, but Python does. There is a whole platform module just for this.

14NGiestas commented 1 year ago

C might not have it, but Python does.

Yep, Python isn't standardized though, but it surely is one big source of inspiration. Rust also has it std::env::consts using string constants.

jacobwilliams commented 1 year ago

Would definitely be a good idea for stdlib.

14NGiestas commented 1 year ago

Would definitely be a good idea for stdlib.

There was an attempt by awvwgk here to detect platforms and implement some POSIX stuff, but it didn't work since the lack of proper C macros I've mentioned, I did try too but gave up after such issue.

It could be revisited now, we could get Python's platform info at the compile time using fypp as a start, in such case it would be trivial to implement, but I wonder if it would work along with the C interfaces needed to support other POSIX routines (I hope so).

14NGiestas commented 1 year ago

Hmm there's one thing, stdlib needs to receive the proper fpmization in order to compile it with the correct fypp platform (in the current state it would get the CI platform and not the desired one).

w6ws commented 1 year ago

Back in the early 1990s, POSIX.9-1992 defined a Fortran API into the POSIX environment. A number of vendors implemented the API. Unfortunately the Standard was never renewed, so eventually died.

However, today you can look at Intel and Cray for examples of good implementations. I used to use them a lot. And in fact have developed my own personal version for use with gfortran. (Yes, I should probably put it out on github to share with others. But I'm actually completely re-writing it right now. So maybe later.)

For this request, the POSIX.9 call would be PXFUNAME. Its sole argument, besides the error return, is a handle to a 'utsname' structure for the uname(2) system call to fill in. It returns 'sysname', 'nodename', 'release', 'version', and 'machine' fields in the struct.

The API library uses handles to structs because back in 1992 most vendors only had Fortran 77 compilers. So it was written to be compatible with Fortran 77. (Ick.) You create a handle and associated underlying struct by calling PXFSTRUCTCREATE. In this case, pass the handle to PXFUNAME. Then use PXFSTRGET to access the various character string fields. It can work well enough - but of course isn't as nice as if it had been defined using Fortran-90 derived types. Here is a snippet:

character(128) :: sysname integer :: sysname_l

integer :: jutsname ! handle to utsname struct integer :: ierror ... call pxfstructcreate ('utsname', jutsname, ierror) if (ierror /= 0) ... ! Error call pxfuname (jutsname, ierror) if (ierror /= 0) ... ! Error call pxfstrget (jutsname, 'sysname', sysname, sysname_l, ierror) if (ierror /= 0) ... ! Error print *, 'system name = ', sysname(:sysname_l)

In my new version, the calls that require structure handles will also have derived type equivalents. I'm also recoding to make extensive internal use of the Fortran 2003 C Interop, and Fortran 2008 submodule features - neither of which existed when I originally wrote it. So hopefully the above code snippet can look something like:

type(pxf_utsname) :: utsname integer :: ierror ... allocate (utsname) call pxf_uname (utsname, ierror) if (ierror /= 0) ... ! Error print *, 'system name = ', utsname%sysname

If a syslib implementation were to be done, this could be a useful direction. Though I realize that 'uname' calls with 'utsname' structs are very POSIX. So the names could be changed to be less POSIX-like.

BTW, 25 years or more ago, I was told by a couple of Fortran committee members that one of the reasons POSIX.9 was being allowed to die was that F2003 C Interop was going to save the world. It hasn't. The .9 Standard should have been updated in a more Fortran 90ish way. MPI and others have proven that APIs originally defined to be compatible with Fortran 77 can successfully be recast in a Modern Fortran way.

14NGiestas commented 1 year ago

@w6ws Thank you for sharing it, I would never knew (born in 98 btw). It would be nice to have something to start with in stdlib_system. One issue more or less it's to support non-posix systems, but even windows nowadays have some support to it, and it's extremely important to build further abstractions upon it.

w6ws commented 1 year ago

@w6ws Thank you for sharing it, I would never knew (born in 98 btw). It would be nice to have something to start with in stdlib_system. One issue more or less it's to support non-posix systems, but even windows nowadays have some support to it, and it's extremely important to build further abstractions upon it.

I initially developed my package on Windoze NT - using cygwin to provide a POSIX-like layer. At the time, the no-longer-supported g77 compiler was popular. Andy Vaught was developing his g95 compiler. Then there was a split between Andy and the folks wanting to help develop g95, and gfortran was born. My package ran on all of them, and a few other unix/linux systems.

Interestingly, the unit tests I wrote to test my package also exposed bugs in the Cray/SGI implementations, and later the Intel implementation. Thankfully the various compiler teams fixed their bugs.

These days I have zero interest in making any of it work with any Fortran 77 compiler. So my rewrite is taking advantage of newer Fortran 2003 and 2008 features (as supported by gfortran 9.4). There are a couple of I/O related features in POSIX.9 that require mods to the compilers run-time library. I didn't support these then. Maybe this time I'll try hacking libgfortran. But first things first...