aradi / fypp

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

Feature: Print result directly to an output file in the *same directory* as the input file #38

Open aerosayan opened 8 months ago

aerosayan commented 8 months ago

Hello,

I'm trying to use Fypp with CMake build system, and faced an issue.

Fypp currently can be used as $ fypp src/Core/test.fpp src/Core/test.F90 which is nice, and simple.

But in a build system like CMake, I'm finding it difficult to extract the directory path to where the output file will be written.

This is mainly because I'm not very experienced in CMake's own weird language syntax.

But I'm thinking, shouldn't it be possible for fypp to just output the result in the same directory?

Adding such a feature will probably not be too complicated, and it will be helpful to everyone.

In best case scenario, it would be as easy to use as $fypp --output-in-source-directory --extension F90 src/Core/test.fpp

Where --extension F90 would be the user specified extension used to write the output file src/Core/test.F90

And --output-in-source-directory is a long form example of a command we can give to instruct fypp to write in the same directory as the source input file.

The commands are little bit verbose to show what I mean, and for better user experience, it might be better to shorten and simply them, as per your own wish.

Thanks.

aradi commented 8 months ago

Sure, in theory that would be possible. However, it would be redundant, as we you can do the same with the current syntax already, as you have shown above. To me, you're problem seems more some difficulty to handle CMake. By the way, if you were using the syntax like suggested above in a CMake build environment, the build would probably fail, as CMake would not find the generated .F90 file, as they would be somewhere else, not where CMake expects them. (Actually, the .F90 files are generated in appropriate subfolder in the build folder. If you use make as build tool in CMake, try to issue make VERBOSE=1 to obtain detailed information, about the command line parameters CMake passes to the various tools.)

aerosayan commented 8 months ago

Also, your cmake documentation has a bug.

https://fypp.readthedocs.io/en/stable/fypp.html#cmake

In the code given on the fypp website,

    # Custom command to do the processing
    add_custom-command(
        OUTPUT "${outfile}"
        COMMAND fypp "${infile}" "${outfile}"
        MAIN_DEPENDENCY "${infile}"
        VERBATIM)

add_custom-command is wrong, and should be add_custom_command.

It took me some time to find this, as the - is almost invisible.

aradi commented 8 months ago

add_custom-command is wrong, and should be add_custom_command.

Great, indeed. I've fixed that now on main, it will be updated in the stable documentation at the next release. Thx for spotting it!

aerosayan commented 8 months ago

Thanks!

Also, another bug is that, the CMake script needs the --create-parents flag for fypp.

Otherwise the files aren't generated.

I made some modifications to the CMake code, and maybe I will improve it in future.


#
# Fypp Source
#

# Manually set the filenames
# NOTE: GLOB_RECURSE based search would be better to find the files,
# However, it creates absolute path names, which makes it little bit difficult to process later on.
# If someone can do this, with GLOB_RECURSE, it'd be nice.
set(fppFiles
  src/Core/testFypp.fpp
)

# Pre-process using Fypp
foreach(infileName IN LISTS fppFiles)

  # Generate output file name
  string(REGEX REPLACE ".fpp\$" ".F90" outfileName "${infileName}")

  # Create the full path for the new file
  # Store the output files in <build>/out/ directory, to keep the build directory clean and organized
  set(outfile "${CMAKE_CURRENT_BINARY_DIR}/out/${outfileName}")

  # Generate input file name
  set(infile "${CMAKE_CURRENT_SOURCE_DIR}/${infileName}")

  # Custom command to do the processing
  # Use --create-parents flag to create the directories required to store the output files
  add_custom_command(
    OUTPUT "${outfile}"
    COMMAND fypp --create-parents "${infile}" "${outfile}"
    MAIN_DEPENDENCY "${infile}"
    VERBATIM)

   # Finally add output file to a list
   set(outFiles ${outFiles} "${outfile}")

endforeach(infileName)

testFypp.fpp

#:for dtype in ['integer', 'real']
  pure elemental function Fypp_Max3_${dtype}$ (a,b,c) result(ans)

    ${dtype}$,intent(in) :: a,b,c
    ${dtype}$ :: ans

    ans = max(a,b,c)
  end function
#:endfor
aradi commented 8 months ago

Also, another bug is that, the CMake script needs the --create-parents flag for fypp.

IMO the need for the --create-parents option in your case is more due to the fact that you use CMake in a rather non-conventional way. We are using fypp in a large project (DFTB+) and do not use this option at all. I also know about other projects, which used Fypp with CMake successfully way before this option was added (due to a user request).