I am currently trying to integrate an NFS server into some code running on RTEMS 4.9.2
on a POWER PC 5200
. This is going to be tough to succinctly explain so bear with me.
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 mount -t nfs ...
option you need to add #define CONFIGURE_SHELL_MOUNT_NFS
to your config file and link the rtems nfs files with -lnfs
. See here 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.
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 librtemsNfs.h
which contains functions for implementing nfs clients. The implementations for these functions are in nfs.c
which is compiled to create 1 of 2 libs:
libnfs.a
nfs.rel
Both are needed to build. As part of our code we are using the function nfsInit(...
which is declared in librtemsNfs.h
and defined in nfs.c
.
So the error is pretty obvious. When we build we get the linker error:
D:\Git\nfs_stuff\Src\RTEMS_proj/init/srvinit.cpp:453: undefined reference to `nfsInit(int, int)'
collect2: ld returned 1 exit status
In order to link these we have tried multiple ways. We have a makefile
but to make this easier on everyone i will show what comes out on the command line build. We have tried:
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
Our compile and link command has -lnfs
, before the inclusion of the offending object file (srvinit.o
). But we still get the linker error.
.a
and .rel
file. We did this by adding: /c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel
to the command line. We added it both before and after the offending object file. We also tried with the -L
command to force linking by path. All of this results in the same error. This is hard to describe, but when removing the direct link of the libnfs.a
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 -lnfs
to build the command line options, but even without this flag it builds successfully. Without the direct include we get the error:
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
Which is the rtems shell code failing to link. If we add the /c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel
to the end of the build line, then everything succeeds.
To re-iterate, to build the command line functions you need to directly include the nfs .a
and .rel
files, you DO NOT need to use -lnfs
.
So the first and most obvious question is, why is this not linking, even when i explicitly give the library files? 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.
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. How can i check that the lib files include the definitions for my functions and are being linked in the correct order? The compiler is a BSP specific GCC
style compiler provided by RTEMS for the Power PC 5200. It accepts most compiler options that GCC/G++ 4.2 would accept.
Finally, are there any good methods for debugging such a linker issue?.
To make the entire library API available to your C++ code, you could include the library header itself within the extern "C" block, like so:
extern "C" {
#include <librtemsNfs.h>
}
More details on why this is needed is well covered here: Why do we need extern "C"{ #include <foo.h> } in C++?