未明确引用`nfsInit`

时间:2016-02-02 21:48:26

标签: c++ gcc linker makefile rtems

我目前正在尝试将NFS服务器集成到RTEMS 4.9.2POWER PC 5200上运行的某些代码中。要简明扼要地解释一下这对我来说很难。

RTEMS NFS

目前,RTEMS通过nfs.c文件实现NFS客户端。要激活命令行界面并能够使用mount -t nfs ...选项,您需要将#define CONFIGURE_SHELL_MOUNT_NFS添加到配置文件中,并将rtems nfs文件与-lnfs链接。有关详细信息,请参阅here。正确地执行此操作允许我们实现RTEMS nfs客户端,并且从命令行我们可以安装远程驱动器。

直接使用RTEMS NFS客户端

我们不在程序中公开RTEMS命令行,因此我们希望能够直接使用nfs接口。 RTEMS库提供librtemsNfs.h,其中包含用于实现nfs客户端的函数。这些函数的实现在nfs.c中,它被编译为创建2个库中的一个:

  1. libnfs.a
  2. nfs.rel
  3. 两者都需要构建。作为我们代码的一部分,我们使用的函数nfsInit(...librtemsNfs.h中声明并在nfs.c中定义。

    错误

    所以错误非常明显。当我们构建时,我们得到链接器错误:

    D:\Git\nfs_stuff\Src\RTEMS_proj/init/srvinit.cpp:453: undefined reference to `nfsInit(int, int)'
    collect2: ld returned 1 exit status
    

    尝试链接这些库

    为了链接这些,我们尝试了多种方法。我们有makefile但为了让每个人都更容易,我将展示命令行构建中出现的内容。我们尝试过:

    1. 推荐的方法是链接-lnfs(source - an old question),这样做会产生一个很好的长而复杂的构建命令:
    2.   

      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

      在包含违规对象文件(-lnfs)之前,我们的编译和链接命令有srvinit.o。但是我们仍然会收到链接器错误。

      1. 我尝试将路径直接链接到.a.rel文件。我们通过在命令行中添加:/c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel来完成此操作。我们在违规对象文件之前和之后添加了它。我们还尝试使用-L命令强制按路径链接。所有这些都会导致相同的错误。
      2. 其他一些信息

        这很难描述,但是当删除libnfs.a文件的直接链接时,即使没有直接使用nfs,我们也无法构建。即。内部RTEMS文件无法相互链接。这很奇怪,在我看来你应该只需要-lnfs来构建命令行选项,但即使没有这个标志它也能成功构建。如果没有直接包含,我们会收到错误:

        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
        

        哪个rtems shell代码无法链接。如果我们将/c/rtems-4.9/powerpc-rtems4.9/5200/lib/libnfs.a /c/rtems-4.9/powerpc-rtems4.9/5200/lib/nfs.rel添加到构建行的末尾,那么一切都会成功。

        要重新迭代,要构建命令行函数,您需要直接包含nfs .a.rel文件,您不需要使用-lnfs

        问题

        所以第一个也是最明显的问题是,为什么这不是链接,即使我明确地给出了库文件?我对此的想法是,也许这些文件不包含我试图使用的功能。但是这在其他信息部分中是不可信的,因为我需要它们来连接RTEMS OS本身的功能。

        我知道这也很难给出一个直接的答案,因为如果不安装PC和所有编译器等,它将是非常不可复制的。我如何检查lib文件是否包含我的函数和正确的顺序链接?编译器是RTEMS为Power PC 5200提供的BSP特定GCC样式编译器。它接受GCC / G ++ 4.2可接受的大多数编译器选项。

        最后,是否有任何调试此类链接器问题的好方法?

2 个答案:

答案 0 :(得分:1)

RTEMS 4.9.2库代码尚未准备好与C ++编译器链接,因此它具有不同的ABI。

您需要修改librtemsNfs.h以使用extern“C”{}块来定义库。

或者,如果您不想修改RTEMS源代码,请以这种方式直接在代码中声明这些函数:

extern "C" {
   int rpcUdpInit(void);
   int nfsInit(int smallPoolDepth, int bigPoolDepth);
   int nfsMount(char *uidhost, char *path, char *mntpoint);
}

答案 1 :(得分:1)

要使整个库API可用于您的C ++代码,您可以将库标题本身包含在extern“C”块中,如下所示:

extern "C" {
    #include <librtemsNfs.h>
}

此处详细介绍了有关原因的详细信息:Why do we need extern "C"{ #include <foo.h> } in C++?