views:

209

answers:

3

A software I am working on ships with NETLIB BLAS/LAPACK embedded into its sources using all-lowercase symbol names but now while porting the application to windows I discovered that Intel MKL and several other BLAS/LAPACK implementations for this platform use all-uppercase symbol names. Is there a way to tell the gnu compiler/linker to ignore case while matching symbol names?

.
.
.
undefined reference to `_dgeqp3'
.
.
.

$ nm /lib/LAPACK.lib | grep -i " T _dgeqp3"
00000000 T _DGEQP3
+2  A: 

I think you might be in for some trouble. Section 6.4.2.1 of the C spec says "Lowercase and uppercase letters are distinct" with respect to identifiers. That means that as far as your compiler and linker are concerned, _DGEQP3 and _dgeqp3 are different symbols. You can probably add some #define statements in a platform-specific header to line things up for you.

Is it because you're linking against a windows library rather than whatever you were using before that this bug showed up?

Carl Norum
Compiling NETLIB BLAS or LAPACK packages with mingw gfortran, as we have been doing so far, results in symbols names like ___dgeqp3___ (lowercase, final underscore) but now I want to use other compilers and libraries on Windows and most BLAS LAPACK implementations distributed in binary form have symbol names like _DGEQP3 (uppercase, no final underscore) and some even have _dgeqp3 (lowercase, no final underscore).We already have #define statements to cover final underscores and if I cannot find a way around this case-sensitivity issue, I guess we'll have to augment them accordingly.
Cetin Sert
@Cetin, sometimes that's the way the cookie crumbles. Good luck!
Carl Norum
@Carl o__O thx!
Cetin Sert
+1  A: 

t.c

#define __CONCAT(x,y) x##y

#ifdef SUFFIX
#define __SUFFIX(x) __CONCAT(x,_)
#else
#define __SUFFIX(x) x
#endif

#ifdef UPPER
#define __c(U,l) __SUFFIX(U)
#else
#define __c(U,l) __SUFFIX(l)
#endif

#define xaxpy __c(XAXPY, xaxpy)

#include <stdio.h>

char* xaxpy;
char* DAXPY;

int main()
{
    printf(xaxpy);
    printf(DAXPY);
}

e.c

char* xaxpy  = "ln";
char* xaxpy_ = "ls";
char* XAXPY  = "UN";
char* XAXPY_ = "US";

there seems to be a way to introduce symbol aliases at link-time using --defsym:

Cetin@BAKA-CHAN ~
$ gcc -D UPPER -D SUFFIX -c t.c e.c

Cetin@BAKA-CHAN ~
$ gcc -o t t.o e.o -Wl,--defsym=_DAXPY=_xaxpy

Cetin@BAKA-CHAN ~
$ ./t
USln
Cetin@BAKA-CHAN ~
$

There must also be a way to give the linker different scripts to handle a large number of such symbol definitions. So I could make it part of the build process to automatically create linker scripts that create mappings between different cases.

Cetin Sert
+5  A: 

The difference you're seeing is due to Fortran calling conventions: in Fortran, symbol case is unimportant, and thus every compiler has a way to translate Fortran symbol names into assembler symbol names: GNU compilers usually translate all to lowercase, Intel on Windows goes for uppercase.

If you're working with Fortran code, you can use the -fsymbol-case-upper option on the older g77 compiler (the newer gfortran compiler doesn't have this). Otherwise, no simple answer for C, except:

  • using #define's
  • using the C interfaces to BLAS and LAPACK.
FX