对 `nfsInit` 的未定义引用
Undefined reference to `nfsInit`
我目前正在尝试将 NFS 服务器集成到 POWER PC 5200
RTEMS 4.9.2
上的某些代码 运行 中。这将很难简洁地解释,所以请耐心等待。
RTEMS NFS
目前 RTEMS 通过 nfs.c 文件实现了一个 NFS 客户端。为了激活命令行界面并能够使用 mount -t nfs ...
选项,您需要将 #define CONFIGURE_SHELL_MOUNT_NFS
添加到您的配置文件中,并使用 -lnfs
添加 link rtems nfs 文件。有关详细信息,请参阅 here。正确地执行此操作允许我们实现 RTEMS nfs 客户端,并且我们可以从命令行挂载远程驱动器。
直接使用 RTEMS NFS 客户端
我们没有在我们的程序中公开 RTEMS 命令行,所以我们希望能够直接使用 nfs 接口。 RTEMS 库提供 librtemsNfs.h
,其中包含用于实现 nfs 客户端的函数。这些函数的实现在 nfs.c
中,它被编译为创建 2 个库中的 1 个:
libnfs.a
nfs.rel
两者都需要构建。作为我们代码的一部分,我们使用函数 nfsInit(...
,它在 librtemsNfs.h
中声明并在 nfs.c
中定义。
错误
所以错误很明显。当我们构建时,我们得到 linker 错误:
D:\Git\nfs_stuff\Src\RTEMS_proj/init/srvinit.cpp:453: undefined reference to `nfsInit(int, int)'
collect2: ld returned 1 exit status
尝试 link 这些库
为了link这些我们尝试了多种方法。我们有一个 makefile
但为了让每个人都更容易,我将展示命令行构建中出现的内容。我们尝试过:
- 推荐的方法是 link 与 -lnfs (source - an old question) 并且这样做会产生一个很好的长而复杂的构建命令:
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
我们的编译和 link 命令在包含有问题的目标文件 (srvinit.o
) 之前有 -lnfs
。但是我们仍然得到 linker 错误。
- 我试图通过路径 link 直接到
.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
命令强制按路径 linking。所有这些都会导致相同的错误。
一些其他信息
这很难描述,但是当删除 libnfs.a
文件的直接 link 时,即使不直接使用 nfs,我们也失去了构建的能力。 IE。内部 RTEMS 文件无法相互 link。这很奇怪,在我看来你应该只需要 -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\c00\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\c00\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 代码失败 link。如果我们将 /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
.
问题
所以第一个也是最明显的问题是,为什么这不是 linking,即使我明确提供了库文件?我对此的看法是,也许这些文件不包括我正在尝试使用的功能的定义。但这在其他信息部分是不可信的,因为我需要它们 link RTEMS OS 本身的功能。
我知道这也很难给出一个直接的答案,因为如果没有 PC 和所有安装的编译器等,它将很难重现。我如何检查 lib 文件包括我的函数的定义并且link以正确的顺序编辑?编译器是 RTEMS 为 Power PC 5200 提供的 BSP 特定 GCC
风格的编译器。它接受大多数GCC/G++ 4.2 会接受的编译器选项。
最后,有什么好的方法可以调试这样的 linker 问题吗?。
RTEMS 4.9.2 库代码尚未准备好 link 使用 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);
}
要使整个库 API 可用于您的 C++ 代码,您可以将库 header 本身包含在 extern "C" 块中,如下所示:
extern "C" {
#include <librtemsNfs.h>
}
这里详细介绍了为什么需要这样做:Why do we need extern "C"{ #include <foo.h> } in C++?
我目前正在尝试将 NFS 服务器集成到 POWER PC 5200
RTEMS 4.9.2
上的某些代码 运行 中。这将很难简洁地解释,所以请耐心等待。
RTEMS NFS
目前 RTEMS 通过 nfs.c 文件实现了一个 NFS 客户端。为了激活命令行界面并能够使用 mount -t nfs ...
选项,您需要将 #define CONFIGURE_SHELL_MOUNT_NFS
添加到您的配置文件中,并使用 -lnfs
添加 link rtems nfs 文件。有关详细信息,请参阅 here。正确地执行此操作允许我们实现 RTEMS nfs 客户端,并且我们可以从命令行挂载远程驱动器。
直接使用 RTEMS NFS 客户端
我们没有在我们的程序中公开 RTEMS 命令行,所以我们希望能够直接使用 nfs 接口。 RTEMS 库提供 librtemsNfs.h
,其中包含用于实现 nfs 客户端的函数。这些函数的实现在 nfs.c
中,它被编译为创建 2 个库中的 1 个:
libnfs.a
nfs.rel
两者都需要构建。作为我们代码的一部分,我们使用函数 nfsInit(...
,它在 librtemsNfs.h
中声明并在 nfs.c
中定义。
错误
所以错误很明显。当我们构建时,我们得到 linker 错误:
D:\Git\nfs_stuff\Src\RTEMS_proj/init/srvinit.cpp:453: undefined reference to `nfsInit(int, int)'
collect2: ld returned 1 exit status
尝试 link 这些库
为了link这些我们尝试了多种方法。我们有一个 makefile
但为了让每个人都更容易,我将展示命令行构建中出现的内容。我们尝试过:
- 推荐的方法是 link 与 -lnfs (source - an old question) 并且这样做会产生一个很好的长而复杂的构建命令:
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
我们的编译和 link 命令在包含有问题的目标文件 (srvinit.o
) 之前有 -lnfs
。但是我们仍然得到 linker 错误。
- 我试图通过路径 link 直接到
.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
命令强制按路径 linking。所有这些都会导致相同的错误。
一些其他信息
这很难描述,但是当删除 libnfs.a
文件的直接 link 时,即使不直接使用 nfs,我们也失去了构建的能力。 IE。内部 RTEMS 文件无法相互 link。这很奇怪,在我看来你应该只需要 -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\c00\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\c00\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 代码失败 link。如果我们将 /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
.
问题
所以第一个也是最明显的问题是,为什么这不是 linking,即使我明确提供了库文件?我对此的看法是,也许这些文件不包括我正在尝试使用的功能的定义。但这在其他信息部分是不可信的,因为我需要它们 link RTEMS OS 本身的功能。
我知道这也很难给出一个直接的答案,因为如果没有 PC 和所有安装的编译器等,它将很难重现。我如何检查 lib 文件包括我的函数的定义并且link以正确的顺序编辑?编译器是 RTEMS 为 Power PC 5200 提供的 BSP 特定 GCC
风格的编译器。它接受大多数GCC/G++ 4.2 会接受的编译器选项。
最后,有什么好的方法可以调试这样的 linker 问题吗?。
RTEMS 4.9.2 库代码尚未准备好 link 使用 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);
}
要使整个库 API 可用于您的 C++ 代码,您可以将库 header 本身包含在 extern "C" 块中,如下所示:
extern "C" {
#include <librtemsNfs.h>
}
这里详细介绍了为什么需要这样做:Why do we need extern "C"{ #include <foo.h> } in C++?