How to get external libs provided to fpm in the right place?

I am trying to port the ncio package ( an overlay to the NetCDF library ) to fpm by providing external libraries through the toml file as follow:

name = "test_ncio"
link = ["netcdff","netcdf"]

(full setup is there: GitHub - dmr-dj/ncio: Simple Fortran interface to NetCDF reading and writing. , branch fpm)

When doing so, the generated compilation command by fpm is (on my system):

gfortran   -I/usr/include   -L/usr/lib/x86_64-linux-gnu build/gfortran_72880B597F4FEB11/ncio/test_main.f90.o -lnetcdff -lnetcdf build/gfortran_72880B597F4FEB11/ncio/libncio.a -o build/gfortran_4F14C1E13F387E09/test/test_ncio

and fails with an error message indicating that it cannot find the NetCDF libraries.

However, manually modifying the order of the command above to:

gfortran   -I/usr/include   -L/usr/lib/x86_64-linux-gnu build/gfortran_72880B597F4FEB11/ncio/test_main.f90.o build/gfortran_72880B597F4FEB11/ncio/libncio.a -o build/gfortran_4F14C1E13F387E09/test/test_ncio -lnetcdff -lnetcdf

results to a success.
This second version is much more inline with the usual ordering:

$(FC) -o $@ $(FFLAGS) $(LDFLAGS) $(FOBJ) $(LIBS)

Where LIBS are at the end.
Am I missing something in the setup of the fpm.toml file or is this gfortran specific?

For info, I am using:

Ubuntu 22.04.1 LTS / gcc version 11.3.0 (Ubuntu 11.3.0-1ubuntu1~22.04)

Thanks in advance for your kind help in this matter!

For a single-pass loader the caller should come first on the left so what you are seeing is wrong in most cases as the project library is very often the caller for external libraries instead of the main program so I agree the order you are seeing should change.

But I am seeing it in the correct order when I use the --verbose switch in my own packages.

So what does “fpm --version” show?

Can you do the fpm command that fails with --verbose added and show the messages that produces, including the specific error message?

You are saying it builds OK when you do the command directly, so it is probably not that you do not have the directory containing netcfd in your default load path, either because it is in the default system list or you placed it in a default location, or have the environment variables LIBRARY_PATH and/or LD_LIBRARY_PATH set up with the directory in it, or you might be using fpm(1) flags, etc. So need to know what fpm command options you are using, so make sure you include the fpm command you used.

After that, depending on your netcdf build, you might also have to include the hdf5 library in your “link=” directive and you might have to add a line like the following in your fpm.toml file as well:

  external-modules = [ "netcdf", "h5lt"]

So there are a few possibilities, but it can work. I use external libraries from fpm quite often. You already mentioned the ‘link=’ line so you are half-way there. If you can provide those details we might be able to tell you right off; otherwise someone will probably have to look at your package a little bit more.

Thank you very much for your feedback.

To provide more details in order:

I am using fpm version:

Version:     0.7.0, alpha
Program:     fpm(1)
Description: A Fortran package manager and build system
Home Page:
License:     MIT
OS Type:     Linux

I then first build the library as follow:

fpm build --flag "-I/usr/include" --link-flag "-L/usr/lib/x86_64-linux-gnu"

That succeeds without issue, output:

ncio.f90                               done.
ncio_transpose.f90                     done.
libncio.a                              done.
[100%] Project compiled successfully.

Then I try to build the test (part I was referring to yesterday) as follow:

fpm test --flag "-I/usr/include" --link-flag "-L/usr/lib/x86_64-linux-gnu" --verbose

I obtain the output here:
verbose-output-failed.txt (47.1 KB)

(too long to quote)
The command that fails is, as yesterday:

gfortran  -I/usr/include  -L/usr/lib/x86_64-linux-gnu build/gfortran_38303812D7ED7C73/ncio/test_main.f90.o  build/gfortran_38303812D7ED7C73/ncio/libncio.a -o build/gfortran_601BF29EB0732939/test/test_ncio

… and displacing the “-lnetcdff -lnetcdf” at the end of the line allows correct compilation (and correct run of the test).

I have tried to use the FPM_* environnement variables in replacement of the flags, but the results are identical to those posted here (as expected).

I also looked up to include the hdf5 library, but the nc-config only puts it in the “static” requirements. I thought maybe the includes for hdf5 were necessary for dynamic linking, so I tried adding “-I/usr/include/hdf5/serial” to the flags for fpm, but there was no difference to what is reported above. In other compilation cases I have done on that setup I never needed hdf5 to be explicitly added, so I doubt this could be the issue.

Thanks again for any further input!

Unfortunately, the link to the .txt file is not working so I cannot see the output. In this case, the -lnetcdff -lnetcdf is not showing up on the command you indicated failed; and I just changed to a new machine recently and had trouble building a new netcdff library and some of the links on the netcdf page are broken regarding Fortran. I need to get that built anyway but until I do I cannot try your package as-is.

But I use external libraries all the time without problem. So pullling down your project and switching to
the fpm branch I saw your fpm.toml was doing the link= specifically for a target; but mine all had it above
in the general section.

So if you move your link= line to the build section along with the external-modules I believe it will work.

The --link-flag value and target-specific link= directives are being expanded in the wrong place as you
noted and that needs corrected in fpm(1). When in the general build section it is placed at the end.

But I think that moving the link= line will get you around the problem in the meantime.

1 Like

Many thanks @urbanjost , moving the “link =” directive to the “build” section of the .toml file indeed fixes the issue. Quite unexpected, but thrilled to see this progressing!
Thanks again.