I am trying to compile the GitHub FortLearner project, which has many machine learning algorithms.
On Windows, running the command make main in the directory benchmark\covariance I get errors such as
c:/equation/bin/../lib/gcc/x86_64-w64-mingw32/12.0.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find ./mod/mod_const.out: No such file or directory
c:/equation/bin/../lib/gcc/x86_64-w64-mingw32/12.0.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find ./mod/mod_common.out: No such file or directory
c:/equation/bin/../lib/gcc/x86_64-w64-mingw32/12.0.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find ./mod/mod_timer.out: No such file or directory
c:/equation/bin/../lib/gcc/x86_64-w64-mingw32/12.0.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find ./mod/mod_random.out: No such file or directory
Maybe I was supposed to use another makefile first, but I don’t know which one. I raised an issue two weeks ago, but the author has not replied.
After a quick glance over the project, I thought it might be easy enough to just give fpm a try. Looks like the project is doing templating by using include files, those should be possible with fpm, but must not end with f90 due to the automatic source detection.
Here is what I did to transform the code to give fpm a try (sorry for the mess):
❯ git clone https://github.com/NaoMatch/FortLearner && cd FortLearner
# Create boilerplate package manifest
❯ cat > fpm.toml <<EOF
name = "FortLearner"
[library]
source-dir = "."
EOF
# Get all top-level directories
❯ ls -d */ | awk '{gsub("/",""); print " \""$0"\","} BEGIN {print "include-dir = ["} END {print "]"}' >> fpm.toml
# Find all include files and rename them in the directory tree
❯ fd '\.f90' */include | awk '{print $1, $1".in"}' | xargs -n 2 git mv
# Find all include directives and rename the included files
❯ rg "\.f90\"" -l | xargs sed -i "s/\.f90\"/.f90.in\"/"
# This C file seems to be broken, but not used anywhere
❯ mv ./benchmark/minmax/sum_up_gt_matrix.c{,-ignore}
# Now give it a try, project uses long lines and C preprocessor for f90 files
❯ fpm build --profile debug --flag "-cpp -D_x86_64 -ffree-line-length-none"
Took me way too long to figure all those commands out .
I usually use fd and rg as alternatives to find and grep in case you wonder what those are.
There are no executables linked yet of course, next step would be to sort out where the programs are located and move them to an app or example directory to have fpm auot-detect them, while collecting the rest of the directories in a src folder and cut down the boilerplate package manifest again.
Thanks. Under WSL I installed fd and rg and followed the instructions up to the line above. When I run the command I get a text-based interface for FD asking me to type a command. What it is supposed to do is rename all the .f90 files that appear in include statements with .f90.in and then changing the include statements to reflect the new names? If I can do this some other way I will try the rest of the script.
An alternative to changing the file extensions is to move all the included files into a top-level include folder - fpm will not search this folder for source files, but it will be supplied as an include path to the compiler if it exists. (Apologies, I now realise this behaviour is not documented anywhere.)
See also library.incude-dir for specifying custom include directories (these can’t reside in the main source folders).
does produce executables. The data files that the programs read are not included in the repo. Looking at the readme.md, the author has found his Fortran algorithms to be faster than those in the popular scikit-learn Python machine learning library. I think the data files can be generated using scikit-learn.
The codes are written in an object-oriented manner. To a Luddite Fortran-95-er like me, it appears that the codes which actually compute something are mixed with many codes defining the framework.
If a machine learning framework in Fortran can be created that is as easy to use, understand, and modify as scikit-learn, and which can be run interactively via LFortran, that would be a selling point for Modern Fortran.