title: Building a shared library using gcc
body: <p><strong>SOLVED.  See below for the corrections (labeled FIXED).</strong> </p>
  
  <p>I'm having trouble creating a shared library using gcc.</p>
  
  <p>I created a little sample project that closely mirrors the structure of the actual project I'm working on.  I've made it available as a tar.gz archive here:</p>
  
  <p><a href="http://209.59.216.197/libtest.tar.gz" rel="noreferrer">http://209.59.216.197/libtest.tar.gz</a></p>
  
  <p><strong>FIXED: I've made the fixed version available here:</strong><br>
  <a href="http://209.59.216.197/libtest_fixed.tar.gz" rel="noreferrer">http://209.59.216.197/libtest_fixed.tar.gz</a></p>
  
  <p>In this sample project, I have an application (app) that loads a shared library that I wrote (libshared.so) at runtime and calls a function that the shared library defines: function_inside_shared_lib().</p>
  
  <p>In turn, this shared library uses a function defined inside a static library (libstatic.a): function_inside_static_lib().</p>
  
  <p>The problem is when I build the shared library, the symbol "function_inside_shared_lib" does not get exported.  I examined the shared library using "nm" and the symbol wasn't there.  I am wondering if the command I am using to create the shared library is correct:</p>
  
  <blockquote>
    <p>g++ -g -ggdb -fPIC -rdynamic -I ../static -c shared.cpp -o shared.o<br>
    g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so</p>
  </blockquote>
  
  <p><strong>FIXED: The correct commands are:</strong></p>
  
  <blockquote>
    <p>g++ -g -ggdb -fPIC -rdynamic -I../static -c shared.cpp -o shared.o<br>
    g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic</p>
  </blockquote>
  
  <p>I tried these commands with and without -rdynamic, as well as with and without -fPIC.  The results are always the same.</p>
  
  <p>I am using Ubuntu 10.04 (64-bit) with g++ version 4.4.3.</p>
  
  <p>The full sample project follows.  (Or you can download the archive using the link at the top of my post).</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest$ ls<br>
    app  shared  static</p>
  </blockquote>
  
  <p>Here are the three components:</p>
  
  <p><strong>Component 1: A static library that defines a function called function_inside_static_lib()</strong>.</p>
  
  <p>This consists of the following:</p>
  
  <blockquote>
  <pre><code>serg@rodent:~/libtest$ cd static/  
  serg@rodent:~/libtest/static$ ls  
  static.cpp  static.h
  </code></pre>
  </blockquote>
  
  <p><strong>static.h</strong></p>
  
  <pre><code>// Header file for the static library
  
  int function_inside_static_lib(int arg1, int arg2);
  </code></pre>
  
  <p><strong>static.cpp</strong> </p>
  
  <pre><code>// Source file for the static library
  
  #include &lt;iostream&gt;
  using namespace std;
  
  #include "static.h"
  
  int function_inside_static_lib(int arg1, int arg2)
  {
      cout &lt;&lt; "In function_inside_static_lib()" &lt;&lt; endl;
  
      // Return the sum
      int result = arg1 + arg2;
      return result;
  }
  </code></pre>
  
  <hr>
  
  <p><strong>Component 2: A shared library that uses the static library and defines a new function.</strong></p>
  
  <blockquote>
    <p>serg@rodent:~/libtest$ cd shared<br>
    serg@rodent:~/libtest/shared$ ls<br>
    shared.cpp</p>
  </blockquote>
  
  <p><strong>shared.cpp</strong> </p>
  
  <pre><code>// The shared library only has one source file.
  
  // The shared library uses the static one.
  #include "static.h"
  
  #include &lt;iostream&gt;
  using namespace std;
  
  int function_inside_shared_lib(int arg1, int arg2)
  {
      cout &lt;&lt; "In function_inside_shared_lib()" &lt;&lt; endl;
  
      cout &lt;&lt; "Calling function_inside_static_lib()" &lt;&lt; endl;
      int result = function_inside_static_lib(arg1, arg2);
  
      return result;
  }
  </code></pre>
  
  <hr>
  
  <p><strong>Component 3: An application that uses the shared library.</strong></p>
  
  <blockquote>
    <p>serg@rodent:~/libtest$ cd app<br>
    serg@rodent:~/libtest/app$ ls<br>
    app.cpp</p>
  </blockquote>
  
  <p><strong>app.cpp</strong> </p>
  
  <p><strong>FIXED: Because C++ symbols get mangled, the correct function name to search for is <code>_Z26function_inside_static_libii</code> instead of <code>function_inside_static_lib</code></strong></p>
  
  <pre><code>// The application loads the shared library at runtime.
  
  #include &lt;dlfcn.h&gt;
  #include &lt;iostream&gt;
  
  using namespace std;
  
  int main(int argc, char **argv)
  {
      void *handle;
      int (*function_inside_shared_lib)(int, int);
      char *error;
  
      int arg1 = 3;
      int arg2 = 7;
  
      cout &lt;&lt; "app: loading the shared library." &lt;&lt; endl;
      handle = dlopen ("libshared.so", RTLD_LAZY);
      if (!handle) {
          cout &lt;&lt; "Error: Failed to open shared library." &lt;&lt; endl;
          cout &lt;&lt; dlerror() &lt;&lt; endl;
          return -1;
      }
  
      cout &lt;&lt; "app: Looking for function_inside_shared_lib" &lt;&lt; endl;
  
      // The next line is now FIXED:
      function_inside_shared_lib = (int (*)(int, int))dlsym(handle, "_Z26function_inside_static_libii");
  
      if ((error = dlerror()) != NULL)  {
          cout &lt;&lt; "Error: Could not find the function." &lt;&lt; endl;
          cout &lt;&lt; error &lt;&lt; endl;
          return -1;
      }
  
      cout &lt;&lt; "app: Calling function_inside_shared_lib(" &lt;&lt; arg1 &lt;&lt; ", " &lt;&lt; arg2 &lt;&lt; ")" &lt;&lt; endl;
      int result = (*function_inside_shared_lib)(arg1, arg2);
  
      cout &lt;&lt; "app: The result is " &lt;&lt; result &lt;&lt; endl;
  
      dlclose(handle);
      return 0;
  }
  </code></pre>
  
  <hr>
  
  <p>Here are the commands I'm using to build all of these components. Note that I want debugging symbols to be available in the final resulting app.  Ideally, I want to be able to do a backtrace inside the app and see symbols from both the shared library and the static library.</p>
  
  <p>1: Building the static library.  I think I'm fine with this step:</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest/static$ g++ -g -ggdb -c static.cpp -o static.o    # See the FIXED version just below<br>
    serg@rodent:~/libtest/static$ ar rcs libstatic.a static.o<br>
    serg@rodent:~/libtest/static$ ls<br>
    libstatic.a  static.cpp  static.h  static.o  </p>
  </blockquote>
  
  <p><strong>FIXED: The first command above must include -fPIC as well. The correct command is</strong></p>
  
  <blockquote>
    <p>g++ -g -ggdb -fPIC -c static.cpp -o static.o</p>
  </blockquote>
  
  <p>2: Building the shared library. I'm pretty sure this is where I'm going wrong.</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -I ../static -c shared.cpp -o shared.o<br>
    serg@rodent:~/libtest/shared$ g++ -g -ggdb -fPIC -rdynamic -shared -L ../static -lstatic -o libshared.so   # See just below for FIXED version
    serg@rodent:~/libtest/shared$ ls<br>
    libshared.so  shared.cpp  shared.o  </p>
  </blockquote>
  
  <p><strong>FIXED: The second command above should be:</strong></p>
  
  <blockquote>
    <p>g++ -g -ggdb -fPIC -rdynamic -shared -L../static -o libshared.so shared.o -lstatic</p>
  </blockquote>
  
  <p>At this point, if I run nm to examine the symbols inside libshared.so, I don't see function_inside_shared_lib() anywhere, even with the -a and -D options for nm.  (However, I do see it inside shared.o).</p>
  
  <p>EDIT: With the fix above, the symbol appears as <code>_Z26function_inside_shared_libii</code>.</p>
  
  <p>3: Building the app:</p>
  
  <p>First, copy the shared library into the app folder:</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest$ cp shared/libshared.so app/<br>
    serg@rodent:~/libtest$ cd app<br>
    serg@rodent:~/libtest/app$ ls<br>
    app.cpp  libshared.so  </p>
  </blockquote>
  
  <p>Now compile:</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest/app$ g++ -g -ggdb -ldl -L. -lshared app.cpp -o app<br>
    serg@rodent:~/libtest/app$ ls<br>
    app  app.cpp  libshared.so  </p>
  </blockquote>
  
  <p>If I try to run:</p>
  
  <blockquote>
    <p>serg@rodent:~/libtest/app$ ./app<br>
    app: loading the shared library.<br>
    app: Looking for function_inside_shared_lib<br>
    Error: Could not find the function.<br>
    /home/serg/libtest/app/libshared.so: undefined symbol: function_inside_shared_lib  </p>
  </blockquote>
  
  <p>This makes sense because I could not see function_inside_shared_lib() using nm either, which means I'm probably building the shared library incorrectly in step 2.</p>
  
  <p>How can I fix my command in the second step so that function_inside_shared_lib gets exported correctly?</p>
  
  <p>Also feel free to give me any other advice if you notice that I'm doing anything odd.  I'm still a beginner.</p>