为我的 ARM SoC 交叉编译 GLIBC

tts*_*ras 14 arm cross-compilation glibc

我在 chroot-ed Debianarmel环境中看到了一些非常奇怪的东西。

但首先,有点背景故事......这很长,但问题很复杂,任何潜在的帮助都取决于了解完整的故事。

我有一个运行 Linux 的嵌入式 ARM SoC - 更具体地说,armel是 2.6.17 内核上的Debian Lenny。Debian的发行版本身易于升级到更高版本(sudo apt-get dist-upgrade),因此可以升至速度,到armel的版本 squeeze或甚wheezy

问题是内核是自定义的......有问题的 ARM SoC 不是主线内核的一部分,所以它在 2.6.17 几乎被放弃了。

如果您知道 Linux 和 GLIBC 是如何工作的,那么您已经可以看到问题了——GLIBC 版本是用最低支持的内核版本编译的……这已经超过了 2.6.17。因此,如果我们尝试将 chroot 转换为 Debian 压缩...

$ # From inside the little ARM machine running Debian Lenny
$ sudo debootstrap --arch armel squeeze /squeeze \
     http://ftp.whateverCountry.debian.org/debian
$ sudo -i
# mount -t proc none /squeeze/proc
# mount -t sysfs none /squeeze/sys
# mount -t devpts none /squeeze/dev/pts
# chroot /squeeze
Fatal: Kernel too old
Run Code Online (Sandbox Code Playgroud)

...我们看到来自 GLIBC 的消息squeeze,告诉我们它没有被编译为与这个旧内核 (2.6.17) 一起工作。

同样的问题也发生在 wheezy 上——因为它比squeeze 新——而且实际上从现在开始任何Debian 版本都会发生,因为它们的GLIBC 不能在我的2.6.17 内核上运行。

起初我认为这是一个交易破坏者 - 但后来我意识到理论上我可以重新编译 GLIBC 以与我的 SoC 使用的旧内核一起工作......但我需要一个与用于构建 libc6 的环境相同的环境包在例如 Debian 挤压。

我猜测 GLIBC 的编译和 libc6_2.11.3-4.deb 文件的准备是通过 Debian 众神发明的自动交叉编译机制完成的。

我不是上帝……我也无法在 Google 中找到任何关于如何成为一个的信息 - 即如何使用我的 Core i5 作为主机,使用与打包版本(在 Debian 内部squeeze)完全相同的设置交叉编译 GLIBC使用。

所以我欺骗了它 - 我想出了如何在我的 Core i5 上设置 Debian 的 ARM 版本(一种使用qemu-arm二进制静态版本的技术)。

一旦我在我的 x86 托管版本中 chroot Debian-armel-squeeze,我就能够简单地...

$ cd /var/tmp
$ apt-get source libc6
...
$ # edit this in - compile for my kernel...
$ vi eglibc-2.11.3/debian/sysdeps/linux.mk
...
MIN_KERNEL_SUPPORTED := 2.6.17
...
$ export DEB_BUILD_OPTS="nocheck parallel=1"
$ cd eglibc-2.11.3
$ dpkg-buildpackage -b -d -us -uc
Run Code Online (Sandbox Code Playgroud)

...在 3 小时后(Core i5 托管的 chrooted 版本 Debian-armel-squeeze比本地机器慢得多......)我得到了我的 libc6 .deb 包。在我的 SoC 中完成这个构建可能需要 3 个月的时间,所以我没有抱怨。

回到我真正的 ARM SoC 内部,我将新包的所有 libc 文件 (.so) 复制到了默认的挤压文件中,并尝试 chroot ......

# chroot squeeze/
root@ttsiodras:/# 
Run Code Online (Sandbox Code Playgroud)

是的!有效!(或者看起来是这样)

我的自定义 libc 从 chroot 内部报告:

# /lib/libc.so.6 
GNU C Library (Debian EGLIBC 2.11.3-4) stable release version 2.11.3, by Roland McGrath et al.
Copyright (C) 2009 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.26 system on 2014-10-23.
Available extensions:
        crypt add-on version 2.1 by Michael Glad and others
        GNU Libidn by Simon Josefsson
        Native POSIX Threads Library by Ulrich Drepper et al
        Support for some architectures added on, not maintained in glibc core.
        BIND-8.2.3-T5B
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
Run Code Online (Sandbox Code Playgroud)

事情似乎奏效了——我复制了一个文件,调用了ls......

但是当我尝试使用apt-get从 安装一些应用程序时squeeze,我开始收到...一些意外错误:

