    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Static C library and GNU Make</title>
        <link>https://members.accu.org/index.php/articles/2734</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>




<div class="xar-mod-head"><span class="xar-mod-title">Programming Topics + CVu Journal Vol 31, #6 - January 2020</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c65/">Programming</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/articles/c406/">316</a>
<br />

                                            <a href="https://members.accu.org/index.php/articles/c65-406/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/articles/c65+406/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Static C library and GNU Make</h1>
<p><strong>Author:</strong>&nbsp;Bob Schmidt</p>
<p>
<strong>Date:</strong> 05 January 2020 17:28:31 +00:00 or Sun, 05 January 2020 17:28:31 +00:00</p>
<p><strong>Summary:</strong>&nbsp;Ian Bruntlett shares his experiences with using â€˜makeâ€™ to build a small test project.</p>
<p><strong>Body:</strong>&nbsp;<p>My biggest problem with the GNU Make manual <a href="#[1]">[1]</a> was its lack of testable examples. This article is intended to partially redress that, by offering a very simple but expandable example. For simplicity, I am not using a TDD framework like check <a href="#[2]">[2]</a> or CppUTest <a href="#[3]">[3]</a> â€“ that is likely to come later. The code is now available on my GitHub page <a href="#[4]">[4]</a>.</p>

<h2>My Makefile â€“ the main bits</h2>

<p>This is what happens when<code> make clean </code>is invoked:</p>

<pre class="programlisting">
  $ make clean
  rm -fv *.o libtrim.a test_ltrim test_rtrim
  removed 'ltrim.o'
  removed 'rtrim.o'
  removed 'libtrim.a'
  removed 'test_ltrim'
  removed 'test_rtrim'</pre>
  
<p>This is what happens when<code> make all </code>is invoked, after a<code> make clean</code>:</p>

<pre class="programlisting">
  $ make all
  gcc -g   -c -o ltrim.o ltrim.c
  ar rvU libtrim.a ltrim.o
  ar: creating libtrim.a
  a - ltrim.o
  gcc -g -L.    test_ltrim.c -ltrim -otest_ltrim
  gcc -g   -c -o rtrim.o rtrim.c
  ar rvU libtrim.a rtrim.o
  a - rtrim.o
  gcc -g -L.    test_rtrim.c -ltrim -otest_rtrim</pre>

<h2>Show me the code</h2>

<p>First off, a header file to list what will be in our static C library.</p>

<pre class="programlisting">
  // trim.h
  // (c) Ian Bruntlett, October 2019
  // trim left-hand side text from a string, 
  // in situ
  extern void ltrim(char s[]);
  
  // trim left-hand side text from a string, into 
  // a user-provided buffer
  extern void ltrimcpy(char *dest, char *src);
  
  // trim right-hand side text from a string, 
  // in situ
  extern void rtrim(char text[]);

  // trim right-hand side text from a string, 
  // into a user-provided buffer
  extern void rtrimcpy(char *dest, char *src);</pre>
  
<p>This library is tiny â€“ it is only made up of two files â€“ <span class="filename">ltrim.c</span> and <span class="filename">rtrim.c</span> but is OK as an example. Typically, many more object files would be part of the library. Listing 1 is one of them.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
// ltrim.c
// (c) Ian Bruntlett, October 2019
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &quot;trim.h&quot;

