fortran-lang / fpm

Fortran Package Manager (fpm)
https://fpm.fortran-lang.org
MIT License
870 stars 97 forks source link

Universal Fortran compiler #475

Open awvwgk opened 3 years ago

awvwgk commented 3 years ago

Suggested on discourse: https://fortran-lang.discourse.group/t/gsoc-project-meeting-fpm-compiler-flags/1265/3

I really like the idea of having an universal Fortran compiler in fpm. We could have fpm provide a compiler wrapper which abstracts existing compilers and tries to normalize command line options. The possibly best way to realize this might be a separate fpm project which provides an fpm-compiler command as standalone and fpm plugin as well as a library which fpm can depend on to actually make use of the compiler abstraction for the target compilation.

LKedward commented 3 years ago

I'm also a fan of this idea and it is not something I'd ever considered before. This would also open up the opportunity to standardise a directory structure for distributing Fortran module-based libraries as discussed here.

certik commented 3 years ago

Indeed. I think there is a large common denominator of all Fortran compilers, that we should provide a unified interface to. This is another avenue to tackle https://github.com/fortran-lang/fpm/discussions/443, as we slowly build this "unified interface", we can then use it in fpm itself to provide good support for things like fast-math or debugging options such as array bounds checking.

urbanjost commented 3 years ago

In my own environment I use a command (ccall) for programs (not for libraries, there is something else for that)

$ ccall --help
untitled()                                                          untitled()

NAME
       ccall(1) - identifies system and then compiles and loads and installs
       C, Fortran, and manpages

SYNOPSIS
       ccall file.[f|F|c|f90|F90|.ff|.FF|html|HTML|[1-8]|.man] other_options
       ccall -r ccall [-h]

DESCRIPTION
       Given program source code or other files needing processing, determine
       what system you are on, preprocess the files based on their suffix, and
       then build and install them in a standard location.

       The installation area top directory set is by $CCALL_HOME (that
       defaults to $HOME). It ia assumed to have subdirectories bin/, lib/,
       and doc/man in it. A subdirectory is expected under bin called
       $TARGET_REV this is for a unique programming environment.  If
       $TARGET_REV is not set the output of the command "systemtype -r" is
       used to create a directory.

       A number of libraries and options are defined for each programming
       environment so that all that is typically required to build and load a
       program is

             ccall $FILENAME

       You need to add any new programming environment to the script.

       "ccall -r" return a name that includes which Fortran compiler is
       available.

       "ccall -h" shows help.

       NAME.[f|F|c|f90|F90]
              Load a main program using the libraries and other common options
              used on various platforms (UNICOS, Tru64 Unix, HP-UX, AIX,
              SunOS, Solaris, ...)

       NAME.[ff|FF]
              Run .ff thru "uffp TESTPRG90 ..." and .FF thru "ufpp TESTPRG90
              -system" and then treat files as .F90 files.

       NAME.[html|HTML]
              If an HTML file is given; run through f2html to extract Fortran
              and then treat it as a .ff or .FF file.

              Then run it thru c2html and then treat any output file as a .c
              file.

       NAME.[1-8]|, NAME.[1-8],txt
              installs man(1) pages.  The files are compressed with gzip(1)
              and placed in the directory pointed to by $PUTMAN.

       NAME.[1-8]*.man
              Run file thru txt2man(1) to creat a *roff file and install the
              file as a man(1) page.

ENVIRONMENT
       PREFIX options before filename when loaded

       SUFFIX options after filename when loaded

       NOTTHEREONLY
              if TRUE, do not build if output file already exists

       CCALL_OS
              generic programming environment name. Defaults to output of
              "systemtype". Used to select compiler and loader options for a
              system.

       CCALL_COMPILER
              compiler-specific programming environment name. Defaults to
              output of "systemtype -r". Used to create subdirectory to place
              executables in in $CCALL_HOME/bin/. Selects additional compiler
              options specific to a particular compiler. $CCALL_OS identified
              the type of system you are on, $CCALL_COMPILER specified a very
              specific programming environment.

       CCALL_HOME
              top directory where output directors bin/, lib/, and doc/man
              exist defaults to $HOME.

       CCALL_LOG
              name of log file to create. By default no log is created

       PUT    directory to place binaries in (defaults to
              $CCALL_HOME/bin/$TARGET_REV)

       PUTMAN directory to place man pages in (defaults to
              $CCALL_HOME/doc/man)

       TMPDIR top directory where scratch files are generated. Defaults to
              /tmp

EXAMPLES
       Sample calls:

That defaults to specifying about twentyfive libraries so I just enter "ccall FILENAME" and it builds an executable and places in in the correct bin/ subdirectory (one for each programming environment) that I have used for a very long time and miss in any environment I do not have it in. Everything in netlib and the "real" GPF collection is predefined in the load path; and it preselects a compiler depending on which ones it finds in the path if no environmental variables are set. So I totally like the idea of a universal compiler command. We did a similar thing for years in a production environment where you just entered "f90" or "cc" so that batch jobs did not have to typically change when new environments were created. I have been thinking about that for a while and wondering about making it more "fpm-ish" where, especially assuming that profiles can be in the manifest files soon that you could have a universal compiler command that could use an fpm environment "remotely" from any directory that could specify a list of dependencies and compiler options. So something where an fpm directory could be used somewhat like modules but have waffled on whether I would want it to build the file where it is just using the information, or automatically create a cloned fpm package and if so whether it should all be in a scratch area that gets cleaned up after the build or if it creates and leaves the program as a package. It seems like a lot of the pieces are there. Maybe it sounds lazy, as I could new an "fpm new" and copy in my favorite fpm.toml file and the program file relatively easily, but trying to move more files to fpm I miss ccall the most, and was thinking the environment that you can create with fpm could be leveraged to set up a pre-defined load environment like ccall, and already has an install capability too. So basically, I think a "universal compiler" is great, and would be particularly useful in solving some of the issues fpm faces; but I also think there is something fpm can provide back to the universal compiler. So If I could set up an fpm package area with no packages in it and specify compiler options, load options, and a default install area and then use the universal compiler command pointed to that "empty" fpm package I would feel right at home and I think it would be better than ccall. I need to take some time to put the idea down more coherently, but this (#475) would go a long way towards that.

PS: ccall has been around maybe a bit too long -- I was just looking at it for the first time in a while and it still has branches for some OS environments that have not existed for a long time (anyone ever heard of COS and Aegis and SunOS?) but it shows how portable and long-lived a Fortran app can be).