aradi / fypp

Python powered Fortran preprocessor
http://fypp.readthedocs.io
BSD 2-Clause "Simplified" License
180 stars 29 forks source link

Using fypp through the Intel Fortran compilers #24

Open ivan-pi opened 1 year ago

ivan-pi commented 1 year ago

The Intel compilers provide a flag -fpp-name=<name> which can be used to specify an alternative preprocessor of the form:

alt_fpp [ [–D<define>]..] [[-I<include directory>]..] inputfile 

which prints output to STDOUT that will get captured by the compiler for further processing.

I've tried to use this with fypp, but I run into errors:

$ ifx -fpp-name=`which fypp` -DNAME=\"Ivan\" fypp_example.F90 
error: Failed to open file '@/tmp/ifxargBf8BjW' for read [FyppFatalError]
error: [Errno 2] No such file or directory: '@/tmp/ifxargBf8BjW' [FileNotFoundError]
$ ifx -fpp-name=fypp -Qlocation,fpp,/home/ivan/.local/bin -DNAME=\"Ivan\" fypp_example.F90 
error: Failed to open file '@/tmp/ifxarg6DL4Me' for read [FyppFatalError]
error: [Errno 2] No such file or directory: '@/tmp/ifxarg6DL4Me' [FileNotFoundError]

It seems like the compiler prepends @ to the path, but otherwise it seems it could work. If you'd like to experiment, here is the toy code:

! fypp_example.F90
#:def hello(name)
print *, "Hello ${name}$"
#:enddef

#:if defined('NAME')
$:hello(NAME)
#:else
print *, "Hello World"
#:endif
end

Do you have any previous experience with such usage, or should I raise an issue at the Intel Fortran forum?

aradi commented 1 year ago

I had a look at it with a toy bash script as pre-processor. The ifort option seems to work somewhat differently from what is documented. It writes all the command line arguments it wants to pass to the pre-processor (including the source file name) into a file, and passes that file, prefixed with @ to the pre-processor. The pre-processor is supposed to recognize the @ prefix and treat the content of the file as command line arguments. While GNU cpp seems to be capable to do so (although, I did not find this feature anywhere documented), fypp is currently not.

One could, in theory, implement the same feature in Fypp (one would have to parse sys.argv before optparse sees it) and pass the extracted list of arguments to optparse. But first, it would be good to know, that this is the intended long term behavior of the ifort compiler...

ivan-pi commented 1 year ago

So it actually uses response files? They were added also to GCC to support Windows platforms where command-line length limits exist. I small test on MacOS shows response files work here too:

ivan:~/fortran/legacy$ cat debug
-Wall -Werror -g
ivan:~/fortran/legacy$ gfortran @debug -v loop_cycle.f 
Driving: gfortran -Wall -Werror -g -v loop_cycle.f -mmacosx-version-min=12.5.0 -asm_macosx_version_min=12.5 -nodefaultexport -l gfortran -shared-libgcc
...

My initial goal was to write an ifort command wrapper or perhaps simply a configuration file to get a "natural" experience of using the fypp preprocessor without a separate generation step. While non-portable to some extent, it simplifies the writing of build-system files. (Since our cluster has Intel CPUs dominantly, the Intel Fortran compiler is the de-facto standard one, hence I'm willing to sacrifice portability for a nicer developer experience.)

ivan-pi commented 1 year ago

I thought I'd mention that fpm on Windows also uses response files in the archiver and linker commands: https://github.com/fortran-lang/fpm/issues/427. Given that fpm is in the process of adding a fypp wrapper (https://github.com/fortran-lang/fpm/pull/729) it might become an issue for fpm sooner or later.

ivan-pi commented 1 year ago

I've opened an issue about the undocumented behavior at the Intel Fortran Forum: https://community.intel.com/t5/Intel-Fortran-Compiler/Undocumented-behavior-of-fpp-with-alternative-preprocessor/m-p/1411981#M162675

ivan-pi commented 1 year ago

One of the moderators replied that the documentation will be amended. The exact layout of the response file remains somewhat under-specified for my taste. More information can be found here:

The GCC mail archives state the contents of the file are whitespace-separated strings. Presumably, this would mean the separator between option strings are all the tokens recognized by the C library function isspace.