- Name : Arteev Raina
- Organization : Fortran-lang
- Project : fpm-ize the Fortran ecosystem
- Mentors : Sebastian Ehlert, Milan Curcic
- Discourse Profile : Profile
Fortran Package Manager is a build system and a package manager for Fortran projects.
My project motive was to fpm-ize the Fortran Ecosystem by making the packages that are available in the Fortran Ecosystem fpm compatible. So, we had two ways to achieve this objective one was to work on the packages directly and change the code there but on the other hand we had another way to implement new features inside fpm only and lower the bar for the packages that use preprocessing extensively to get fpm compatible. So, I took up the problem to implement preprocessing support in Fortran Package Manager during the first week of community bonding itself so that I have enough time in understanding the project and its requirements.
This was the first task that I took up while implementing preprocessing support inside fpm. The completion of this feature enabled the fpm users to add a table in their manifest file and define the preprocessor configuration.
[preprocess.cpp]
suffixes = ["F90", "f90"]
directories = ["src/feature1", "src/models"]
macros = ["FOO", "BAR"]
The preprocess_config_t
that is the type for preprocessor table defined in fpm.toml
has the following member variables.
!> Configuration meta data for a preprocessor
type :: preprocess_config_t
!> Name of the preprocessor
character(len=:), allocatable :: name
!> Suffixes of the files to be preprocessed
type(string_t), allocatable :: suffixes(:)
!> Directories to search for files to be preprocessed
type(string_t), allocatable :: directories(:)
!> Macros to be defined for the preprocessor
type(string_t), allocatable :: macros(:)
In this task, I implemented the feature in fpm to add C Preprocessing flag if cpp preprocessor table is defined in fpm.toml
file. The necessary condition inside the subroutine set_preprocessor_flags
which handles this is as follows :
do i = 1, size(package%preprocess)
if (package%preprocess(i)%name == "cpp") then
flags = flag_cpp_preprocessor// flags
exit
end if
end do
In this way, fpm user can avoid passing the cpp preprocessor flag using command line like this
fpm build --flag "-cpp -DFOO"
In the first task, as I had already added the ability to define the macros inside the preprocessor table. So, now in this task I added the feature in fpm to parse and read those defined macros in the manifest and pass them as flags in the command for compilation of the files.
We can also define the valued macros in the manifest and also reuse value like Version number from the manifest as a value for a particular macro.
version = "1"
[preprocess]
[preprocess.cpp]
macros=["FOO", "-BAR=2", "VERSION={version}"]
While implementing this feature, I along with my mentors identified a specific problem with the implementation of macros parsing. The problem was that macro definition were made global and that would have created undesirable results in large projects as these macro definitions were passing to the dependencies of the current project as well. Therefore, we decided to keep these macros definitions local to the package type.
!> Type for describing a single package
type package_t
!> Name of package
character(:), allocatable :: name
!> Array of sources
type(srcfile_t), allocatable :: sources(:)
!> List of macros.
type(string_t), allocatable :: macros(:)
!> Package version number.
character(:), allocatable :: version
end type package_t
My next objective that I decided with my mentors was to add fypp
support inside fpm as it would allow us to compile stdlib
using fpm.
Fypp
is a Python powered Fortran Preprocessor that stdlib uses and as of now fpm does not support fypp
so we could not compile stdlib
using fpm
.
In this script, we added fypp preprocessing on demand. Fpm can invoke this script by passing the path to the script file in the --compiler
flag.
fpm build --compiler "$PWD/fypp-gfortran.py"
We faced multiple problems while using this script to compile stdlib
. These include:
- Macros defined in the manifest were not available while compiling tests.
This was a quick fix as I was not adding macros while fpm was building target list specifically for the type FPM_UNIT_PROGRAM
.
case (FPM_UNIT_PROGRAM)
call add_target(targets,package=model%packages(j)%name,type = FPM_TARGET_OBJECT,&
output_name = get_object_name(sources(i)), &
source = sources(i), &
macros = model%packages(j)%macros, &
version = model%packages(j)%version)
- Tests in the stdlib used functions that were defined in C++ files and fpm could not compile C++ files.
- We were not skipping some tests defined in
test_mean_f03.fypp
if the supported MAXRANK was not provided.
While compiling stdlib
tests using fpm
wrapper script I discovered that some of the functions referenced in the test files were defined in the C++ files and fpm is not able to compile the C++ files and properly link them. So, I worked on adding the C++ compilation support and with proper linking we were able to compile the tests which uses C++ files inside the stdlib
.
In order to compile the stdlib we had to modify its structure a bit in order to get the files in source directory, the tests and the example directory directly compiled using fpm with the help of compiler wrapper script using fypp
.
These changes include :
- Adding project specific
fpm.toml
file.
name = "stdlib"
[dev-dependencies]
test-drive.git = "https://github.com/fortran-lang/test-drive.git"
[build]
auto-examples = false
auto-tests = true
[preprocess.cpp]
macros = [
"PROJECT_VERSION_MAJOR=0",
"PROJECT_VERSION_MINOR=1",
"PROJECT_VERSION_PATCH=0",
"MAXRANK=4",
]
-
Renaming submodules with same names & moving the
common.fypp
file inside include directory. -
Skipping the tests inside
test_mean_f03.fypp
whenMAXRANK
was not greater than 7.
-
The compiler wrapper script inside
fypp-gfortran.py
is still a temporary solution for addingfypp
support in the fpm. In long term, we have planned to inject this script insidefpm
andfpm
should be able to handle thefypp
preprocessing on its own without any external wrapper script. -
Hashing of included files to detect changes.
-
Support for C++ modules.
Pull Request | Description |
---|---|
Added Basic Preprocess Table Configuration #715 |
|
Ability to parse and read macros from manifest #720 |
|
Added Compiler Wrapper script for Preprocessing using fypp #729 |
|
Added support for C++ files compilation #733 |
|
Structural Change in Stdlib #675 |
|
Added Documentation for Preprocess Table #60 |
|
Updated Example Readme #740 |
|
Remove unnecessary space in fpm new cmd #684 |
|
Remove extra space from help-test cmd #686 |
|
Week | Blog Links |
---|---|
Week 1 (23-05-2022) |
# Blog 1 |
Week 2 (30-05-2022) |
# Blog 2 |
Week 3 (06-06-2022) |
# Blog 3 |
Week 4 (20-06-2022) |
# Blog 4 |
Week 5 (27-06-2022) |
# Blog 5 |
Week 6 (04-07-2022) |
# Blog 6 |
Week 7 (11-07-2022) |
# Blog 7 |
Week 8 (18-07-2022) |
# Blog 8 |
Week 9 (25-07-2022) |
# Blog 9 |
Week 10 (01-08-2022) |
# Blog 10 |
Week 11 (08-08-2022) |
# Blog 11 |
Week 12 (15-08-2022) |
# Blog 12 |
Week 13 (22-08-2022) |
# Blog 13 |
Week 14 (29-08-2022) |
# Blog 14 |
Week 15 (05-09-2022) |
# Blog 15 |
Week 16 (11-09-2022) |
#Blog 16 |
Link to the Weekly Meeting Notes.
I would like to thank my mentors Sebastian Ehlert, Milan Curcic, Laurence Kedward, Jeremie Vandenplas, Zoziha and other community members as well because of their support I was able to progress and complete my objectives. They also helped me in understanding some crucial parts of Fortran code whenever I felt stuck while solving issues. They always responsded to my queries whether it was related to code or anything related to program. While contributing to this project, I learned a lot about writing Fortran, writing maintainable and clean code. I look forward to keep contributing to the project even after the completion of GSoC program because of great learning experience that I have had while contributing to this organization and will continue to have.