我买了一台龙芯2F的笔记本来当玩具。
买回来发现,这台笔记本上没法安装软件,因为既没有软件仓库,也没有GCC。
因此需要构建交叉工具链和构建本地工具链。
下面是我研究如何搞定着一切的笔记。
工具链组件包含:
binutils: 用于操作二进制文件的实用程序集合。包括ar, as, objdummp, objcopy
gcc:
glibc: 所有的应用程序都将链接到C库。还有一个流行的适合于嵌入式的精简libc是uclibc。
从头设置交叉工具链是一件很麻烦的任务,它包括:
- 下载源码
- 打补丁
- 配置
- 编译
- 设置头文件
- 安装
- 等等等
我打算使用buildroot。
下载buildroot: http://www.buildroot.org/download.html
下载并安装cygwin。
Buildroot里面有一个很好的配置工具,与Linux内核中很类似。
第一步运行配置助手
yueew@FaceMachine /cygdrive/e/FaceProjs/buildroot-2015.05
$make menuconfig百度里龙芯的细节资料较少,为求准确,
我只好到龙芯官方网站翻http://www.loongson.cn/product_info.php?id=23 ,
龙芯Loongson 2F的指令集(ISA)是MIPS III。
但是在menu里,Target Architecture里找不到MIPS III,这种老掉牙的架构估计已经被buildroot废弃了。
在百度里用标题搜索title:(mips III) buildroot也没有结果,这时候只能上yahoo了。
据说配置一下以下地方就可以了。但是配了之后还是没有MIPS III供选择。难道相关代码都删掉了?
Build options -> Show packages that are deprecated or obsolete
这是什么节奏,是龙芯太落伍?还是......?
这时候我只能去buildroot官方网站去看每个版本的改动历史,打算找到一个能用的老版本。
http://www.buildroot.org/news.html
http://git.buildroot.net/buildroot/plain/CHANGES?id=2015.05
终于找到相关描述:
2015.02-rc1, Released February 8th, 2015
Architectures: Freescale E5500 and E6500 PowerPC support added, deprecated MIPS 1/2/3/4 support removed.最后,我下载了buildroot-2014.11.tar.bz2,这个是能用的最新版本了。Target Architecture Variant里面终于可以选择MIPS III。
到这里,万里长征才走完了第一步。
问题又来了,虽然MIPS III是64位的,但是也可以运行在32位兼容模式。
我编出来的编译器或者应用程序的ABI要与龙芯笔记本上现在运行glibc动态库的ABI匹配。
ABI不一致的程序没法链接在一起运行,因为寄存器约定不一致。
于是我在龙芯笔记本上运行which ls,找到系统实用程序ls的路径/bin/ls,然后又执行file /bin/ls。
这样可以看到ls程序(每个命令其实就是一个程序)的执行格式。
yee@Loong:~$ file /bin/ls
/bin/ls: ELF 32-bit LSB executable, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, with unknown capability 0xf41 = 0x756e6700, stripped这里又要分析了,每个字段是什么含义。
这里可以看到,32-bit LSB说明龙芯笔记本上的可执行程序是32位小端的。
因此,Target Architecture选MIPS (little endian),Target Architecture Variant选mips III。
然后是配置Toolchain:
Kernel Headers版本选择2.6.x,这个信息也是从刚才的file命令里看到的。
C library选什么呢?首先要知道龙芯笔记本上用的是哪种libc。这个怎么看呢?
首先,打算看龙芯笔记本上是否已经有libc相关的头文件。结果没有找到。
这里用了一个小技巧2>/dev/null来关闭标准错误。否则访问很多目录会报权限不够的错误,看着眼花。
yee@Loong:/$ find -name "*stdio.h*" 2>/dev/null
./usr/lib/perl/5.10.0/CORE/nostdio.h然后百度查到使用ldd命令可以看到程序连接的动态库。通过readelf -d /bin/ls也能看到程序连接的动态库。
yee@Loong:/$ ldd /bin/ls
librt.so.1 => /lib/librt.so.1 (0x2aaec000) libselinux.so.1 => /lib/libselinux.so.1 (0x2ab08000) libacl.so.1 => /lib/libacl.so.1 (0x2ab38000) libc.so.6 => /lib/libc.so.6 (0x2ab50000) libpthread.so.0 => /lib/libpthread.so.0 (0x2acc8000) /lib/ld.so.1 (0x2aaa8000) libdl.so.2 => /lib/libdl.so.2 (0x2acf4000) libattr.so.1 => /lib/libattr.so.1 (0x2ad08000)直接在shell下运行libc.so.6可以看到龙芯笔记本用的是glibc,还可以得到libc library版本是2.7。yee@Loong:/$ /lib/libc.so.6GNU C Library stable release version 2.7, by Roland McGrath et al. #这个很重要,因为不同版本的libc头文件定义不一样。Copyright (C) 2007 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 APARTICULAR PURPOSE.Compiled by GNU CC version 4.3.2. #这个无所谓,反正编译出来的二进制都符合统一的ABI标准Compiled on a Linux >>2.6.27.7<< system on 2009-05-31. #这个应该无所谓,否则与cat /proc/version不一致怎么解释?有待研究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-T5BFor bug reporting instructions, please see:<http://www.gnu.org/software/libc/bugs.html>.yee@Loong:/$ cat /proc/version
#和编译glibc用的GCC版本不一致,这个无所谓,因为他们之间通信不需要链接,是通过系统调用。
Linux version 2.6.27.1 (huhb@debian) (gcc version 3.4.6) #643 Sun Jan 3 11:38:33 CST 2010 yee@Loong:/$ file /lib/libc.so.6/lib/libc.so.6: symbolic link to `libc-2.7.so'yee@Loong:/$ file /lib/libc-2.7.so/lib/libc-2.7.so: ELF 32-bit LSB shared object, MIPS, MIPS-I version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.8, with unknown capability 0xf41 = 0x756e6700, stripped从这篇文章的一系列命令输出里,我们可以看到好几个不同的Linux版本号和GCC版本号。
一旦配置完成,配置工具将产生一个.config文件来存储你的配置。它将被Makefile所使用。
配置完毕后开始编译,这里使用tee命令记录编译日志。
make | tee -a loongson.log
通常,此命令将执行以下步骤:
- 按照需要下载源文件;
- 如果使用内部(internal)工具链则,配置、创建和安装交叉编译工具链;如果外部(external)工具链被用到则导入;
- 创建和安装被选中的目标包;
- 如果被选择的话,创内核镜像;
- 如果被选择的话,创建bootloader;
- 如果选中创建格式,创建根文件系统。
output/build/host-mpc-1.0.2编译通不过,查了一下config.log,貌似是什么动态库找不到。
百度之后的结果是,PATH设置中,buildroot-2013.05/output/host/usr/bin目录和/bin目录中有同名的动态库,
而buildroot-2013.05/output/host/usr/bin在前,gcc就链接到了错误的动态库。
具体修改方案是把buildroot-2014.11\Makefile里面的这一行
BR_PATH = "$(HOST_DIR)/bin:$(HOST_DIR)/sbin:$(HOST_DIR)/usr/bin:$(HOST_DIR)/usr/sbin:$(PATH)"
改为
BR_PATH = "$(PATH):$(HOST_DIR)/bin:$(HOST_DIR)/sbin:$(HOST_DIR)/usr/bin:$(HOST_DIR)/usr/sbin"
网上本来的说法是要改这个文件package\Makefile.in,但是buildroot代码也是不停演化的,
折腾了好一会儿,找到相应的代码行挪到了buildroot-2014.11\Makefile
好,再次make | tee -a loongson.log,错误消失了。
buildroot下载软件包奇慢,40M的内核头文件我手动下载好放到buildroot-2014.11/dl目录,再执行make | tee -a loongson.log。
编译内核时又遇到问题了,Makefile:1601: *** mixed implicit and normal rules. Stop.
1601行:/ %/: prepare scripts FORCE
改为 :%/: prepare scripts FORCE刚编了一会儿,又遇到问题了
scripts/unifdef.c:209:25: error: conflicting types for ‘getline’
百度说修改scripts/unifdef.c把getline改为别的名字例如get_line,共3处的。
后来又遇到一堆编译问题。
然后,配置下载了glibc-2.20.tar.xz,可惜configure阶段提示
GNU libc 2.20 requires kernel header files from Linux 2.6.32 or later to be installed before configuring.
看来glibc-2.19.tar.xz已经是支持Linux 2.6.27.1的最新版本,但是有编译问题。
然后,下载了glibc-2.7.tar.bz2,解压,打包成xz,伪装(重命名)成glibc-2.20.tar.xz,sha256 hash检验通不过。
只要手动解压到output/build/glibc-2.20/,可以configure时还是遇到问题了。
checking sysdep dirs... configure: error: The mipsel is not supported.
从glibc2.17开始才支持mipsel。因此我只有2.17,2.18.2.19这3个版本可用。
eglibc是一个增加了可移植性的glibc分支,最后一个版本是2.19,后面就合并glibc里面了。因此这里我们选择eglibc2.19
打算从glibc2.8到glibc2.18一个个试过去,看哪个能编译通过。
然后把编出来的glibc动态库拷到龙芯笔记本上。一个Linux里面,只要设置好相关环境变量,多个glibc可以共存。
- 然后的目标就是要在buildroot里面编一个龙芯上可运行的gcc,支持的编译语言嘛,至少C语言要支持吧。
- 龙芯2F的性能有限,目前跑的桌面是QT,我打算替换成LXDE。当然,要自己编译和配置。
- 把内核升级到更新的版本。