void ltrim(char s[])
{
  if ( !isspace(s[0]) )
    {return;}
  // Get index of first non-space
  int non_space_index=0;
  while ( isspace(s[non_space_index]) )
    { ++non_space_index; }
  // copy text characters over the white space
  int dest_index=0;
  while ( s[dest_index++] =
    s[non_space_index++] )
  ;
}
void ltrimcpy(char *dest, char *src)
{
  strcpy(dest, src);
  ltrim(dest);
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 1</td>
	</tr>
</table>

<p>The functions in Listing 1 are used to trim white space from the left-hand side of a C string. I think they work as they have passed various tests (more on that later). The companion source file, <span class="filename">rtrim.c</span> (Listing 2) trims white space from the right-hand side of a C string.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
// rtrim.c
// (c) Ian Bruntlett, October 2019
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &quot;trim.h&quot;
#define TEST_MAX (100)

void rtrim(char text[])
{
  int length = strlen(text);
  if (!length)
    return;
  for (int rhs = length-1;
       isspace(text[rhs]);
       --rhs
       )
    text[rhs] = '\0';
}
void rtrimcpy(char *dest, char *src)
{
  strcpy(dest,src);
  rtrim(dest);
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 2</td>
	</tr>
</table>

<p>So that is some code to test. I have two test programs, <span class="filename">test_ltrim.c</span> and <span class="filename">test_rtrim.c</span>, that I have used as test beds for the above code. Listing 3 is <span class="filename">test_ltrim.c</span>. If run with no parameters, it runs a built-in set of tests. Otherwise it uses two parameters from the command line (usage: <code>test_ltrim &quot;test string&quot; &quot;expected result string&quot;</code>) for convenience.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
// test_ltrim.c
// (c) Ian Bruntlett, October 2019
#include &lt;assert.h&gt;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;ctype.h&gt;
#include &quot;trim.h&quot;

#define TEST_MAX (100)

void test_ltrimcpy(char *test_argument, 
  char *expected_result)
{
  char test_result[TEST_MAX];
  assert(strlen(test_argument) &lt; TEST_MAX);
  ltrimcpy(test_result, test_argument);
  int success = !strcmp(test_result,
    expected_result);  
  if ( success )
    { printf(&quot;OK :&quot; );  }
  else
    { printf(&quot;Failed :&quot; );  }
  printf(&quot;argument : '%s' result : '%s' 
    : expected '%s'\n&quot;, test_argument,
    test_result, expected_result);
  assert(success);
}
int main(int argc, char *argv[])
{
  if (argc==1 )
  {
    test_ltrimcpy(&quot;  Hello &quot;, &quot;Hello &quot;);
    test_ltrimcpy(&quot;Hello &quot;, &quot;Hello &quot;);
    test_ltrimcpy(&quot;&quot;,&quot;&quot;);
    test_ltrimcpy(&quot;     &quot;,&quot;&quot;);
  }
  else if (argc==3)
    test_ltrimcpy(argv[1],argv[2]);
  else
    printf(&quot;%s incorrect arguments\n&quot;, argv[0] );
  return 0;
}
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 3</td>
	</tr>
</table>

<p>So that is the code. How do we build and run it? It is possible (but error-prone) to continually type in commands to build the code prior to running it. Step forward GNU Make. It automates the build process and typically needs to be provided with a Makefile so it knows what you want it to do. Listing 4 is my Makefile.</p>

<table class="sidebartable">
	<tr>
		<td>
			<pre class="programlisting">
# makefile for libtrim.a static library, using
# archive members as targets.
# (c) Ian Bruntlett, October 2019

CC = gcc
CFLAGS = -g
ARFLAGS = rvU
executables =  test_ltrim test_rtrim
tar_filename = trim-source-$(shell date &quot;+%Y-%m-%d&quot; ).tar

all: $(executables)

test_ltrim : test_ltrim.c trim.h libtrim.a(ltrim.o)
  $(CC) -g -L.    test_ltrim.c -ltrim -o$@

test_rtrim : test_rtrim.c trim.h libtrim.a(rtrim.o)
  $(CC) -g -L.    test_rtrim.c -ltrim -o$@

ltrim.o : ltrim.c trim.h

rtrim.o : rtrim.c trim.h

.PHONY: tar-it
tar-it:
  tar -cvf $(tar_filename) *.c *.h makefile

.PHONY: clean
clean:
  rm -fv *.o libtrim.a $(executables)
			</pre>
		</td>
	</tr>
	<tr>
		<td class="title">Listing 4</td>
	</tr>
</table>

<p>This makefile can build the test executables (<code>test_ltrim</code> and <code>test_rtrim</code>), the library modules (<span class="filename">ltrim.o</span> and <span class="filename">rtrim.o</span>), and the library itself (<span class="filename">libtrim.a</span>), when the command  <code>make</code> is run. That runs the default goal which, in this case, is called <code>all</code> and depends upon <code>test_ltrim</code> and <code>test_rtrim</code>. Make then looks at those targets and determines that as well as those targets, both <span class="filename">ltrim.o</span> and <span class="filename">rtrim.o</span> are required and are to be stored in the static C library <span class="filename">libtrim.a</span>.</p>

<h2>Makefiles</h2>

<p>To quote the manual, Makefiles contain five kinds of things:</p>

<ol>
	<li><strong>Explicit rules</strong>, like those for <code>test_ltrim</code> and <code>test_rtrim</code>.</li>
	
	<li><strong>Implicit rules</strong> that define how a source file with a particular file extension can be processed to build a destination file with another file extension. Like telling the compiler how to build object files from C source files. They tend to be customisable by setting variables such as <code>CFLAGS</code> and <code>ARFLAGS</code>. To avoid conflicts between Makeâ€™s built-in variables and user-defined variables, the user-defined variables are usually given lower-case names.</li>
	
	<li><strong>Variable definitions</strong> (there are two types of variables). Typically used to specify pieces of text that are likely to be repeated. For example, in my makefile there is a line that defines the variable executables to contain the text <code>&quot;test_ltrim test_rtrim&quot;</code>.</li>
	
	<li><strong>Directives</strong> for more advanced Makefiles. See the manual <a href="#[1]">[1]</a>.</li>
	
	<li><strong>Comments</strong> â€“ lines starting with <code>#</code>.</li>
</ol>

<h2>Rules</h2>

<p>Rules tell Make how to behave. An explicit rule looks similar to this (note that some things can be left out):</p>

<pre class="programlisting">
  targets : prerequisites
    commands that must be indented with a TAB
    character
  all: $(executables)</pre>
  
<p>The above code is an explicit rule that depends on the value of <code>$(executables)</code> which we know contains the two values <code>test_ltrim</code> and <code>test_rtrim</code>. So, when <code>make all</code> is invoked, it is akin to running <code>make test_ltrim test_rtrim</code>.</p>

<pre class="programlisting">
  test_ltrim : test_ltrim.c trim.h
  libtrim.a(ltrim.o)
    $(CC) -g -L.    test_ltrim.c -ltrim -o$@</pre>
	
<p>The above rule has the target <code>test_ltrim</code>. Once this rule is processed, the file <span class="filename">test_ltrim</span> should have been created (it is an error if it isnâ€™t). It lists the prerequisites â€“ these are files that the target (<code>test_ltrim</code>) depends upon. If they are changed, the target needs to be recompiled. This rule is special in that it has the prerequisite <code>libtrim.a(ltrim.o)</code>. Normally it would be l<code>trim.o</code>. However, this alternative syntax tells <code>make</code> that the target depends on <span class="filename">ltrim.o</span> which, in turn, is to be part of an automatically generated static C library called <span class="filename">libtrim.a</span>. In Linux, library files are managed using the <code>ar</code> utility. To get the library created and updated properly, a built-in variable had to be set like this:</p>

<pre class="programlisting">
  ARFLAGS = rvU</pre>
  
<p>The command line to build <code>test_ltrim</code> is this:</p>

<pre class="programlisting">
  $(CC) -g -L.    test_ltrim.c -ltrim -o$@</pre>
  
<p>Where:</p>

<ul>
	<li><code>$(CC)</code> indicates that the default C compiler is to be used. In this case, gcc.</li>
	
	<li><code>-g</code> specifies that debugging information is to be included</li>
	
	<li><code>-L.</code> specifies that the current directory is also going to be searched for libraries</li>
	
	<li><code>test_ltrim.c</code>  specifies the source filename</li>
	
	<li><code>-ltrim</code> specifies that the shared library <span class="filename">libtrim.a</span> must be consulted</li>
</ul>

<p><code>-o$@</code> is interesting. It states that the output executable name is the same name as the target â€“ i.e. <code>test_ltrim</code>. <code>$@</code> is one of many special variables that are invaluable.</p>

<p>The rules for determining if <span class="filename">ltrim.o</span> and <span class="filename">rtrim.o</span> need to be recompiled are this:</p>

<pre class="programlisting">
  ltrim.o : ltrim.c trim.h
  rtrim.o : rtrim.c trim.h</pre>
  
<p>They specify that the above object files depend on their namesake C source files as well as the header, <span class="filename">trim.h</span>. If I had used a default rule for this, the header file would not have been considered as a prerequisite.</p>

<h2>Helper scripts (aka Phony Targets): clean and tar-it</h2>

<p>For convenience, it is possible to put commonly used shell commands into the Makefile which can in turn be invoked when required. In my Makefile, <code>make clean</code> deletes all the binary files.</p>

<pre class="programlisting">
  .PHONY: clean
  clean:
    rm -fv *.o libtrim.a $(executables)</pre>
	
<p>This also shows that, when maintaining Makefiles, you need to be conversant with Makeâ€™s syntax and your shellâ€™s syntax. This can be confusing.</p>

<p>Early on in my makefile, this variable was defined by me.</p>

<pre class="programlisting">
  tar_filename = trim-source-$(shell date 
    &quot;+%Y-%m-%d&quot; ).tar</pre>
	
<p>The above line is defines a variable, <code>$(tar_filename)</code>, which is set to some literal text and gets some of its value from running the date command. For example, if the above code was run today, <code>$(tar_filename)</code> would be set to the value <span class="filename">trim-source-2019-11-03.tar</span>. This variable is used later on in the makefile, to be used when <code>make tar-it</code> is invoked:</p>

<pre class="programlisting">
  .PHONY: tar-it
  tar-it:
    tar -cvf $(tar_filename) *.c *.h makefile</pre>

<h2>Git and Git-Hub (from my notes)</h2>

<p>I confess, a long time ago, I wrote a very basic (but functional, nevertheless) source code sharing system called SCHOLAR (Source Code Held Online Archiving and Retrieving). Apparently this makes it harder for me to get to grips with git and GitHub (a site for hosting git repositories). This is not a tutorial. Fortunately for me, I had help from accu-general to get me going and, most recently, had help directly from Bronek Kozicki.</p>

<p>First I signed up for a (free) GitHub account (<a href="https://github.com">https://github.com</a>). Then I started trying to do things. The next thing I should have done is use the GitHub webpage to create a new repository â€“ called â€˜trimâ€™ for my code. I have (eventually) decided to go public on my email account and so I also went to <a href="https://github.com/settings/emails">https://github.com/settings/emails</a> and deselected <em>Block command line pushes that expose my email</em> . I do hope that I have done the right thing. Another thing I should have done was these commands (your parameters will need your name and your email address):</p>

<pre class="programlisting">
  git config --global user.email
    &quot;ian.bruntlett@gmail.com&quot;
  git config --global user.name &quot;Ian Bruntlett&quot;</pre>
  
<p>Before I could put files on GitHub, I needed a local repository. So I went to the directory I had my code in and typed:</p>

<pre class="programlisting">
  git init
  git status
  git add *.c
  git add *.h
  git add makefile
  git add readme.txt
  git commit -m &quot;First commit for libtrim support
  code&quot;
  git remote add origin https://github.com/ian-
  bruntlett/trim.git
  git remote -v</pre>
  
<p>Output of the above command:</p>

<pre class="programlisting">
  origin  https://github.com/ian-bruntlett/trim.git
  (fetch)
  origin  https://github.com/ian-bruntlett/trim.git
  (push)
  git push -u origin master</pre>
  
<p>Donâ€™t quote me on git! Now that I have an idea of which commands are most important to me, I will be reading the man pages in depth and reading a good book about it <a href="#[5]">[5]</a>.</p>

<h2>Conclusion</h2>

<p>I hope this has been a helpful introduction to Make and static libraries. Happy coding!</p>

<h2>References</h2>

<p class="bibliomixed"><a id="[1]"></a>[1] GNU Make manual <a href="https://www.gnu.org/software/make/manual/">https://www.gnu.org/software/make/manual/</a></p>

<p class="bibliomixed"><a id="[2]"></a>[2] Check â€“ see <a href="https://libcheck.github.io/check/">https://libcheck.github.io/check/</a> (or install the check package)</p>

<p class="bibliomixed"><a id="[3]"></a>[3] CppUTest â€“ see  <a href="https://cpputest.github.io/">https://cpputest.github.io/</a> (or install the cpputest package)</p>

<p class="bibliomixed"><a id="[4]"></a>[4] <a href="https://github.com/ian-bruntlett/trim">https://github.com/ian-bruntlett/trim</a></p>

<p class="bibliomixed"><a id="[5]"></a>[5] <em>Version control with Git</em> by Jon Loeliger &amp; Matthew McCullough.</p>

<p class="bio"><span class="author"><b>Ian Bruntlett</b></span> On and off, Ian has been programming for some years. He is a volunteer system administrator (among other things) for a mental health charity called Contact (<a href="http://www.contactmorpeth.org.uk">www.contactmorpeth.org.uk</a>). He is learning low-level and other, higher-level, aspects of programming.</p>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
