基于qemu-riscv从0开始构建嵌入式linux系统ch17. bash——交叉编译应用

交叉编译

嵌入式开发中免不了交叉编译,交叉编译就是使用的开发环境中运行编译器生成另一个平台的可执行程序,常见的pc开发平台就是x86的linux系统,而嵌入式平台一般是arm或者riscv的linux平台,一些低端嵌入式环境是rtos或裸机平台。本节我们就打算将linux系统内的bash工具进行交叉编译,移植到我们的riscv目标系统内,来代替busybox的ash作为shell。

传统的GNU项目源码结构

bash源码可以在gnu网站上下载:https://ftp.gnu.org/gnu/bash/。bash作为一款经典而基础的软件经过了非常多年的沉淀依旧保持更新。一般来讲,这类经典代码的自动化编译脚本一般都比较相似,通常由发布者使用autoconf工具生成configure脚本,然后用户使用该脚本添加需要的参数进行环境配置编译前检查,最终生成Makefile文件,然后使用make工具进行最终的编译链接。

bash编译

bash交叉编译比较容易,配置命令如下(–host指定目标系统,–prefix指定输出路径),完成后根据需求拷贝输出目录的/bin/bash到目标系统内。

./configure --host=riscv64 --prefix=$SHELL_FOLDER/output CXX=$CROSS_PREFIX-g++ CC=$CROSS_PREFIX-gcc 
make -j16
make install

由于我们使用的交叉编译器riscv64–glibc–bleeding-edge-2020.08-1环境存在ncurses库,会在编译时链接到这个库,但我们并没有这个库的源码,因此系统中缺少对这库的一些数据包的安装,因此我们还需要下载ncurses的源码。

备注:本项目自ch22节后均改用自己编译的交叉编译器,而该编译器内仅包含基本的glibc库,因此与本节交叉编译的配置稍有出入,请结合具体的tag对应的文档说明和注释理解。

make编译

在交叉编译ncurses由于需要安装一些数据文件到目标系统上,目前比较稳妥简单的交叉编译方案是在主机交叉编译,然后在目标机进行make install,因此我们先交叉编译一个make工具给目标机。make源码可以在gnu网站上下载:https://ftp.gnu.org/gnu/make/。配置命令如下,完成后根据需求拷贝输出到目标系统内。

./configure --host=riscv64 --prefix=$SHELL_FOLDER/output CXX=$CROSS_PREFIX-g++ CC=$CROSS_PREFIX-gcc 
make -j16
make install

make工具没有任何运行时依赖,完成。

virtio-9p-device

virtio-9p-device本不该和本节主题相关,但由于我们需要将一些文件拷贝到我们的qemu虚拟机中的系统内,之前我们都是直接在主机挂载文件系统img到本地回环虚拟设备上,这样操作非常麻烦且容易误操作破坏映像,这里我给出一个简单的方案,由于我们的虚拟机还拥有很多条virtio-mmio线,我们可以添加virtio-9p-device设备到虚拟机启动命令行上:

-fsdev local,security_model=mapped-xattr,id=fsdev0,path=$SHELL_FOLDER/
-device virtio-9p-device,id=fs0,fsdev=fsdev0,mount_tag=hostshare

这样在qemu内的linux系统上执行:

mount -t 9p -o trans=virtio,version=9p2000.L hostshare /mnt/

就可将host系统上的的一个目录挂载到target系统内/mnt路径下。注意下mapped-xattr选项,这里我们之所以选择这个选项是为了能让target系统拷贝文件到host中,否则target将只能只读不能写入共享目录。

ncurses编译

ncurses源码可以在gnu网站上下载:https://invisible-mirror.net/archives/ncurses/。ncurses库非常有用,后面我们有机会会对其功能进行深入分析。编译ncurses,首先在host系统交叉编译

./configure --host=riscv64 --disable-stripping CXX=$CROSS_PREFIX-g++ CC=$CROSS_PREFIX-gcc 
make -j16

进入目标系统机中挂载ncurses目录。执行以下命令,将安装相关工具和数据到目标系统/usr/local目录中。由于我们配置是禁用了strip,如果你的目标系统存储空间有限,可以手动strip /usr/local/bin中的工具减小体积。

make install.progs
make install.data

最后拷贝交叉编译工具链目录下$CROSS_COMPILE_DIR/riscv64-buildroot-linux-gnu/sysroot/usr/lib/libncurses.so.6.1库到目标系统的/usr/local/lib/libncurses.so.6.1,并创建相关软连接/usr/local/lib/libncurses.so.6、/usr/local/lib/libncurses.so,/lib/libncurses.so.6均指向该文件。

bash配置

将目标系统/etc/passwd中的启动shell /bin/sh替换为/bin/bash。

添加以下内容到~/.bashrc,当然你可以根据你自己的喜好修改其中的配置。

export TERM=xterm-256color
export TERMINFO=/usr/local/share/terminfo
export PS1='[\w]\$'

这里TERM和TERMINFO就是和ncurses相关的环境变量,有了ncurses终端就可以支持一些更丰富的表现手法而不是干枯的黑白色,当然ncurses发出的终端协议还需要外部终点仿真窗口正确解析渲染,不过不需太担心,现代的linux系统下各类软件几乎都支持xterm-256color格式。PS1环境变量是命令行首的提示符,你可以自己配置,这里’[\w]$’为显示当前路径以及显示当前用户是否是root(root就显示#,非root就显示$),我们的配置比较简单就和传统的pc发行版的终端相似,你可以在这里自定义显示如主机名称,用户名称,当前时间等内容。

本教程的
github仓库:https://github.com/QQxiaoming/quard_star_tutorial
gitee仓库:https://gitee.com/QQxiaoming/quard_star_tutorial
本节所在tag:ch17