LFortran: linking to a C library

I have a Fortran program that interfaces a C function, say fooFunc(), which is available in a C library installed on my system, say foolib. In the Makefile I have LDLIBS = -lfoolib. The program compiles and runs as expected in gfortran. In LFortran, the program compiles but linking fails saying

undefined reference to `fooFunc'

meaning the linker cannot “see” foolib for some reason, even though it is located in the default LIBDIR, which of course is in the PATH. I added LDFLAGS = -L/usr/lib64 (the correct LIBDIR,) just in case - no dice, still won’t link. The only way to link it is to explicitly add the library in the linking phase together with the object files the compiler made, i.e. something like

lfortran  $(OBJS)  /usr/lib64/libfoo.so  -o  $(EXE)

This works, and the resulting executable gives the correct output. That alone is great progress, but I don’t understand why the typical -lfoolib doesn’t work, and I must explicitly link the library. What am I doing wrong here?

1 Like

This should work. We use Clang or GCC to do the linking and we pass through the -l options. Since it doesn’t work for you, I opened up an issue at Issues with linking a shared library using the `-l` option · Issue #2947 · lfortran/lfortran · GitHub to debug this and fix this.

Thank you @certik. I wasn’t sure this was a bug, I assumed I was missing something, so I posted a question here first.

On a related subject, would it be possible or even desirable for LFortran to inline C or other languages?

For example with C code:

program test
use iso_c_binding
implicit none

integer(c_int), parameter :: n=100
integer(c_int) :: i,j
real(c_float) :: arr(0:n-1),temp

call random_number(arr(:))

arr(:)=2*(arr(:)-1)

inline_c

for (i = 0; i < n - 1; i++) {
  for (j = 0; j < n - i - 1; j++) {
    if (arr[j] > arr[j + 1]) {
      temp = arr[j];
      arr[j] = arr[j + 1];
      arr[j + 1] = temp;
    }
  }
}

end inline_c

print *,arr

end program

…or assembly:

program test
implicit none
integer n
real(8) dot
real(8), allocatable :: a(:),b(:)


n=1000
allocate(a(n),b(n))

call random_number(a(:))
call random_number(b(:))


inline_asm

vmovaps zmm0, zmmword ptr [a]
vmovaps zmm1, zmmword ptr [b]

mov ecx, n

.loop:
  vmulpd zmm2, zmm0, zmm1
  vaddpd zmm3, zmm2, zmm2
  vaddpd zmm2, zmm3, zmm3

  add ecx, 8

  vmovsd xmm4, zmm2, xmm0
  vaddpd zmm0, zmm0, zmm4

  cmp ecx, 16
  jne .loop

vmovsd dot, xmm0

end inline_asm


print *,dot

end program

It doesn’t fit with the Fortran ethos, but it may be useful in certain circumstances for optimization, interfacing to libraries or system-level coding.

With gcc the -flto option allows for C functions to be inlined where appropriate. Optimize Options (Using the GNU Compiler Collection (GCC))