_sbrk 函数在放置在静态库中时找不到
_sbrk function not found when placed in a static library
我正在为具有 ARM Cortex M4 内核的 stm32f407 微控制器创建一个裸机应用程序。因此,我将亲自交付 _sbrk
等功能的实现。我现在发现,当我尝试创建一个包含 _sbrk
和 link 的静态库以及我的 main.c
到应用程序时,linker 说
"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".
如果我从静态库中取出相同的函数,并将其放入 main.c
,一切 compiles/links/runs 都很好。
我几乎可以肯定这与linker在所有库中读取的顺序有关,并且在读取我自己的静态库时,没有定义_sbrk
还需要,因此被扔掉了,只是在后来 link 编辑了一个标准库时才发现无论如何都需要它。但是,我自己没有指定任何标准库,因此不能更改linking 这些库的顺序。我也试过声明_sbrk
函数为__attribute __ ((__ used__ ))
,以为linker不会把那个函数扔掉,可惜,这并没有解决我的问题
所以我的问题是,如何将 _sbrk
放入静态库,而不将 运行 放入未解析的引用中?
更新: link 最终应用程序的命令是:
C:\PROGRA~2\GNUTOO~147E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
其中 AR10B2~.EXE
解析为 arm-none-eabi-g++.exe
。
添加以下内容使事情成为 link:
-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Th libcmsis_stm.cmsis_stm.a
库是使用以下命令构建的:
C:\PROGRA~2\GNUTOO~147E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj
其中 ARM-NO~2.EXE
解析为 arm-none-eabi-ar.exe
所以还有一个问题:我想把中断向量table,它是一个变量,放到静态库中,但是linker把那个变量扔掉了,因为没有源文件需要那个变量。是否有一种机制可以在 linker 处理 linker 文件中的输出部分之前保留该变量?
当ld
link针对库时,它只会选择那些当时需要的函数(因为引用了来自在 之前 中 link 编辑的翻译单元)。 linker 会忘记所有其他功能(以后不会考虑库)。
因此 linking 顺序很重要。通常你会在你的应用程序对象文件中 link(它引用 malloc
),然后是标准库(它提供 malloc
并反过来引用 _sbrk
),然后你的(应用程序)库,它提供 _sbrk
.
所以 linking 应该看起来像
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp
_sbrk
函数由 libapp
提供。
因此要 linked 的对象的顺序很重要。
更新
如其中一条评论所述:如果您在编译期间使用 -g
添加调试符号,那么您还必须针对 libg link (-lg
)。
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp
我正在为具有 ARM Cortex M4 内核的 stm32f407 微控制器创建一个裸机应用程序。因此,我将亲自交付 _sbrk
等功能的实现。我现在发现,当我尝试创建一个包含 _sbrk
和 link 的静态库以及我的 main.c
到应用程序时,linker 说
"c:/progra~2/gnutoo~1/4947e~1.920/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7e-m/softfp\libg_nano.a(lib_a-sbrkr.o): In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'".
如果我从静态库中取出相同的函数,并将其放入 main.c
,一切 compiles/links/runs 都很好。
我几乎可以肯定这与linker在所有库中读取的顺序有关,并且在读取我自己的静态库时,没有定义_sbrk
还需要,因此被扔掉了,只是在后来 link 编辑了一个标准库时才发现无论如何都需要它。但是,我自己没有指定任何标准库,因此不能更改linking 这些库的顺序。我也试过声明_sbrk
函数为__attribute __ ((__ used__ ))
,以为linker不会把那个函数扔掉,可惜,这并没有解决我的问题
所以我的问题是,如何将 _sbrk
放入静态库,而不将 运行 放入未解析的引用中?
更新: link 最终应用程序的命令是:
C:\PROGRA~2\GNUTOO~147E~1.920\bin\AR10B2~1.EXE -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -ffunction-sections -fno-rtti -fno-exceptions -std=c++11 -fno-use-cxa-atexit -fno-threadsafe-statics -g -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=softfp -mthumb -Wl,--gc-sections -nostartfiles -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/mem.ld" -Wl,-T"C:/Users/Richard Peters/Documents/Projects/Embedded/http_server/ldscripts/sections.ld" "CMakeFiles\http_server.http_server.dir\src\main.cpp.obj" "CMakeFiles\http_server.http_server.dir\src\vectors_stm32f4xx.c.obj" "CMakeFiles\http_server.http_server.dir\http_server.http_server_linker_script_dummy.c.obj" -o "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\http_server.http_server\Generic-stm32f4xx\bin\http_server.http_server.elf" "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
其中 AR10B2~.EXE
解析为 arm-none-eabi-g++.exe
。
添加以下内容使事情成为 link:
-lc -lg "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a"
Th libcmsis_stm.cmsis_stm.a
库是使用以下命令构建的:
C:\PROGRA~2\GNUTOO~147E~1.920\bin\ARM-NO~2.EXE cq "c:\Users\Richard Peters\Documents\Projects\Embedded-install\targets\cmsis_stm.cmsis_stm\Generic-stm32f4xx\lib\libcmsis_stm.cmsis_stm.a" CMakeFiles/cmsis_stm.cmsis_stm.dir/src/cmsis/system_stm32f4xx.c.obj
其中 ARM-NO~2.EXE
解析为 arm-none-eabi-ar.exe
所以还有一个问题:我想把中断向量table,它是一个变量,放到静态库中,但是linker把那个变量扔掉了,因为没有源文件需要那个变量。是否有一种机制可以在 linker 处理 linker 文件中的输出部分之前保留该变量?
当ld
link针对库时,它只会选择那些当时需要的函数(因为引用了来自在 之前 中 link 编辑的翻译单元)。 linker 会忘记所有其他功能(以后不会考虑库)。
因此 linking 顺序很重要。通常你会在你的应用程序对象文件中 link(它引用 malloc
),然后是标准库(它提供 malloc
并反过来引用 _sbrk
),然后你的(应用程序)库,它提供 _sbrk
.
所以 linking 应该看起来像
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -lm -lapp
_sbrk
函数由 libapp
提供。
因此要 linked 的对象的顺序很重要。
更新
如其中一条评论所述:如果您在编译期间使用 -g
添加调试符号,那么您还必须针对 libg link (-lg
)。
arm-none-eabi-gcc ... -o out.elf startup.o main.o -lc -g -lm -lapp