fortran-lang / fpm

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

A proposed "metadata" command to include metadata from the TOML configuration file in a Fortran-readable format #252

Open urbanjost opened 3 years ago

urbanjost commented 3 years ago

Something I miss using fpm(1) versus my own tools is being able to provide metadata to the Fortran files directly such as the build time, compiler version used (which some compilers can now provide via Fortran intrinsics), the version number and such. Essentially if there were a command that converted the TOML metadata into PARAMETER statements each time the build command were used you would have much the same functionality available. Packages past and present such as sccs(1) provided some way to do this but (unless I missed it) git(1) does not. I am not suggesting this is high priority for fpm(1) but would like it discussed and added to the list as appropriate. If an INCLUDE file could be generated automatically or via a subcommand it would be much easier to include correct version and license information in programs without having to edit the code files or a manual editing of an include file it is so often easy to overlook changing the build date or version in.

awvwgk commented 3 years ago

Sounds like a good idea, having to maintain redundant information in different places is really error prone. For meson and CMake I use configure_file to insert build system meta data as parameter into Fortran source code. I very much in favour of having a configure_file or similar option for fpm as well.

ivan-pi commented 3 years ago

@awvwgk is a configure_file in your case a Fortran include file? Nevermind, I see configure_file is essentially a preprocessor mechanism.

Would there be any advantages to doing this with a (read-only) namelist or maybe having a public fpm_tools module which contains some functions and subroutines to recover such meta-data from some cached build/toml files?

awvwgk commented 3 years ago

Preferably we keep in line with existing configure_file implementations as present in CMake and meson instead of making up our own: https://mesonbuild.com/Configuration.html. In a multi-build system approach one might want to use the same template for fpm, CMake and meson and get the same result independent of the build system used.

ivan-pi commented 3 years ago

Can you point me to a Fortran example of yours in a public repository? I still have trouble grasping if the concept relies upon use of the cpp/fpp preprocessor or are the input files preprocessed independently by CMake/meson.

Is the following a valid setup example?

I have a template file called projconfig.fi.in, containing

character(*), parameter :: version = "@FPM_VERSION_STR@"
integer, parameter :: version_major = @FPM_VERSION_MAJOR@
integer, parameter :: version_minor = @FPM_VERSION_MINOR@
integer, parameter :: version_bugfix = @FPM_VERSION_BUGFIX@

In the manifest file of the project, we then specify this as a target for configuration, with the actual preprocessing/replacement done by an extension to fpm or a special command. The template substitution rules would follow the same definitions as CMake and Meson.

Finally in the main module of my project, I can include the configured template file as:

module myproject

  include "projconfig.fi"

end module
awvwgk commented 3 years ago

For an example see:

https://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.name.in https://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.f90#L43

I made a small implementation here when working on the fpm-dist command

https://github.com/fortran-lang/fpm/blob/e2a837b/fpm/src/fpm/dist/meson.f90#L433-L473

ivan-pi commented 3 years ago

For an example see:

https://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.name.in https://github.com/MarDiehl/stdlib_os/blob/c03a636/src/os.f90#L43

Interesting, if stdlib-os currently relies upon this configuration mechanism, and we want fpm to rely upon on stdlib-os in the future to get the operating system ID, does this mean that to bootstrap fpm using the Haskell version, it is necessary to use the current build-script feature (using CMake) or extend the Haskell version to support OS identification and configure file template substitution? This reminds me of the movie Inception...

awvwgk commented 3 years ago

You can just cut the loop short and drop Haskell fpm from it, with support for configure_file in Fortran fpm we are already fine to dependent on stdlib_os once it is ported to fpm. No need to make life more complicated than necessary, just look for changeable parts were changes are simple to make.

urbanjost commented 3 years ago

As a simpler scheme that leverages some of the existing fpm components and required user knowledge, and does not require a preprocessor I would propose something like this:
o fpm parses the fpm.toml file (which it already does) and obtains the version number and other metadata such as the project name and author. It then gets the compiler name from the command line, and the current time, and possibly the compiler options and the OS type. o the build commands could add a -D $OS_TYPE and -D $COMPILER option or equivalent to the compiles, which I think all major compilers support for use with cpp/fpp or their equivalent. o using the metatadata it writes and compiles a module called fpm_metadata that creates a type of METADATA.

This could be ignored by the fpm user, but if desired they could include "use fpm_metadata, only : metadata" in their program and then get to at least a standard set of keywords by using such things as:

write(*,*)'VERSION',metadata%version
write(*,*)'COMPILE_TIME',metadata%compile_time

and so on. As more functions become available (via stdlib, preferably) such things as the equivalent of the output of a uname(1) command could also become default behavior.

This would require no preprocessing of the user code, supply a standard set of variables that could be used by all packages, and allow for standard names to be used in preprocessing and leverage the existing TOML configuration file and syntax. Since the existing code already parses the TOML file and it already contains some of the most common metadata such as the version number this would fit into the existing fpm quite naturally, I believe.

The drawback to the user would be that no such module would exist outside of fpm. So adding -DFPM to the build lines would allow for #ifdef FPM to be used as a preprocessor directive, and leaving the built code in build/ for the user to grab or use as a template for a build outside of fpm(1) would be desirable.