使用avr-gcc编译器/链接器对链接的avrfix库中函数的未定义引用

undefined references to functions in linked avrfix library using avr-gcc compiler/linker

本文关键字:链接 函数 引用 未定义 avrfix avr-gcc 编译器 使用      更新时间:2023-10-16

我正在尝试在项目中使用avrfix库,使用Eclipse(v4.2.2)作为IDE,使用avr-gcc作为编译器。头文件(avrfix.h)和库文件(libavrfix.a)都包含在同一目录中,该目录位于项目的搜索路径和链接器的库搜索路径中。编译时,我得到以下错误:

D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:359: undefined reference to `lsincoslk(long, long*)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:360: undefined reference to `lsincoslk(long, long*)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:361: undefined reference to `lmullkD(long, long)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:362: undefined reference to `lmullkD(long, long)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:365: undefined reference to `lmullkD(long, long)'
./HMC5883/HMC5883.o:D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:367: more undefined references to `lmullkD(long, long)' follow
./HMC5883/HMC5883.o: In function `HMC5883::Calc_Heading(long, long)':
D:DocumentsArduinoIMU_KalmanRelease/../HMC5883/HMC5883.cpp:369: undefined reference to `latan2lk(long, long)'
make: *** [IMU_Kalman.elf] Error 1

我理解这意味着链接器没有正确查找和链接有问题的函数(lsincoslk、lmullkD、lata2lk)。这些函数应该位于avrfix库中。完整地说,这里是使用的链接器调用:

avr-gcc -Os -Wl,--gc-sections  -Wl,-Map,"IMU_Kalman.map",--cref --export-all-symbols -L"D:DocumentsArduinoIMU_Kalmanavrfix" -L"D:DocumentsArduinoIMU_KalmanBoard_Support_Library" -mmcu=atmega328p  -o"IMU_Kalman.elf"  ./Wire/Wire.o ./Wire/twi.o  ./SPI/SPI.o  ./MPU6000/MPU6000.o  ./Kalman_Filters/GyroKalman.o  ./HMC5883/HMC5883.o  ./GlobalVariables.o ./IMU_Kalman.o   -lavrfix -lArduino_Duemilanove_w__ATmega328 -lm

这里的重要部分是包含了-lavrfix命令。我知道链接器能够找到那个库,因为如果我尝试拼写错误的avrfix,它会出现找不到库的错误,而不是上面提到的错误。值得一提的是,我使用了我认为相同的方法,成功地包含了libArduino_Duemilanove_w__ATmega328.a库。

当我查看编译器生成的.map文件时,我确实看到了来自Arduino_Duemilanove_w__ATmega328库的几个函数,正如预期的那样(例如malloc)。然而,avrfix库中似乎没有任何函数或对象进入地图。在.map文件中搜索"avrfix"只会产生一行内容:

LOAD D:DocumentsArduinoIMU_Kalmanavrfixlibavrfix.a

链接顺序可能有问题吗?我不知道这里可能出了什么问题。是否由于某种原因,avrfix库与我正在使用的avr-gcc编译器不兼容?我也有点不熟悉二进制解析器(或者它们是否与我的问题有关),但我已经尝试在项目属性的C/C++构建->设置->二进制解析器选项卡中选择多个不同的解析器(包括GNU Elf Parser)。有关更多信息,我在github上有整个项目(尽管这是一项正在进行的工作,处于早期阶段)。我试着在其他线程中寻找帮助,但在我的应用程序中似乎找不到太多特定于avrfix库的信息。在另一个线程中,我发现了在链接器调用中使用--export-all-symbol选项的建议,但这似乎对我的情况没有帮助。

如果有人知道发生了什么事,请帮忙!不要犹豫,向我索取更多信息。

问候,

Paul

对"lsincoslk(long,long*)"的未定义引用

这是对C++损坏名称的引用。

libavrfix.a很可能将该符号定义为未修饰的C名称。你可以通过运行来验证这一点

avr-readelf -Ws libavrfix.a | grep lsincoslk

如果你看到NNNN T _Z9lsincoslklPl,我的猜测是错误的。但如果你看到NNNN T lsincoslk,那么我的猜测是正确的。

看看这个版本的avrfix.h,我发现它缺少适当的extern "C"保护。当您将此标头包含到C++中时,必须执行以下操作:

extern "C" {
#include "avrfix.h"
}

如果avrfix开发人员关心C++,您就不必这么做了。你可以给他们发一个补丁到avrfix.h。补丁应该在开始时添加以下内容:

#ifdef __cplusplus
extern "C" {
#endif

最后这个:

#ifdef __cplusplus
}
#endif