~~非常隐秘不知道怎么说出口~~地说,某芯片采用mips架构,可是速度着实很尴尬。
背后的一切不谈,我们要交叉编译,在x86上编译mips架构的程序。
工具链一听非常底层,可软件这个世界总有大佬不断的探索去降低制造成本和难度,并且开源。
工具介绍可以去官网或者轮子看,可以简单的说成这是一个易用的制造工具链工具。
这里记录一下制造mips工具链的过程,为的是能激情的带着速度编译程序并跑起来。
~~虽然都差不多但还是当作前无古人地记一下~~
根据踩过的雷,保持在用户状态下操作(鄙视整天一开终端立刻sudo的某自己)。
1.下载crosstool-ng工具
这个简单,直接官网下载,这个时候的最新版应该是1.24吧。由于是用户,我在自己的/home/jal/下新建了一个文件夹作为此工程的目录,所以东西放到/home/jal/mips-linux-obj/目录下。
2.解压编译安装
运行tar xvf 解压,新建一个安装目录NG_install,进入crosstool源码目录运行./configure --prefix=/home/jal/mips-linux-obj/NG_install、make、make install。如果没有意外,顺利完成后在NG_install目录下能看到bin libexec share三个目录生成。
3.添加环境变量
再次强调是用户模式,修改~/.bashrc,末尾添加PATH=$PATH:/home/jal/mips-linux-obj/mips-linux-obj/bin,再source一下环境变量搞定
4.配置制作环境
先新建NG_build和NG_src和tool三个目录,NG_build用作构建工具链的目录,里面有构建日志,tool用于存放制好的工具链,NG_src用于存放制造工具链过程中下载的工具源码包。至此整个工程的目录都差不多了,不厌其烦地再显示一次,主要就是/home/jal/mips-linux-obj/目录下,有NG_build、NG_install、NG_src、tool和crosstool-ng-1.24.0这几个目录(够了)。工具链配置和内核配置很很很像,进入NG_build运行ct-ng list-samples查看支持的硬件配置,找到自己想要的直接ct-ng mipsel-unknown-linux-gnu,他会复制这个硬件配置作为本目录的.config文件,然后运行ct-ng menuconfig 命令运行一个ncurses界面进行细化配置(果然就是内核配置方法啊亲)
在Paths and misc options ---> 这个选项中设置文件路径,新建的目录要用到了
在 *** Paths ***下一行敲入/home/jal/mips-linux-obj/NG_src/;在Working diretory下一行敲入/home/jal/mips-linux-obj/tool;用到它们了。
在Target option ---> 这个选项中设置芯片特性,介入某芯片 *** Option for mips *** 选ABI(n64)Bitness: 选(64-bit)
,architecture level 敲mips64,Floationg point: 选(hardware(FPU))。
按一下save,配置就这么好了。
5.跑它!
执行ct-ng build跑起来!
过程可能会出错,他是先从网上下载一下需要用到的源码工具包在解压构建,包括内核。如果这时下载链接崩了我也就崩了,这时可以从别的地方下载对应版本的包放到NG_src目录下,就可以了。
我那个年代,需要这些:
automake-1.16.1.tar.xz
binutils-2.32.tar.xz
expat-2.2.6.tar.bz2
gcc-8.3.0.tar.xz
gdb-8.2.1.tar.xz
gettext-0.19.8.1.tar.xz
glibc-2.28.tar.xz
glibc-2.29.tar.xz
gmp-6.1.2.tar.xz
isl-0.20.tar.xz
libiconv-1.15.tar.gz
linux-4.20.8.tar.gz
mpc-1.1.0.tar.gz
mpfr-4.0.2.tar.xz
ncurses-6.1.tar.gz
strace-4.26.tar.xz
zlib-1.2.11.tar.gz
跑挺久的。。它还会帮你算时间,我用了一个钟。
去tool目录查看成品!这一看就要设置环境变量。
这里就是编译的一堆宏定义了,一般都是写一个environment文件,里面一堆export,每次用工具链之前source一下就好。
那基于一个开源嵌入式的文件(yocto)修改这个environment,暂时来说把文件写成这样,当然后续如果要改还是得改改这个文件。
文件里定义了交叉工具链存放的位置,把对应的目录名字配成自己的,每次source之后就能看到有这个工具链了。
export SDKTARGETSYSROOT=/opt/mips-linux-obj/tool/mips64el-3a-linux-gnu/sysroot
export PATH=/opt/mips-linux-obj/tool/mips64el-3a-linux-gnu/sysroot/usr/bin:/opt/mips-linux-obj/tool/mips64el-3a-linux-gnu/sysroot/usr/sbin:/opt/mips-linux-obj/tool/bin:$PATH
export CMAKE_PREFIX_PATH=/usr/lib/mips64el-linux-gnuabi64/cmake
export QMAKESPEC=/usr/lib/mips64el-linux-gnuabi64/qt5/mkspecs/linux-g++
export OECORE_NATIVE_SYSROOT="/opt/mips-linux-obj/tool/mips64el-3a-linux-gnu/sysroot"
export OECORE_TARGET_SYSROOT="$SDKTARGETSYSROOT"
export OPENGL_opengl_LIBRARY=/usr/lib/mips64el-linux-gnuabi64/libGL.so
unset command_not_found_handle
export CC="mips64el-3a-linux-gnu-gcc -mel -mhard-float -mabi=64 -march=mips64r2 -I$SDKTARGETSYSROOT/usr/include --sysroot=$SDKTARGETSYSROOT"
export CXX="mips64el-3a-linux-gnu-g++ -mhard-float -mabi=64 -march=mips64r2 -I$SDKTARGETSYSROOT/usr/include --sysroot=$SDKTARGETSYSROOT"
export CPP="mips64el-3a-linux-gnu-gcc -E -mel -mbi=64 -mhard-float -march=mips64r2 -I$SDKTARGETSYSROOT/usr/include --sysroot=$SDKTARGETSYSROOT"
export AS="mips64el-3a-linux-gnu-as "
export LD="mips64el-3a-linux-gnu-ld -rpath --sysroot=$SDKTARGETSYSROOT -m elf64ltsmip"
export GDB=mips64el-3a-linux-gnu-gdb
export STRIP=mips64el-3a-linux-gnu-strip
export RANLIB=mips64el-3a-linux-gnu-ranlib
export OBJCOPY=mips64el-3a-linux-gnu-objcopy
export OBJDUMP=mips64el-3a-linux-gnu-objdump
export AR=mips64el-3a-linux-gnu-ar
export NM=mips64el-3a-linux-gnu-nm
export M4=m4
export TARGET_PREFIX=mips64el-3a-linux-gnu-
export CONFIGURE_FLAGS="--target=mips64el-3a-linux-gnu --host=mips64el-3a-linux-gnu --build=i686-linux --with-libtool-sysroot=$SDKTARGETSYSROOT"
export CFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types "
export CXXFLAGS=" -O2 -pipe -g -feliminate-unused-debug-types "
export LDFLAGS="-Wl,-O1 -Wl,--as-needed"
export CPPFLAGS=""
export KCFLAGS="--sysroot=$SDKTARGETSYSROOT"
export OECORE_DISTRO_VERSION="2.2.4"
export OECORE_SDK_VERSION="2.2.4"
export ARCH=mips
export CROSS_COMPILE=mips64el-3a-linux-gnu-
# Append environment subscripts
if [ -d "$OECORE_TARGET_SYSROOT/environment-setup.d" ]; then
echo "there is environment-setup.d"
for envfile in $OECORE_TARGET_SYSROOT/environment-setup.d/*.sh; do
. $envfile
done
fi
if [ -d "$OECORE_NATIVE_SYSROOT/environment-setup.d" ]; then
echo "there is environment-setup.x86"
for envfile in $OECORE_NATIVE_SYSROOT/environment-setup.d/*.sh; do
. $envfile
done
fi
看到那个环境文件定义的链接库,链接头文件,CPPFLAGS、LDFLAGS等等,所以编一个最简单的helloworld它可能都说找不到那个stdio.h,其实也只需要把stdio.h放到对应的链接头文件目录就可以了。依赖库会比较麻烦,毕竟库也有架构之分,最好能直接从仓库什么的拿到对应架构的依赖库吧,依赖库的依赖库,需要添加-rpath和-rpath-link选项,其实也差不了多少。
那么source完之后编一下hello:mips64el-3a-linux-gnu-gcc hello.c -o hello
file一下编出来的可执行程序看到架构和其他东西都正确。
当然条件允许还可以放到目标机运行一下。
后续编译工程项目,带有Makefile那些,保证Makefile里CC和一些链接目录正确,和对应的库齐全,基本是没有问题的。
嗨呀,那么费劲。就为了个速度。