使用 nano.specs 时 libc.a 和 libc_nano.a 之间的多个函数定义

Posted

技术标签:

【中文标题】使用 nano.specs 时 libc.a 和 libc_nano.a 之间的多个函数定义【英文标题】:Multiple definitions of functions between libc.a and libc_nano.a while using nano.specs 【发布时间】:2021-09-23 22:38:00 【问题描述】:

我正在为 STM32 微控制器构建一个项目,其中包含一个 .cpp 文件,其中包含标准 C++ 库中的一些结构,例如 std::vector、std::string 等。我没有使用 std:: cout 或 std::malloc。我需要使用简化的 C/C++ 库并将 -specs=nano.specs 标志传递给链接器。我使用arm-none-eabi交叉编译工具编译链接,使用cmake生成构建文件,使用ninja构建。

我不断收到一个链接器错误,上面写着(例如),

/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sinit_lock_release':

findfp.c:(.text.__sinit_lock_release+0x0): multiple definition of `__sinit_lock_release'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit_lock_release+0x0): first defined here

    我对这个错误有点困惑,因为我认为 specs=nano.specs 标志用 libc_nano.a 替换了 libc.a,但这里看起来两个库都在使用,并且一些函数在 libc_nano 中重新定义.a.

    如果我使用-nostdlibs 标志,我会收到undefined reference to 错误,例如:

/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/WM_MainMicro.elf.dir/Core/Src/Components/message_table.cpp.obj: in function `std::vector<_app_msg, std::allocator<_app_msg> >::_M_check_len(unsigned int, char const*) const':
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/arm-none-eabi/include/c++/9.3.1/bits/stl_vector.h:1756: undefined reference to `std::__throw_length_error(char const*)'
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: CMakeFiles/WM_MainMicro.elf.dir/Core/Src/Components/message_table.cpp.obj: in function `__gnu_cxx::new_allocator<_app_msg>::allocate(unsigned int, void const*)':

    如果我不使用 nano.specs,我的 elf 文件对于可用的 Flash 来说太大了。 (这就是为什么我首先要使用简化的 C/C++ 库)

    我发现了一个名为-allow-multiple-definitions 的标志,它允许我毫无问题地进行编译。从我在文档中找到的内容来看,这意味着链接器将允许一个符号的多个定义,并将使用第一个定义的符号。这是否意味着链接器将使用首先链接的库中的符号?如果是这样,它将在 libc.a 和 libc_nano.a 的符号之间使用哪个符号? (考虑到 libc.a 似乎默认包含在内)

编辑:在此处发布整个链接器错误:

/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `_cleanup_r':
findfp.c:(.text._cleanup_r+0x0): multiple definition of `_cleanup_r'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text._cleanup_r+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sfmoreglue':
findfp.c:(.text.__sfmoreglue+0x0): multiple definition of `__sfmoreglue'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sfmoreglue+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `_cleanup':
findfp.c:(.text._cleanup+0x0): multiple definition of `_cleanup'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text._cleanup+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sfp_lock_acquire':
findfp.c:(.text.__sfp_lock_acquire+0x0): multiple definition of `__sfp_lock_acquire'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp_lock_acquire+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sfp_lock_release':
findfp.c:(.text.__sfp_lock_release+0x0): multiple definition of `__sfp_lock_release'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp_lock_release+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sinit_lock_acquire':
findfp.c:(.text.__sinit_lock_acquire+0x0): multiple definition of `__sinit_lock_acquire'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit_lock_acquire+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sinit_lock_release':
findfp.c:(.text.__sinit_lock_release+0x0): multiple definition of `__sinit_lock_release'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit_lock_release+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sinit':
findfp.c:(.text.__sinit+0x0): multiple definition of `__sinit'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sinit+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__sfp':
findfp.c:(.text.__sfp+0x0): multiple definition of `__sfp'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__sfp+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__fp_lock_all':
findfp.c:(.text.__fp_lock_all+0x0): multiple definition of `__fp_lock_all'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__fp_lock_all+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o): in function `__fp_unlock_all':
findfp.c:(.text.__fp_unlock_all+0x0): multiple definition of `__fp_unlock_all'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-findfp.o):findfp.c:(.text.__fp_unlock_all+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-snprintf.o): in function `_snprintf_r':
snprintf.c:(.text._snprintf_r+0x0): multiple definition of `_snprintf_r'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-snprintf.o):snprintf.c:(.text._snprintf_r+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-snprintf.o): in function `snprintf':
snprintf.c:(.text.snprintf+0x0): multiple definition of `snprintf'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-snprintf.o):snprintf.c:(.text.snprintf+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-nano-svfprintf.o): in function `__ssprint_r':
nano-vfprintf.c:(.text.__ssprint_r+0x0): multiple definition of `__ssprint_r'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-svfiprintf.o):vfprintf.c:(.text.__ssprint_r+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-nano-svfprintf.o): in function `_svfprintf_r':
nano-vfprintf.c:(.text._svfprintf_r+0x0): multiple definition of `_svfprintf_r'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-svfprintf.o):vfprintf.c:(.text._svfprintf_r+0x0): first defined here
/usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-nano-svfprintf.o): in function `_svfprintf_r':
nano-vfprintf.c:(.text._svfprintf_r+0x0): multiple definition of `_svfiprintf_r'; /usr/local/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc.a(lib_a-svfiprintf.o):vfprintf.c:(.text._svfiprintf_r+0x0): first defined here

【问题讨论】:

如果您发布整个命令行而不仅仅是错误,可能更容易诊断。 你应该试试@nhatnq 的答案。 '2' 也是如此。在您使用-nostdlibs 的地方,您可以按照Undefined..cxa-end-cleanup 添加-lsupc++-nostdlibs 禁止链接超出您的要求。您仍然可以尝试提供对库的直接引用。此外,当您尝试在资源受限的平台上进行编码时,您可能真的很想生成一个地图文件来查看占用空间的内容。 【参考方案1】:

您可以尝试使用-nolibc 选项而不是-nostdlibs。我认为问题在于使用原始选项它不会同时使用标准 C/C++ 库。在您的情况下,您只想替换 libc

-nolibc

不要使用 C 库或与之紧密耦合的系统库 链接时。仍然与启动文件、libgcc 或工具链链接 提供语言支持库,例如 libgnat、libgfortran 或 libstdc++ 除非也使用了阻止它们包含的选项。 这通常会从链接命令行中删除 -lc,以及 通常与它一起使用并在以下情况下变得毫无意义的系统库 假设没有 C 库,例如 -lpthread 或 -lm in 一些配置。这适用于裸板目标时 确实没有C库

【讨论】:

以上是关于使用 nano.specs 时 libc.a 和 libc_nano.a 之间的多个函数定义的主要内容,如果未能解决你的问题,请参考以下文章

gcc默认链接到libc.a或libc.so吗?

CLion 在stm32 环境下使用重定向printf方法,导致float数据无法输出的解决办法

CLion 在stm32 环境下使用重定向printf方法,导致float数据无法输出的解决办法

musl 无法将 libc.a 链接到共享库

Android NDK编译如何强制使用libc++.a的静态链接库

libc.a与libm.a包含多少文件