Can not use the blas at MacOS

While using the the blas no matter the framework accelerate or the openblas in the MacOS, it tells the Segmentation fault. How to fix this problem. The code is

MODULE BLAS_INTERFACE
    IMPLICIT NONE
  
    INTERFACE
      FUNCTION ZDOTC(N, X, INCX, Y, INCY) RESULT(DOTC)
        INTEGER, INTENT(IN) :: N
        COMPLEX(8), INTENT(IN) :: X(*), Y(*)
        INTEGER, INTENT(IN) :: INCX, INCY
        COMPLEX(8) :: DOTC
      END FUNCTION ZDOTC
    END INTERFACE
  
  END MODULE BLAS_INTERFACE
  
  PROGRAM TEST_ZDOTC
    USE BLAS_INTERFACE, ONLY: ZDOTC
    IMPLICIT NONE
  
    INTEGER, PARAMETER :: N = 3
    COMPLEX(8) :: X(N), Y(N)  
    COMPLEX(8) :: dot_result
  
    X = [ (1.0D0, 2.0D0), (3.0D0, 4.0D0), (5.0D0, 6.0D0) ]
    Y = [ (2.0D0, 1.0D0), (4.0D0, 3.0D0), (6.0D0, 5.0D0) ]
  
    dot_result = ZDOTC(N, X, 1, Y, 1)
  
    PRINT *, dot_result
  
  END PROGRAM TEST_ZDOTC

I think this is related to,

The easiest workaround would be to call the CBLAS version instead: GitHub - tenomoto/dotwrp: A wrapper for CBLAS *dot* functions in Accelerate framework of Mac OS X

You can also do so from Fortran:

    interface
      subroutine cblas_zdotc_sub(n,x,incx,y,incy,dotc) bind(c,name="cblas_zdotc_sub")
        integer, value :: n, incx, incy
        complex(8), intent(in) :: x(*), y(*)
        complex(8), intent(out) :: dotc
      end subroutine
    end interface

I think it is, but I was unaware of the problems with zdotc() and zdotu() when I posted the previous test/demo code. I was only aware of the problems with the single-to-double declaration errors. These double-to-double errors are new to me, and they are surprising because I would have thought they they would have been used much more frequently than the single precision routines.

It is correct that -ff2c does fix the problem using gfortran. This apparently corrupts the calling code to match the traditionally corrupt library code. This old f2c conversion error strikes again.

$ gfortran -framework accelerate -ff2c zdotcx.f90 && a.out
              (88.000000000000000,-21.000000000000000)

I did a quick test, and the openblas library does appear to work correctly without a seg fault.

$ gfortran -L/opt/homebrew/opt/openblas/lib -lblas zdotcx.f90 && a.out
              (88.000000000000000,-21.000000000000000)

Here, the correctly compiled fortran code calls the correctly compiled library code.

1 Like

Here I have another question, I can not compile it with

gfortran -o test_zdotc test_zdotc.f90  -lopenblas

when I use openblas and with the code in zshrc

export LDFLAGS="-L/opt/homebrew/opt/openblas/lib"
export CPPFLAGS="-I/opt/homebrew/opt/openblas/include"

which means I must use

gfortran -o test_zdotc test_zdotc.f90 -L/opt/homebrew/opt/openblas/lib -lopenblas

So why can’t I use the cleaner compile command.

I’m not sure that ld looks at LDPATH. Look at the output from man ld, and that environment variable is not mentioned. Maybe there is some other symbol that is used?

I use several combinations of libraries and compilers, so I usually set search paths in makefiles rather than environment variables. That helps ensure that I keep things straight when I switch projects.

Maybe use LIBRARY_PATH instead…?

export LIBRARY_PATH="/opt/homebrew/opt/openblas/lib"
gfortran -o test_zdotc test_zdotc.f90 -lopenblas

You need to tell the linker where it can find the OpenBLAS library.

Btw a good way to check which (dynamic) libraries have been linked on a Mac is with otool -L,

$ gfortran test_blas.f90 -framework Accelerate
$ otool -L a.out
a.out:
	/opt/homebrew/opt/gcc/lib/gcc/current/libgfortran.5.dylib (compatibility version 6.0.0, current version 6.0.0)
	/System/Library/Frameworks/Accelerate.framework/Versions/A/Accelerate (compatibility version 1.0.0, current version 4.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)

Not that MacOS also has named BLAS and LAPACK librares (sub-components of Accelerate):

$ gfortran test_blas.f90 -lblas
$ otool -L a.out
a.out:
	/System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib (compatibility version 1.0.0, current version 1.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libgfortran.5.dylib (compatibility version 6.0.0, current version 6.0.0)
	/opt/homebrew/opt/gcc/lib/gcc/current/libquadmath.0.dylib (compatibility version 1.0.0, current version 1.0.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1351.0.0)
1 Like

This does work. However, LIBRARY_PATH is not mentioned anywhere in man ld either, so one would need to know to look elsewhere:
Environment Variables (Using the GNU Compiler Collection (GCC))
Anyone know if there is local documentation (e.g. a man page) where this is discussed?

Hi Ron,

In my case, I just searched the net with related keywords and found those pages (GCC manual and Stackoverflow). But I usually do not use LIBRARY_PATH for my programs (indeed, I guess my compilation method is probably similar to yours mentioned above…). RE local documents, man gfortran and searching for the ENVIRONMENT section gives:

ENVIRONMENT
   The gfortran compiler currently does not make use of
   any environment variables to control its operation above and 
   beyond those that affect the operation of gcc.

and doing the same for gcc (with man gcc) gives:

ENVIRONMENT
...
  LIBRARY_PATH
     The value of LIBRARY_PATH is a colon-separated list
     of directories, much like PATH.  When configured as a native
     compiler, GCC tries the directories thus specified when
     searching for special linker files, if it cannot find them
     using GCC_EXEC_PREFIX.  Linking using GCC also
     uses these directories when searching for ordinary libraries
     for the -l option (but directories specified with -L come first).

(Probably the same sentences shown in the above online manual.)

I don’t think this comment applies to any of the questions in this thread, but I thought it might be mentioned that the MacOS ld behaves differently than the typical linux ld in several ways. I don’t know if this is because they are entirely different tools or if they are the same basic tool but with different build configurations. One difference I’ve noticed is that you never need to specify a library with the MacOS ld command more than once. It automatically searches the specified libraries repeatedly to satisfy any unresolved symbols. The linux ld command by contrast sometimes requires either that a library to be specified more than once or that it be listed within -( and -) symbols, which apparently duplicates the MacOS ld behavior.

Most of the utilities in macOS were inherited from BSD, whereas the ones used in linux come from GNU (that is, unless you’re Ubuntu and want to use the Rust-based equivalents instead, hehehe). So they tend to behave very differently.

I kind of prefer the GNU behavior (e.g., date), and homebrew lets you replace some of those (BSD) utilities with the GNU ones.

I think it’s because GNU’s ld only visits symbols tables once and in the listed order, which is fine only for shared libraries (but for static ones, you might need -Wl,--start-group/-Wl,--end-group).

(Since glibc is not intended for static linking, I think the GNU guys don’t really care that people prefer static libraries for performance and/or portability reasons)