Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save likev/751efc14b03016daeff977945fe308ca to your computer and use it in GitHub Desktop.
Save likev/751efc14b03016daeff977945fe308ca to your computer and use it in GitHub Desktop.
Building and Linking Libraries in C on Linux
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Building and Linking Libraries in C on Linux</title>
<link rel="stylesheet" href="https://stackedit.io/res-min/themes/base.css" />
<script type="text/javascript" src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"></script>
</head>
<body><div class="container"><h2 id="c-libraries">C Libraries</h2>
<p>In general, libraries are created from many library source files, and are either built as archive files (libmine.a) that are statically linked into executables that use them, or as shared object files (libmine.so) that are dynamically linked into executables that use them. To link in libraries of these types, use the gcc command line options -L for the path to the library files and -l to link in a library (a .so or a .a):</p>
<pre class="prettyprint"><code class="language-c++ hljs applescript">-L{<span class="hljs-command">path to</span> <span class="hljs-type">file</span> containing library} -l${library <span class="hljs-property">name</span>}</code></pre>
<p>For example, if I have a library named libmine.so in /home/newhall/lib/ then I’d do the following to link it into my program:</p>
<pre class="prettyprint"><code class="language-c++ hljs lasso">$ gcc <span class="hljs-attribute">-o</span> myprog myprog<span class="hljs-built_in">.</span>c <span class="hljs-attribute">-L</span>/home/newhall/lib <span class="hljs-attribute">-lmine</span></code></pre>
<p>You may also need to specify and include path so the compiler can find the library header file: <code>-I /home/newhall/include</code></p>
<p>If you create your own shared object files and do not install them in <code>/usr/lib</code>, then you need to set your <code>LD_LIBRARY_PATH</code> environment variable so that the runtime linker can find them and load them at run time. For example, if I put my <code>.so</code> files in a directory named lib in my home directory, I’d set my <code>LD_LIBRARY_PATH</code> enviroment to the following:</p>
<pre class="prettyprint"><code class="language-bash hljs "><span class="hljs-comment"># if running bash:</span>
<span class="hljs-keyword">export</span> LD_LIBRARY_PATH=/home/newhall/lib:<span class="hljs-variable">$LD_LIBRARY_PATH</span>
<span class="hljs-comment"># if running tcsh:</span>
setenv LD_LIBRARY_PATH /home/newhall/lib:<span class="hljs-variable">$LD_LIBRARY_PATH</span></code></pre>
<hr>
<h2 id="using-and-linking-library-code">USING AND LINKING LIBRARY CODE</h2>
<p>To use a Library that is not linked into your program automatically by <br>
the compiler, you need to (1) include the library’s header file in your <br>
C source file (test.c in the example below), and (2) tell the compiler to <br>
link in the code from the library .o file into your executable file:</p>
<ul>
<li><p>step 1: Add an include line (#include “somelib.h”) in a program <br>
source file (e.g., test.c).</p></li>
<li><p>step 2: Link the program’s .c file with the library object file <br>
(i.e. specify the somelib.o file as a command line argument to gcc): </p></li>
</ul>
<pre class="prettyprint"><code class="language-c++ hljs avrasm">% gcc -o myprog test<span class="hljs-preprocessor">.c</span> somelib<span class="hljs-preprocessor">.o</span></code></pre>
<p>The resulting executable file (myprog) will contain machine code <br>
for all the functions defined in test.c plus any mylib library <br>
functions that are called by</p>
<h2 id="creating-and-using-your-own-library-code">CREATING AND USING YOUR OWN LIBRARY CODE</h2>
<p>To create a Library of code you need to do the following:</p>
<ol>
<li>Create an INTERFACE to your library: mylib.h</li>
<li>Create an IMPLEMENTATION of your library: mylib.c</li>
<li> <br>
(a) Create a LIBRARY OBJECT FILE that can be linked with programs that want to use our library code <br>
(b) or create a SHARED OBJECT FILE from many .o files that can be linked with programs that want to use your library code</li>
<li>USE the library in other C code: <br>
(a) #include “mylib.h” <br>
(b) link in the libary code into a.out file</li>
<li>Set LD_LIBRARY_PATH environment variable for finding shared objects in non-standard locations at runtime</li>
</ol>
<h4 id="details">Details:</h4>
<p>(1) INTERFACE: the header file to your library should contain definitions for everything exported by your library: <br>
function prototypes with comments for users of your library functions <br>
definitions for types and global variables exported by your library </p>
<p>You should have “boiler plate” code (#ifndef … #endif) around the header file’s contents, to ensures that the preprocessor only includes the mylib.h file one time.</p>
<p>Here is what an example .h file might look like:</p>
<pre class="prettyprint"><code class="language-c++ hljs cs"><span class="hljs-preprocessor">#ifndef _MYLIB_H_</span>
<span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> _MYLIB_H_</span>
<span class="hljs-comment">// a constant definition exported by library:</span>
<span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> MAX_FOO 20</span>
<span class="hljs-comment">// a type definition exported by library:</span>
<span class="hljs-keyword">struct</span> foo_struct {
<span class="hljs-keyword">int</span> x;
<span class="hljs-keyword">float</span> y;
};
typedef <span class="hljs-keyword">struct</span> foo_struct foo_struct;
<span class="hljs-comment">// a global variable exported by library</span>
<span class="hljs-comment">// "extern" means that this is not a variable declaration, it </span>
<span class="hljs-comment">// just defines that a variable named total_foo of type int</span>
<span class="hljs-comment">// exits and you can use it (its declaration is in some library source file)</span>
<span class="hljs-keyword">extern</span> <span class="hljs-keyword">int</span> total_foo;
<span class="hljs-comment">// a function prototype for a function exported by library:</span>
<span class="hljs-keyword">extern</span> <span class="hljs-keyword">int</span> foo(<span class="hljs-keyword">float</span> y, <span class="hljs-keyword">float</span> z); <span class="hljs-comment">// a very bad function name</span>
<span class="hljs-preprocessor">#<span class="hljs-keyword">endif</span></span></code></pre>
<p>(2) IMPLEMENTATION: create a mylib.c file that #includes “mylib.h” and contains the implementation of every function in your library.</p>
<pre class="prettyprint"><code class="language-cpp hljs "><span class="hljs-preprocessor">#include "mylib.h"</span>
...
<span class="hljs-keyword">int</span> total_foo;
<span class="hljs-keyword">int</span> foo(<span class="hljs-keyword">float</span> y, <span class="hljs-keyword">float</span> z) {
...
}</code></pre>
<p>(3) create a LIBRARY OBJECT FILE that can be linked into other programs that use your library (use the -c option to gcc to tell it just to create an object file (a .o file) rather than an executable:</p>
<pre class="prettyprint"><code class="language-cpp hljs ">gcc -o mylib.o -c mylib.c</code></pre>
<p>you can then use the mylib.o file as the “library file” and statically link it into other programs that use it, or…</p>
<p>(3a) alternately, you can create a SHARED OBJECT FILE from one or more .o files that can be linked into other programs that use your library A shared object file is the Unix name for a dynamically linked library whose code is loaded into the a.out file at runtime. To create a .so file use the -shared flag to gcc. Here is what an example build might look like:</p>
<pre class="prettyprint"><code class="language-cpp hljs ">gcc -shared -o libmylib.so mylib.o blah.o grr.o -lm </code></pre>
<p>(3b) you could also build an ARCHIVE FILE (a statically linked library, libmylib.a) from one or more .o files. If you link with a static library, its code is copied into the a.out file at runtime.</p>
<p>See gcc documentation for more information on how to build .a and .so files.</p>
<p>(4) USE the library in other programs:</p>
<p>step 1: Add an include line (#include “mylib.h”) in all program source files that use library definitions (e.g., test.c).</p>
<p>step 2: Link the program’s .c file with the library object file <br>
(i.e. specify the mylib.o file as a command line argument to gcc): </p>
<pre class="prettyprint"><code class="language-cpp hljs ">gcc test.c mylib.o</code></pre>
<p>OR to link in libmylib.so (or libmylib.a):</p>
<pre class="prettyprint"><code class="language-cpp hljs ">gcc test.c -lmylib</code></pre>
<p>OR to link with a library not in the standard path:</p>
<pre class="prettyprint"><code class="language-cpp hljs ">gcc test.c -L/home/newhall/lib -lmylib</code></pre>
<p>The resulting a.out out will contain machine code for all the functions <br>
defined in test.c plus any mylib library functions that are called by <br>
the test.c code. </p>
<p>(5) RUNNING an executable linked with a shared object file:</p>
<p>If the shared object file in not in /usr/lib, then you need to set your <br>
LD_LIBRARY_PATH environment variable so that the runtime linker can find <br>
and load your .so file into the executable at runtime:</p>
<pre class="prettyprint"><code class="language-bash hljs "><span class="hljs-comment"># in bash:</span>
<span class="hljs-keyword">export</span> LD_LIBRARY_PATH=/home/newhall/lib:<span class="hljs-variable">$LD_LIBRARY_PATH</span>
<span class="hljs-comment"># in tcsh:</span>
setenv LD_LIBRARY_PATH /home/newhall/lib:<span class="hljs-variable">$LD_LIBRARY_PATH</span></code></pre></div></body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment