Fpm version 0.7.0 released

Sorry for being such a dumbhead but I still do not get whether (and how) one could install a library (or a module) for future use with fpm. AFAIU, all dependencies added to fpm.toml file are resolved, downloaded and built inside the project tree, so if I create another project and add, say, stdlib as a dep, it will be redownloaded and rebuilt. Unless I miss something important, this does not make much sense to me.

2 Likes

The reason not to reuse dependencies between projects is that dependencies vary across several dimensions; namely version, compiler, compiler version, compiler flags, their dependency versions, etc. Note that there are compatibility issues between compilers, possibly even compiler versions and compiler flags, not to mention the likely compatibility issues between package versions. We could cache and organise all of the used packages along these various dimensions, but the gains haven’t quite seemed worth the effort as of yet.

2 Likes

If you have several projects using a fpm library, you can also use in their fpm.toml manifests the local path instead of the GitHub URL:

[dependencies]
that_lib = { path = "../that_lib" }

In that case, it will be up to you to fix the eventual problems presented by @everythingfunctional
(of course it could be a problem for other persons if you push that on GitHub)

Since the Linux world pretty much runs on external libraries they are not all bad. There are problems with them that fpm tries to avoid; but that of course creates its own complications.
Hopefully, being able to set file-specific compile options and user-defined profiles will be incorporated into fpm soon; but that is a major fpm limitation currently.

So fpm does support external libraries and modules; just not in the most user-friendly way;
partially intentionally. If you are familiar with bash(1) perhaps this simple QA script will help.
If you are not familiar with Linux it will probably be more confusing to read it than to not :>
`

bash(1) test using external libraries
#!/bin/bash
########################################################
SETUP(){
#
# Suppose you create two projects. Project A builds some code
# you would like to place into a collection of external resources
# to be used by any projects, not just fpm projects.

fpm new /tmp/A --src

# edit the fpm.toml manifest to allow library installation
cd /tmp/A
sed -i -e 's/library = false/library = true/' fpm.toml

# assume the default location is OK ($HOME/.local/include
# and $HOME/.local/lib); see "fpm help install" for other
# options:
fpm install
# this should have placed a.mod and libA.a in an external
# location. The files in /tmp/A will not be used any further

# Now make project B, which is going to use project A as an
# external system library; not as an fpm project.

fpm new /tmp/B
cd /tmp/B

# In the [build] section add the library link= and module external-modules= lines

sed -i -e '\%\[build\]%{
alink=["A"]\
external-modules=["a"]
}' /tmp/B/fpm.toml

# so now the build section should start out like this
#     [build]
#     link=["A"]
#     external-modules=["a"]
#        :
#        :

# now make the program in project B call the external library and module
cat > /tmp/B/app/main.f90 <<\EOF
program main
use A,only: ha=>say_hello  ! use external module, not anything in /tmp/A
use B,only: hb=>say_hello  ! use a regular project module
  implicit none

  print *, "hello from project B"
  print *, "now call the external library with module A in it"
  call ha()
  print *, "now call the project library with module B in it"
  call hb()
end program main
EOF
}
########################################################
BASIC(){
# You have to tell where the library and mod files are with flags on the fpm command.
cd /tmp/B
fpm run --link-flag "-L$HOME/.local/lib" --flag "-I$HOME/.local/include" --verbose
}
########################################################
ENV(){
# you can make that easier with a response file, or setting environment variables
# like LIBRARY_PATH, LD_LIBRARY_PATH, the FPM_* variables.

# usually for static libraries
export LIBRARY_PATH=$HOME/.local/lib:$LIBRARY_PATH
# usually for dynamically loaded libraries
export LD_LIBRARY_PATH=$HOME/.local/lib:$LD_LIBRARY_PATH

# not used by all compilers, allows specifying include directories
export CPATH=$HOME/.local/lib:$CPATH
export FPATH=$HOME/.local/lib:$FPATH

cd /tmp/B
fpm run --flag "-I$HOME/.local/include"  --verbose
}
########################################################
FPM_ENV(){
# the FPM_* variables.
                   
# FPM_FC            sets the path to the Fortran compiler used for the build,
# FPM_FFLAGS        sets the arguments for the Fortran compiler
# FPM_LDFLAGS       sets additional link arguments for creating executables
#
# FPM_AR            sets the path to the archiver used for the build,
#
# FPM_CC            sets the path to the C compiler used for the build,
# FPM_CFLAGS        sets the arguments for the C compiler
# FPM_CXXFLAGS      sets the arguments for the C++ compiler
# FPM_CXX           sets the path to the C++ compiler used for the build,

export FPM_FFLAGS="-I$HOME/.local/include"
export FPM_LDFLAGS="-L$HOME/.local/lib" 

cd /tmp/B
fpm run  --verbose
}
########################################################
TEARDOWN(){
rm -rfv /tmp/A /tmp/B
}
########################################################
(
exec 2>&1
TEARDOWN
SETUP
banner BASIC
BASIC
banner ENV
ENV
banner FPM_ENV
FPM_ENV
TEARDOWN
)|tee /tmp/$(basename $0).log
########################################################
exit