title: Undefined reference to `nfsInit`
body: <p>I am currently trying to integrate an NFS server into some code running on <code>RTEMS 4.9.2</code> on a <code>POWER PC 5200</code>. This is going to be tough to succinctly explain so bear with me. </p>
  
  <h2>RTEMS NFS</h2>
  
  <p>Currently RTEMS implements an NFS client through the nfs.c file. In order to activate the command line interface and be able to use the <code>mount -t nfs ...</code> option you need to add <code>#define CONFIGURE_SHELL_MOUNT_NFS</code> to your config file and link the rtems nfs files with <code>-lnfs</code>. See <a href="https://docs.rtems.org/releases/rtemsdocs-4.10.1/share/rtems/html/shell/shell00046.html" rel="nofollow">here</a> for more details. Doing this correctly allows us to implement the RTEMS nfs client and from the command line we can mount a remote drive.</p>
  
  <h2>Using the RTEMS NFS client directly</h2>
  
  <p>We don't expose the RTEMS command line in our program, so we would like to be able to use the nfs interface directly. The RTEMS libs provides <a href="https://github.com/atgreen/RTEMS/blob/master/cpukit/libfs/src/nfsclient/src/librtemsNfs.h" rel="nofollow"><code>librtemsNfs.h</code></a> which contains functions for implementing nfs clients. The implementations for these functions are in <code>nfs.c</code> which is compiled to create 1 of 2 libs:</p>
  
  <ol>
  <li><code>libnfs.a</code></li>
  <li><code>nfs.rel</code></li>
  </ol>
  
  <p>Both are needed to build. As part of our code we are using the function <code>nfsInit(...</code> which is declared in <code>librtemsNfs.h</code> and defined in <code>nfs.c</code>. </p>
  
  <h2>The error</h2>
  
  <p>So the error is pretty obvious. When we build we get the linker error:</p>
  
  <pre><code>D:\Git\nfs_stuff\Src\RTEMS_proj/init/srvinit.cpp:453: undefined reference to `nfsInit(int, int)'
  collect2: ld returned 1 exit status
  </code></pre>
  
  <h2>Attempts to link these libraries</h2>
  
  <p>In order to link these we have tried multiple ways. We have a <code>makefile</code> but to make this easier on everyone i will show what comes out on the command line build. We have tried:</p>
  
  <hr>
  
  <ol>
  <li>The recommended method is to link with -lnfs (<a href="https://lists.rtems.org/pipermail/users/2015-June/028933.html" rel="nofollow">source - an old question</a>) and doing so yields a nice long and complex build command:</li>
  </ol>
  
  <blockquote>
    <p>powerpc-rtems4.9-g++ -g -Wall -g -mcpu=603e -mstrict-align -meabi -msdata -fno-common ... -MANY_PREPROCESSOR_ARGUMENTS ... -MANY_INCLUDE_FILES ... Map=./exe/srvevp.map -lc -lm --gc-sections -lnfs -mcpu=603e -mstrict-align -meabi ... -MANY_OBJECT_FILES ... ./exe/obj/srvinit.o ... -MANY_MORE_OBJECT_FILES</p>
  </blockquote>
  
  <p>Our compile and link command has <code>-lnfs</code>, before the inclusion of the offending object file (<code>srvinit.o</code>). But we still get the linker error.</p>
  
  <hr>
  
  <ol start="2">
  <li>I tried to link by path directly to the <code>.a</code> and <code>.rel</code> file. We did this by adding: <code>/c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel</code> to the command line. We added it both before and after the offending object file. We also tried with the <code>-L</code> command to force linking by path. All of this results in the same error. </li>
  </ol>
  
  <h2>Some other information</h2>
  
  <p>This is hard to describe, but when removing the direct link of the <code>libnfs.a</code> file we lose the ability to build even without direct nfs use. ie. the internal RTEMS files fail to link to one another. This is very odd, it seems to me you should only need to the <code>-lnfs</code> to build the command line options, but even without this flag it builds successfully. Without the direct include we get the error:</p>
  
  <pre><code>c:/rtems-4.9/powerpc-rtems4.9/5200/lib\librtemscpu.a(libshell_a-main_mount_nfs.o): In function `rtems_shell_nfs_mounter':
  e:\CCNET\rtems-4.9\Trunk\build_5200\powerpc-rtems4.9\c\adept_5200\cpukit\libmisc/../../../../../../rtems-4.9.2/c/src/../../cpukit/libmisc/shell/main_mount_nfs.c:46: undefined reference to `rpcUdpInit'
  e:\CCNET\rtems-4.9\Trunk\build_5200\powerpc-rtems4.9\c\5200\cpukit\libmisc/../../../../../../rtems-4.9.2/c/src/../../cpukit/libmisc/shell/main_mount_nfs.c:51: undefined reference to `nfsInit'
  e:\CCNET\rtems-4.9\Trunk\build_5200\powerpc-rtems4.9\c\5200\cpukit\libmisc/../../../../../../rtems-4.9.2/c/src/../../cpukit/libmisc/shell/main_mount_nfs.c:58: undefined reference to `nfsMount'
  collect2: ld returned 1 exit status
  </code></pre>
  
  <p>Which is the rtems shell code failing to link. If we add the <code>/c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel</code> to the end of the build line, then everything succeeds. </p>
  
  <p>To re-iterate, to build the command line functions you need to directly include the nfs <code>.a</code> and <code>.rel</code> files, you DO NOT need to use <code>-lnfs</code>.</p>
  
  <h2>The question</h2>
  
  <p>So the first and most obvious question is, <strong>why is this not linking, even when i explicitly give the library files?</strong> My thoughts on this are, perhaps the files do not include the definitions for the functions i am trying to use. But this is discredited in the other information section as i need them to link the functions for the RTEMS OS itself. </p>
  
  <p>I know this will be hard to give a direct answer too, since it will be very much un-reproducible without the PC and all the compiler installed etc. <strong>How can i check that the lib files include the definitions for my functions and are being linked in the correct order?</strong> The compiler is a BSP specific <code>GCC</code> style compiler provided by RTEMS for the Power PC 5200. It accepts most compiler options that GCC/G++ 4.2 would accept. </p>
  
  <p>Finally, <strong>are there any good methods for debugging such a linker issue?</strong>. </p>