我正试图为运行Xenomai (2.5.6/Linux 2.6.35.9)的嵌入式应用程序交叉编译C代码。我从Xenomai示例开始,并尝试使用它们的makefile编译它们,但它们不能正常工作(此外,我想为我的ARM机器交叉编译)。
我遵循了本教程,并找到了一种手动编译源代码的方法,就是这个:
arm-linux-gnueabi-gcc
-I/home/carles/.../xenomai-2.5.6/usr/xenomai/include
-D_GNU_SOURCE -D_REENTRANT -Wall -pipe -D__XENO__
-lnative
-L/home/carles/.../xenomai-2.5.6/usr/xenomai/lib
-lxenomai -lpthread -lrtdk
rtprint.c -o rtprint
其中arm-linux-gnueabi-gcc
是我用来交叉编译ARM的工具链,-I/home/...
是头所在的路径,-L/home/...
是所有库所在的路径。在Xenomai的安装过程中,这些头文件和库被放在那个文件夹中(所以它们是为ARM构建的)。
CFLAGS和LDFLAGS是使用本教程中所述的xeno-config
生成的,但是当我执行该命令时,得到以下链接器错误:
$ arm-linux-gnueabi-gcc -I/home/carles/Develop/xenomai-2.5.6/usr/xenomai/include -D_GNU_SOURCE -D_REENTRANT -Wall -pipe -D__XENO__ -lnative -L/home/carles/Develop/xenomai-2.5.6/usr/xenomai/lib -lxenomai -lpthread -lrtdk rtprint.c -o rtprint
/tmp/ccEpFEIl.o: In function `rt_task_spawn':
rtprint.c:(.text+0x34): undefined reference to `rt_task_create'
rtprint.c:(.text+0x54): undefined reference to `rt_task_start'
/tmp/ccEpFEIl.o: In function `task2_func':
rtprint.c:(.text+0x88): undefined reference to `rt_printf'
rtprint.c:(.text+0x98): undefined reference to `rt_task_set_mode'
rtprint.c:(.text+0xa4): undefined reference to `rt_task_sleep'
rtprint.c:(.text+0xb0): undefined reference to `rt_print_buffer_name'
rtprint.c:(.text+0xd4): undefined reference to `rt_fprintf'
/tmp/ccEpFEIl.o: In function `main':
rtprint.c:(.text+0x11c): undefined reference to `rt_print_auto_init'
rtprint.c:(.text+0x128): undefined reference to `rt_print_init'
rtprint.c:(.text+0x140): undefined reference to `rt_task_shadow'
rtprint.c:(.text+0x180): undefined reference to `rt_task_set_mode'
rtprint.c:(.text+0x18c): undefined reference to `rt_task_sleep'
rtprint.c:(.text+0x190): undefined reference to `rt_print_buffer_name'
rtprint.c:(.text+0x1b0): undefined reference to `rt_printf'
collect2: error: ld returned 1 exit status
所有rt_...
引用都是Xenomai的内核函数,包含在库中。
EDIT:将-lrt
添加到命令行并正确排序参数(即-L
位于命令行末尾)并不能解决问题。为了确保库确实包含这些函数,我执行了objdump
,得到了以下结果:
.../usr/xenomai/lib$ arm-linux-gnueabi-objdump -x librtdk.a | grep rt_print
00000000 *UND* 00000000 __rt_print_init
00000000 *UND* 00000000 __rt_print_exit
00000000 R_ARM_JUMP24 __rt_print_init
00000000 R_ARM_JUMP24 __rt_print_exit
librtdk_la-rt_print.o: file format elf32-littlearm
rw-rw-r-- 1001/1001 6872 Apr 8 16:06 2013 librtdk_la-rt_print.o
00000000 l df *ABS* 00000000 rt_print.c
00000350 g F .text 0000012c rt_print_init
00000744 g F .text 0000003c rt_printf
000007c8 g F .text 00000010 rt_print_auto_init
000007d8 g F .text 00000044 rt_print_cleanup
0000081c g F .text 00000058 rt_print_buffer_name
00000874 g F .text 00000190 __rt_print_init
00000a04 g F .text 00000034 __rt_print_exit
000006b8 R_ARM_CALL rt_print_init
00000850 R_ARM_CALL rt_print_init
我所做的其他可能有助于找到问题的事情:
- 安装xenomai相关软件包(xenomai-runtime, libxenomai1, linux-patch-xenomai) 删除了一个不同的工具链。因为我是第一次在我的目标设备上使用Ångström发行版,所以我有一个专门的工具链。现在,我转移到Debian,使用binutils-arm-linux-gnueabi包中提供的
arm-linux-gnueabi
工具链。编译了一个新的Linux内核和Xenomai(为我的目标设备)。内核版本是2.6.35.9,Xenomai的是2.5.6。我应该使用更早的版本吗?无论如何,Xenomai安装正确,因为我可以运行预编译的程序(具有讽刺意味的是,在Xenomai的安装期间编译,由我自己…)看来这里发生了奇迹。在折腾了两天的Makefiles、Xenomai CFLAGS和链接器配置之后,我已经达到了编译和链接都可以正常工作的地步。
我真的没有做什么特别的事。我没有(un)安装任何包(除了我已经拥有的包),也没有修改任何环境变量,也没有在命令行中添加任何不同的标志或参数。我刚刚重启了电脑。我甚至不是故意这样做的,我昨天刚离开实验室,命令不能完全工作,今天早上一切都工作得很好。很奇怪吗?是的。
我猜这与终端会话中导出的变量有关。我记得我对LD_LIBRARY_PATH、CFLAGS、LDFLAGS等进行了修改,所以我在试图解决问题时一定搞砸了什么。对于那些想知道在运行Linux 2.6.39.5的ARM机器上交叉编译Xenomai(2.5.6)应用程序的最终工作命令的人来说,这是:
arm-linux-gnueabi-gcc file_name.c -o file_name
-I/path/to/target/usr/xenomai/include
-D_GNU_SOURCE -D_REENTRANT -Wall -pipe -D__XENO__
-lnative -lxenomai -lrt -lpthread -lrtdk
-L/path/to/target/usr/xenomai/lib