Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined reference when dynamically linking with gcc in cygwin

(This is gcc 3.3.1 (long story -- blame NIST) on Cygwin.)

I have compiled some source files with gcc -c -fPIC ... to get .o files.

Then I did:

$ gcc -shared -o foo.dll foo.o bar.o

But when I go to use it:

$ gcc -o usefoo.exe usefoo.o -L. -lfoo
  usefoo.o:usefoo.cpp:(.text+0x2e0): undefined reference to `_get_template_size'
  collect2: ld returned 1 exit status

However, if using the same .o files I instead do:

$ ar rcs libfoo-static.a foo.o bar.o

The link against that is successful:

$ gcc -o foo.exe foo.o -L. -lfoo-static

What is weird to me is that as you can see below, the reference in question is present in both the .a and the .dll. So why the error when linking against the .dll?

Reference is found in the shared library:

$ nm foo.dll|grep get_template
1001b262 T _get_template_size

And it's also in the static library:

$ nm libfoo-static.a |grep get_template
00000352 T _get_template_size

And here's the reference to the symbol generated in the file that wants to use the function:

$ nm usefoo.o
00000000 b .bss
00000000 d .data
00000000 t .text
0000012c T __Z12ErrorMessagei
         U ___main
         U __alloca
         U _atoi
         U _get_template_size
0000026c T _main
         U _printf

Updated to address Marco's answer

Interestingly/annoyingly, when I try to make a minimum test example of this I can't make it happen (though it happens every time with the real thing):

func1.h:

#ifndef FUNC1_H
#define FUNC1_H

int func1(int i);

#endif

func1.c:

#include "func1.h"

int func1(int i) {
  return 2*i;
}

usefunc.c:

#include <stdio.h>
#include "func1.h"

int main() {
  printf("%d\n", func1(10));
}

Then:

$ rm *.o *.dll *.a

$ gcc -fPIC -I. -c func1.c usefunc.c

$ gcc -shared -o func.dll func1.o

$ gcc -L. -o usefunc.exe usefunc.o -lfunc

$ ./usefunc.exe
20
like image 860
QuantumMechanic Avatar asked Feb 16 '12 19:02

QuantumMechanic


1 Answers

I found the answer (in that it solves my link problem) on a Cygwin web page: http://cygwin.com/cygwin-ug-net/dll.html

What I ended up having to do was create the shared library and do the final link like this:

$ gcc -shared -o cygfoo.dll \
      -Wl,--out-implib=libfoo.dll.a \
      -Wl,--export-all-symbols \
      -Wl,--enable-auto-import \
      -Wl,--whole-archive *.o \
      -Wl,--no-whole-archive

$ gcc -L. -o usefoo.exe usefoo.o -lfoo

But I'd still love to know why I didn't have to do this for my simple test.

like image 94
QuantumMechanic Avatar answered Oct 05 '22 02:10

QuantumMechanic