Search code examples
gcclinkergfortranlapacklapacke

Is it possible to link LAPACK, LAPACKE, and BLAS libraries with GCC instead of GFORTRAN?


I have an application that is written in C. I would like to use the LAPACK library to do some linear algebra calculations. I am using LAPACKE, which is the C interface to LAPACK. The C code compiled fine with GCC, but I am having trouble linking the libraries with GCC. It only works with GFORTRAN. I downloaded the lapack-3.11.0.tar.gz file from the LAPACK website. I unpacked the file then I built it. I did not make any changes to the make.inc.example file, which was already configured for a linux machine running GNU compilers. Here is how I built it once in the ~/lapack-3.11.0 directory:

cp make.inc.example make.inc
make

LAPACK built successfully and all of the tests passed. Then, I built LAPACKE. To do this, I simply ran make in the ~/lapack-3.11.0/LAPACKE directory. Similarly, it built successfully and all of the tests passed. Notice that in my case, LAPACK is installed in my home directory and not in a system directory.

To test that I could actually use LAPACKE, I wrote a sample C program that solves a system of equations using LAPACKE_dgesv().

lapack_test.c:

#include <stdio.h>
#include <lapacke.h>

int main()
{
        int n = 3;
        int nrhs = 1;
        int lda = n;
        int ipiv[n];
        double a[9] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 10.0};
        double b[3] = {3.0, 3.0, 4.0};
        int info;

        info = LAPACKE_dgesv(LAPACK_ROW_MAJOR, n, nrhs, a, lda, ipiv, b, nrhs);

        if (info == 0)
        {
                printf("Solution: %f %f %f\n", b[0], b[1], b[2]);
        }
        else
        {
                printf("dgsev failed with error code %d\n", info);
        }

        return 0;
}

Assuming that lapack_test.c is in my home directory, here is how I compiled it and linked the libraries:

gcc -I./lapack-3.11.0/LAPACKE/include -c -o lapack_test.o lapack_test.c 
gfortran -o lapack_test lapack_test.o ./lapack-3.11.0/liblapacke.a ./lapack-3.11.0/liblapack.a ./lapack-3.11.0/librefblas.a

This gave my no errors. However, GFORTRAN is very inconvenient for my case. In my application I have many C libraries that probably will not link using GFORTRAN. Or at least, I do not think that that they will.

If I use GCC, I get linkage errors. For example, if I simply replace GFORTRAN with GCC in the last step I get a bunch of errors:

/usr/bin/ld: ./lapack-3.11.0/liblapack.a(iparmq.o): in function `iparmq_':
iparmq.f:(.text+0x25e): undefined reference to `logf'
/usr/bin/ld: iparmq.f:(.text+0x26b): undefined reference to `lroundf'
/usr/bin/ld: ./lapack-3.11.0/liblapack.a(xerbla.o): in function `xerbla_':
xerbla.f:(.text+0x55): undefined reference to `_gfortran_st_write'
/usr/bin/ld: xerbla.f:(.text+0x60): undefined reference to `_gfortran_string_len_trim'
/usr/bin/ld: xerbla.f:(.text+0x77): undefined reference to `_gfortran_transfer_character_write'
/usr/bin/ld: xerbla.f:(.text+0x87): undefined reference to `_gfortran_transfer_integer_write'
/usr/bin/ld: xerbla.f:(.text+0x8f): undefined reference to `_gfortran_st_write_done'
/usr/bin/ld: xerbla.f:(.text+0x9a): undefined reference to `_gfortran_stop_string'
collect2: error: ld returned 1 exit status

Seems to be linking the static library liblapacke.a with no errors. liblapack.a seems to be where the errors are. It is a FORTRAN library, so it makes sense why it would not link correctly using GCC.

Is there a workaround here? Is it worth using LAPACKE? Or, should I try some other way to interface between FORTRAN and C?


Solution

  • There is no difference in linking else than some libraries being added automatically. gfortran and gcc do the same when linking. Only gfortran links some libraries like libgfortran or libm automatically while with gcc you have to use -lgfortran or -lm. Otherwise they do the exact same thing.

    You can even use the gcc command to compile Fortran code and the gfortran command to compile C code. Or C++ code. It really does not matter. Just link all the necessary library when linking, depending whether you link with gcc, gfortran, g++ or ld.

    In the end the linking is always done by ld, just with some particular flags added by the compiler command.

    Finally, to be precise, distinguish GCC, the GNU compiler collection, and gcc, the command that calls the C frontend or the GCC's C compiler. The gfortran command calls the Fortran frontend. They share the same backend and middlend. When you call, e.g. gcc test.f90, the command recognizes that it is a Fortran source file and will invoke the Fortran frontend for you.