nc-blog 首页软硬兼施

Compiling Project V on merlin-arm-eabi

日期: 2018-09-20, 23:39   共 5,433 次阅读

要在一个刷了梅林系统的路由器上,编译 Project V

在安装了 entware 以及 opkg/gcc/binutils/bash/vim 等一系列必备环境后,因为 Free Pascal 最新版 3.0.4 没有提供 arm 版,所以下载 Free Pascal 3.0.2 arm-linux-eabi。解压后有 install.sh 安装脚本,但由于 BusyBox的 tar 参数有区别,需要将脚本中的 tar 的 --no-same-owner 参数删去,然后才能执行。安装完,fpc 即可正常运行了。

然后尝试用 fpc 编译 Project V,在连接阶段出错:

...
Linking out/proj_v
/opt/bin/ld: warning: out/link.res contains output sections; did you forget -T?
/opt/bin/ld: cannot find -lpthread
/opt/bin/ld: cannot find -ldl
/opt/bin/ld: cannot find -lc
proj_v.lpr(184) Error: Error while linking
proj_v.lpr(184) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /tmp/mnt/sda1/entware/bin/ppcarm returned an error exitcode

搜索 libpthread 文件后,将其所在的工具链目录加入编译选项

-Fl/tmp/mnt/sda1/entware/lib/gcc/arm-openwrt-linux-gnueabi/6.3.0/

重新编译,却得到了不同的错误信息:

...
Linking out/proj_v
/opt/bin/ld: warning: out/link.res contains output sections; did you forget -T?
/tmp/mnt/sda1/entware/lib/fpc/3.0.2/units/arm-linux/rtl/ucprt0.o: In function `_start':
(.text+0x50): undefined reference to `__uClibc_main'
/tmp/mnt/sda1/entware/lib/fpc/3.0.2/units/arm-linux/rtl/system.o: In function `SYSTEM_$$_SYSTEM_EXIT':
system.pp:(.text.n_system_$$_system_exit+0xc): undefined reference to `_haltproc_eabi'
proj_v.lpr(184) Error: Error while linking
proj_v.lpr(184) Fatal: There were 1 errors compiling module, stopping

错误提示说找不到 __uClibc_main 函数,可知编译器连接的 ucprt0.o 文件使用的是 uClibc,而不是 glibc。然后在 github 中找到了华硕梅林的工具链库,在其中的 am-toolchains/brcm-arm-sdk/hndtools-arm-linux-2.6.36-uclibc-4.5.3/lib 目录中,包含了 uClibc 的相关库,将此目录中的所有文件,放置在一个新目录(/tmp/mnt/sda1/entware/libuc),将之前添加的 fpc 编译参数改为:

-Fl/tmp/mnt/sda1/entware/libuc

再编译错误提示没有找到 libpthreadlibdl

/opt/bin/ld: cannot find -lpthread
/opt/bin/ld: cannot find -ldl

需要在 libuc 目录中为这两个库做软链:

$ln -s libpthread-0.9.32.1.so libpthread.so
$ln -s libdl-0.9.32.1.so libdl.so

再行编译,出现新的错误提示:

Linking out/proj_v
/opt/bin/ld: warning: out/link.res contains output sections; did you forget -T?
/tmp/mnt/sda1/entware/lib/fpc/3.0.2/units/arm-linux/rtl/system.o: In function `SYSTEM_$$_SYSTEM_EXIT':
system.pp:(.text.n_system_$$_system_exit+0xc): undefined reference to `_haltproc_eabi'
proj_v.lpr(184) Error: Error while linking
proj_v.lpr(184) Fatal: There were 1 errors compiling module, stopping
Fatal: Compilation aborted
Error: /tmp/mnt/sda1/entware/bin/ppcarm returned an error exitcode

这个错误提示着实令人郁闷了很久,做了很多尝试都失败了。幸好,Free Pascal 是开源的,看似无解的问题最终可以从源码上找答案。于是去下载了 fpc 3.0.2 的源码,在源码的 rtl/linux/system.pp 文件中,查找到 _haltproc_eabi 相关的部分:

{$if defined(CPUARM) and defined(FPC_ABI_EABI)}
procedure haltproc(e:longint);cdecl;external name '_haltproc_eabi';
{$else}
procedure haltproc(e:longint);cdecl;external name '_haltproc';
{$endif}

只知道了 _haltproc_eabi 定义在外部(不在此文件内)。然后在所有源码文件中搜索 _haltproc_eabi,在 rtl/linux/arm/ 目录中的四个 .as 文件(汇编源码)中找到,但该目录下实际有五个 .as 文件,而唯独之前打过交道的 ucprt0.as(也就是之前提到的调用 uClibcucprt0.o 的汇编源码)中没有 _haltproc_eabi 的定义,这样就能说得通了。通过对比 cprt0.as(使用 glibc 的版本)和 ucprt0.as,在 ucprt0.as 的第155行插入如下代码:

        .globl  _haltproc_eabi
        .type   _haltproc_eabi,#function
_haltproc_eabi:
        ldr r0,=operatingsystem_result
        ldrb r0,[r0]
        mov r7,#248
        swi 0x0
        b _haltproc_eabi

并将修改后的 ucprt0.as 放入 fpc 相应目录中 /tmp/mnt/sda1/entware/lib/fpc/3.0.2/units/arm-linux/rtl,使用 as 将其汇编

$as ucprt0.as -o ucprt0.o

再回到 fpc 编译 Project V,编译通过。

尝试运行,正常。

以上是摸索了不少时间后,整理出来的逻辑,看起来简单不少,但其实整个摸索过程却不会这样有条理。尤其最后将问题定位到 ucprt0.o,还是偶然通过查看连接过程中生成的 link.res 文件找到一丝线索的(link.res 文件明确指出了连接时使用的是 ucprt0.o)。

我爱 Pascal。

简短地址:http://ncblog.net/1483/
«
»
评论
› Derek Xiao @ 2018-09-21 00:07 留言:
为何你如此优秀

› it @ 2018-09-22 05:04 留言:
折腾,换做是我早放弃了,大半天时间可以做很多东西 :roll:

nicrosoft @ 2018-09-22 19:15 留言:
生活就是折腾~

Trackback url | Rss 2.0