我有一堆arm组件,C和C ++文件。 gcc正在尝试链接它们,但这些是用于嵌入式项目的。
我没有使用任何外部库,所有正在使用的代码都是由我编写的。似乎发生了错误,因为我在int kernel_main(void)
中定义了一个名为main.c
的函数,该函数试图调用set_LED(int value)
中定义的mailbox.cpp
,其中包含头mailbox.h
(我确实在main.c文件中包含了头文件)。
确切的错误是:
undefined reference to `__aeabi_unwind_cpp_pr1'
我创建项目的方式是: - 将所有源文件(.s,.c,.cpp)编译为目标文件(.o)而不链接(-c),然后使用自定义链接器将它们全部链接在一起脚本。
编辑:我将添加一些信息以使事情更清楚。
首先更改所有文件,以便所有文件都是C文件(没有cpp扩展名)产生:
undefined reference to `set_LED'
问题本身不太可能是名称错误,它可能与CPP和C差异无关。
问题很可能是链接器问题
这是构建过程:
编译c文件,例如:
arm-none-eabi-g++ -O0 -march=armv8-a source/MainFiles/mailbox.cpp -nostartfiles -c -o objects/MainFiles/mailbox.o
(除了使用g ++而不是gcc之外,编译C ++文件是完全相同的)
链接一切:
arm-none-eabi-ld object1 object2... -o build/kernel.elf -T ./source/kernel.ld -I include_directory_1 -I include_directory_2 -L include_directory_1 -L indlude_directory_2
包含目录是当前目录下的所有目录
编辑:错误回来了。忽略与名称重整相关的此问题的部分。我需要解决的错误是:
./objects/Hardware/mailbox.o:(.ARM.exidx+0x18): undefined reference to `__aeabi_unwind_cpp_pr1'
到目前为止,我所知道的是,这与解除堆栈和异常有关。似乎函数是在libgcc中定义的。但是我使用了-nostdlib
,我省略了它,并且在这两种情况下错误仍然存在。我尽可能地尝试将文件扩展名更改为.c,并尽可能将.cpp更改为.cpp,总是存在错误。
只有我有1个cpp文件并且我的其余文件都是C文件(这不再是真的,我试过),它才得到修复。再次触发错误的原因是我正在重构代码,我想将一些函数移动到新文件中。
换句话说,在不删除单个文件的情况下,在mailbox.cpp中声明一个名为wait(uint32_t time)
的函数,可以在一个名为time.c(或cpp)的文件中声明它,并使用它的相应头声明并在mailbox.cpp中包含标题。注意我在移动函数时不删除文件我只是删除每个文件中的函数声明。
添加这样的存根:
void __aeabi_unwind_cpp_pr1()
{
}
修复问题和代码工作。但我不喜欢这个解决方案。我不想在我的代码中神秘地调用无用的存根。我不需要也不想在我当前的实现中使用这个函数,如何告诉编译器或链接器他们要省略他们正在做什么需要这个函数?
您可以参考此函数,该函数属于GCC的C ++运行时。这是异常处理的一部分。无论你做什么,听起来有点疯狂,但无论如何,如果你真的知道自己在做什么,你可以做到这一点。您必须链接到C ++运行时库。而已。链接“libstdc ++”。
关于set_LED
我也相信它只是关于C ++的修改,正如Justin J在另一个答案中提到的那样。
我在混合使用C和C ++时已经看到了这一点。由于名称重整,符号将在内部具有不同的名称,具体取决于源文件的类型。
如果'set_LED'的源是一个c文件,请在原型周围的标题中使用以下内容,看看它是否有帮助。
#ifdef __cplusplus
extern "C" {
#endif
// function prototypes here
#ifdef __cplusplus
}
#endif
解决方案非常简单。事实证明,默认情况下启用了异常(生成调用__eabi_unwind_cpp_pr1
的代码)。要禁用它们,只需将:-fno-exceptions
作为参数传递给gcc / g ++编译器,问题就解决了。
还请在-fno-exceptions中添加前缀“-shared”,不带引号。我正在使用ARM GCC版本