# apt-get install indent
Reading package lists... Done
Building dependency tree... Done
The following NEW packages will be installed:
  indent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 110 kB of archives.
After this operation, 516 kB of additional disk space will be used.
Get:1 http://ftp.gr.debian.org/debian/ squeeze/main indent armel 2.2.11-1 [110 kB]
Fetched 110 kB in 0s (236 kB/s)

tar: ./control: Cannot utime: Function not implemented
tar: ./md5sums: Cannot utime: Function not implemented
tar: .: Cannot utime: Function not implemented
tar: Exiting with failure status due to previous errors

dpkg-deb: subprocess tar returned error exit status 2
dpkg: error processing /var/cache/apt/archives/indent_2.2.11-1_armel.deb (--unpack):
 subprocess dpkg-deb --control returned error exit status 2
configured to not write apport reports

rm: cannot remove `/var/lib/dpkg/tmp.ci': Function not implemented

dpkg: error while cleaning up:
 subprocess rm cleanup returned error exit status 1
Errors were encountered while processing:
 /var/cache/apt/archives/indent_2.2.11-1_armel.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)
Run Code Online (Sandbox Code Playgroud)

哦-哦...一堆Function not implemented. 这听起来像是 GLIBC 报告说基本的东西不起作用......

我设法strace的(不要问如何),并想通了,所有的-at功能都失败:openatmkdiratrenameat,等-他们都是报告ENOSYS。

看来我只是部分成功 - 在我的新 GLIBC 中,一些系统调用失败了。

在2.6.17下编译asqueezewheezeGLIBC是不可能的吗?

任何关于我做错了什么和/或如何继续的想法/指示将不胜感激......

tts*_*ras 8

我做到了 :-)

我基本上遵循了 Gilles 的建议并决定正确地做:即管理 GLIBC 的完整交叉编译。我从 crosstool-ng 开始,最初很失望 - 看到它不支持我的旧内核。不过,我一直坚持下去 - 手动编辑由 crosstool-ng 保存的配置文件,以对默认的 arm-gnueabi 构建配置进行如下更改:

$ ct-ng arm-unknown-linux-gnueabi
$ ct-ng menuconfig
...
$ vi .config
$ cat .config
...
CT_KERNEL_VERSION="2.6.17"
CT_KERNEL_V_2_6_17=y
CT_LIBC_VERSION="2.13"
CT_LIBC_GLIBC_V_2_13=y
CT_LIBC_GLIBC_MIN_KERNEL_VERSION="2.6.9"
CT_LIBC_GLIBC_MIN_KERNEL="2.6.9
...
$ ct-ng +libc
Run Code Online (Sandbox Code Playgroud)

经过无数次测试和失败的尝试,上述更改做到了 - 我得到了一个可以与我的内核一起使用的 GLIBC 编译版本,并将生成的文件复制到我的 Debian Lenny ARM 机器上:

$ cd .build/arm-unknown-linux-gnueabi/build/build-libc-final/
$ tar zcpf newlibc.tgz $(find . -type f -iname \*.so)
$ scp newlibc.tgz root@mybook:.
Run Code Online (Sandbox Code Playgroud)

我一路走过去,通过挤压:我解压了一个 /wheezy 然后 - 非常小心地 -/wheezy用我自己的覆盖了 armel-debootstrapped 的 GLIBC 版本:

# # In the ARM machine
# cd /wheezy/lib/arm-linux-gnueabi/
# mv /var/tmp/ohMyGod/libc.so libc-2.13.so
# mv /var/tmp/ohMyGod/rt/librt.so librt-2.13.so
...
Run Code Online (Sandbox Code Playgroud)

...等,确保我没有错过任何共享库。

最后,我复制了lddldconfig二进制文件(它们也是 GLIBC 的一部分),并在我的 /wheezy 中 chroot。

有效。

我只能假设从 x86 内的 chroot-ed 'qemu-arm' 仿真编译 GLIBC,不知何故搞砸了 - 也许configure进程从运行环境中检测到一些东西 - 而交叉编译不能被误导.

所以我很自然地进入下一步,并使用一个 busybox-static shell用 wheezy替换了我旧 lenny 的 {/bin,/sbin,...} 文件夹 - 并重新启动到我全新的 Wheezy :-)

我在此声明我的 WD MyBook World Edition是地球上唯一运行 Debian Wheezy 的 :-) 如果其他人有兴趣,我可以将 libc 文件的 tarball 上传到某个地方。