title: Building a shared library using gcc on Linux and MinGW on Windows
body: <p>I'm having trouble with generating a build setup that allows shared libraries to be built in both Linux and Windows using gcc and MinGW, respectively.  In Linux, a shared library doesn't have to resolve all dependencies at compile time; whereas, this appears to the case in Windows.  Here is the problem setup:</p>
  
  <hr>
  
  <pre><code>$ cat foo.h 
  #ifndef FOO_H
  #define FOO_H
  void printme();
  #endif
  </code></pre>
  
  <hr>
  
  <pre><code>$ cat foo.c
  #include "foo.h"
  #include &lt;stdio.h&gt;
  void printme() {
      printf("Hello World!\n");
  }
  </code></pre>
  
  <hr>
  
  <pre><code>$ cat bar.h
  #ifndef BAR_H
  #define BAR_H
  void printme2();
  #endif
  </code></pre>
  
  <hr>
  
  <pre><code>$ cat bar.c
  #include "bar.h"
  #include "foo.h"
  void printme2() {
      printme();
      printme();
  }
  </code></pre>
  
  <hr>
  
  <pre><code>$ cat main.c
  #include "bar.h"
  int main(){
      printme2();
  }
  </code></pre>
  
  <hr>
  
  <pre><code>$ cat Makefile 
  .c.o:
          gcc -fPIC -c $&lt;
  
  all: foo.o bar.o main.o
          gcc -shared foo.o -o libfoo.so
          gcc -shared bar.o -o libbar.so
          gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main
  </code></pre>
  
  <hr>
  
  <p>Now, in Linux, this compiles and runs just fine:</p>
  
  <pre><code>$ make
  gcc -fPIC -c foo.c
  gcc -fPIC -c bar.c
  gcc -fPIC -c main.c
  gcc -shared foo.o -o libfoo.so
  gcc -shared bar.o -o libbar.so
  gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main
  
  $ ./main 
  Hello World!
  Hello World!
  </code></pre>
  
  <p>In Windows, we need to change so to dll, which is minor and fine:</p>
  
  <pre><code>$ cat Makefile 
  .c.o:
          gcc -fPIC -c $&lt;
  
  all: foo.o bar.o main.o
          gcc -shared foo.o -o libfoo.dll
          gcc -shared bar.o -o libbar.dll
          gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main
  </code></pre>
  
  <p>However, when we try to build, we get the following error:</p>
  
  <pre><code>$ make
  gcc -fPIC -c foo.c
  foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -fPIC -c bar.c
  bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -fPIC -c main.c
  main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -shared foo.o -o libfoo.dll
  gcc -shared bar.o -o libbar.dll
  bar.o:bar.c:(.text+0x7): undefined reference to `printme'
  bar.o:bar.c:(.text+0xc): undefined reference to `printme'
  collect2.exe: error: ld returned 1 exit status
  make: *** [all] Error 1
  </code></pre>
  
  <p>Now, we can fix the error by simply including the objects from foo.o into libbar.dll:</p>
  
  <pre><code>$ cat Makefile 
  .c.o:
          gcc -fPIC -c $&lt;
  
  all: foo.o bar.o main.o
          gcc -shared foo.o -o libfoo.dll
          gcc -shared bar.o foo.o -o libbar.dll
          gcc main.o  -Wl,-rpath=. -L . -lbar -lfoo -o main
  
  $ make
  gcc -fPIC -c foo.c
  foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -fPIC -c bar.c
  bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -fPIC -c main.c
  main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
  gcc -shared foo.o -o libfoo.dll
  gcc -shared bar.o foo.o -o libbar.dll
  gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main 
  
  $ ./main 
  Hello World!
  Hello World!
  </code></pre>
  
  <p>However, I don't like this approach since libbar.dll now contains symbols for both foo and bar.  In Linux, it only contains symbols for bar.  This separation is important for situations where a library depends on some standard numerical library like BLAS.  I'd like to be able to deploy the shared library and have it depend on the optimized version of the numerical library on the user's machine and not my own.</p>
  
  <p>In any case, what's the proper procedure to create a shared library where not all of the symbols are present at compile time?</p>
  
  <p>In case it matters, I compiled these examples with gcc 4.6.3 on Linux and mingw-get-inst-20120426.exe with gcc 4.7.2 on Windows.</p>