Cmake, MKL, and g++

I’m trying to compile lammps (repo develop branch) with cmake, using g++ and MKL. It correctly identifies the compiler (g++ and gfortran), and finds BLAS from MKL, but for the libraries it picks

-- Found BLAS: /opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_intel_lp64.so;/opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_sequential.so;/opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_core.so;-lpthread;-lm;-ldl  

which I believe is the correct set for the intel compiler, not for gnu: the first library should be mkl_gf_lp64.so instead.

Does anyone know how to control this, or more generally how to achieve the combination of compilers and libraries that I want?

LAMMPS depends entirely on the FindBLAS module of CMake for this. So you need to check with the CMake documentation: FindBLAS — CMake 3.10.3 Documentation
We require CMake to be at least of version 3.10. If you have a more recent version, you may check the documentation corresponding to your specific version for potential additional ways to influence the BLAS detection.

Looks like I can manually set BLAS_LIBRARIES to the string after Found BLAS: except replacing libmkl_intel_lp64 with libmkl_gf_lp64, and then the cmake output suggests that it’ll use them, but then I get a compile time error

[100%] Linking CXX executable lmp
/usr/bin/ld: warning: libmkl_gf_lp64.so.2, needed by liblammps.so.0, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libmkl_sequential.so.2, needed by liblammps.so.0, not found (try using -rpath or -rpath-link)
/usr/bin/ld: warning: libmkl_core.so.2, needed by liblammps.so.0, not found (try using -rpath or -rpath-link)
liblammps.so.0: undefined reference to `zgetri_'
liblammps.so.0: undefined reference to `zgemm_'

followed by many more undefined references.

CMake expects that you set the full path to libraries, if you provide them explicitly and usually you will use the file ending in .so and not .so.2.
If you don’t you may need to set both, LIBRARY_PATH and LD_LIBRARY_PATH for linking. The former works at link time, the latter at run time.

Thanks. I’ve reported the fundamental issue to the cmake discourse - we’ll see what they say.

I am giving it the names with full paths and without the “.so” numerical versions:

-D BLAS_LIBRARIES='/opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_gf_lp64.so;/opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_sequential.so;/opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_core.so;-lpthread;-lm;-ldl'

And the relevant MKL directory is in my $LIBRARY_PATH (it’s the only thing, in fact)

> ls -l $LIBRARY_PATH/libmkl_gf_lp64.so.2
-rwxr-xr-x 1 root root 17141720 Mar 11  2022 /opt/intel/oneapi/mkl/2022.1.0/lib/intel64/libmkl_gf_lp64.so.2*

Hmm. Looks like it wasn’t in LD_LIBRARY_PATH, and even though it’s compiling lmp, the way it’s including liblammps.so must be more like runtime, so apparently LD_LIBRARY_PATH was the relevant one.

This part of the workaround is now working. There’s still some libstdc++ issue, but if I can’t solve it I’ll start another thread, since I don’t think it’s related to MKL (if it is, I’ll follow up here).

For the record: findblas with MKL and gnu compilers - Usage - CMake Discourse

There’s still some libstdc++ issue, but if I can’t solve it I’ll start another thread, since I don’t think it’s related to MKL (if it is, I’ll follow up here).

Never mind. Looks like it was just a manifestation of my LD_LIBRARY_PATH being generally screwed up (which is also why the MKL dir was missing), so now that it’s fixed everything’s working now.

Thanks again, @akohlmey

Looks like FindBLAS is fine, and there’s a small issue with the LAMMPS cmake configuration. As you can see in CMake/FindBLAS.cmake at 4fc3f7e88ff7d5f734ed5d6cf43b6420e869ef19 · Kitware/CMake · GitHub FindBLAS knows about the correct library names, but it depends on some cmake Fortran-related variables being set. As a result, it is necessary to enable fortran before searching for blas. I think you just need to add enable_language(Fortran) before lammps/CMakeLists.txt at a001707b22e661fe49318429789a6efcd5a2e361 · lammps/lammps · GitHub

I’m happy to open a github issue or a PR, if that’s helpful at this point.

Fine may be an overstatement - one could argue that cmake’s BLAS interface shouldn’t require you to explicitly deal with fortran. But in my particular case, since I need BLAS for QUIP, there really is fortran code involved, so the addition of enable_language(fortran) seems reasonable.

It is not. We don’t want people to have to install a Fortran compiler, if they don’t need to use it.
Interfacing QUIP to the CMake build system is a bit of a crazy hack in the first place.

Not to mention, that the libAtoms source code contains outdated code (lbfgs.f) that cannot be compiled without trickery using modern Fortran compilers.

Well, what to do about it is entirely out of my hands, since I’m not in any sense in charge of either cmake or LAMMPS. I would like to point out, however, that this FindBLAS behavior will also affect the other LAMMPS packages that rely on BLAS. If you feel that FindBLAS’s behavior could be improved in this situation, obviously you could weigh in to the discourse or any issue that may eventually be opened.

Not really. You have to have code in Fortran for the difference in linkage to matter.
Also, in that case people can always favor the internal BLAS functions bundled with LAMMPS by using -D USE_INTERNAL_LINALG=yes. The difference in performance between MKL and these functions is rarely relevant.

To add insult to injury, now it no longer complains at link time even if it gets the wrong mkl variant. I have no idea what was going wrong initially, but this whole discussion is apparently moot.

I did learn some useful things, so I guess that’s something. Thanks for the help.