Open urbanjost opened 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.
@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?
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.
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
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
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...
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.
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.
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.