cnCalc计算器论坛

 找回密码
 注册
搜索
查看: 5719|回复: 5

[fx-9860/9750] GCC 交叉编译工具链制作 Add-in 教程

[复制链接]
发表于 2018-1-3 23:07:59 | 显示全部楼层 |阅读模式
本帖最后由 Mike 于 2018-1-4 01:18 编辑

心血来潮翻译了一下国外大神 GCC 交叉编译环境搭建的帖子。有兴趣的朋友可以看看。
翻译时用的MarkDown,不过论坛好像不支持……对排版要求比较高的话可以下载附件中的pdf文档。
PS: 我也不知道为什么标题读起来会这么尬…



使用 GCC 交叉编译制作 Add-in
Linux 上多样而自由的编程环境离不开强大的编译器套件 GCC。这篇教程就将展示如何使 GCC 能够支持计算器所使用的 sh3eb-elf 结构文件的编译。
其实也没那么难,比军训轻松多了。
第一部分:准备工作步骤1:砺兵秣马(依赖安装)
我们要安装的不只有 GCC,而是包括两部分:
  • Binutils(Binary Utilities,二进制工具),用于处理汇编、链接、可执行文件格式,以及与一切编译期之后的东西打交道;
  • GCC(GNU Compiler Collection,GNU 编译器套件)本身。

在这篇教程中我们使用了 gcc-5.5.0 与 binutils-2.29(【译注】原文写作于2016年9月11日,作者使用了 gcc-6.1.0 与 binutils-2.26;但 gcc-6.x/7.x 在我电脑上死活编译不了,换了 5.5.0 反而好了)。你也可以选用其他版本合适的版本——当然那些老古董的版本还是不要考虑了。OSDev 社区(他们经常使用 GCC 交叉编译)维护了一份编译成功的版本的列表;如果你尝试其他组合成功了,也可以向他们反馈。
在操作过程中,你可能因为各种玄学原因失败。在这种情况下,很不幸,你只能下载其他版本然后从头再来(译者:深有体会……)。
你可以通过点击以下链接进行下载(【译注】出于国内访问速度考虑,我选了清华大学的 TUNA 镜像源,上面有很多其他的镜像源):
接下来是逃不掉的依赖项。下载时需要注意,名字中有 -dev 后缀的往往提供了库给其他程序调用,而不仅仅是他们的可执行文件。以下列举的是所需的依赖项,括号里的名字在本文写作时尚可用(【译注】原文写于2016年9月11日,事实上我在2018年1月翻译这篇文章时这些名字也还都可用;而且事实上,有些依赖并不是必需的,如果你没有成功安装其中的某个依赖项,仍然可以尝试编译 GCC):
  • mpfr (libmpfr-dev):可变精度浮点数
  • mpc(libmpc-dev):可变精度复数
  • gmp(libgmp-dev):多种精度的算数运算
  • png(libpng-dev):图像操作
  • ppl(libppl-dev):多面体(经过神奇的优化)
  • g++(g++):C++ 编译器
  • git(git):版本控制工具

总之,下载最新版本。在 Debian 系下(包括 Ubuntu,Mint 等等衍生版),用 apt-get;其他发行版嘛,看你的心情吧(比如 yogurt,yum,pacman,随便哪个,应该不用我来教你了)。
步骤 2:勘测地形(环境准备)
所有的编译操作都将在你个人目录下的 opt 文件夹内完成(古老而神秘的好习惯),所以你需要先创建这个文件夹,再进入它。打开终端,准备好与它共度一段时光。
  
  $ mkdir -p ~/opt/sh3eb-elf
  $ cd ~/opt/sh3eb-elf
记一下,我们将要编译的交叉编译器就叫 sh3eb-elf。
然后我们在其中建立两个子目录用于编译 binutils 和 GCC。整个的编译过程都会在这两个文件夹中完成。如果你不幸要从头再来,你需要把这两个文件夹删除再重新建立。
  
  $ mkdir build-binutils build-gcc
最后,把你下载好的 binutils 和 GCC 的源码解压到 ~/opt/sh3eb-eif 中。完成之后文件夹中应该会有四个文件夹,分别是上面步骤中建立的两个文件夹 build-binutils 和 build-gcc,以及视你下载的版本而定的两个源码文件夹,比如我的就是 binutils-2.29 和 gcc-7.2.0。记得修改下面用到的命令行中的相应部分,如果你选了和我不同的版本。
第二部分:直抵前线步骤 3:兵戎初接(编译 Binutils)
binutils 的编译过程相当经典——先 configure 再 make。注意一下(后面的教程中也一样),如果你给 make 传递了 -j 参数(不要忘了在后面跟一个数字,代表线程数,例如 -j8),就可以获得多线程的加速(【译注】线程数大致可以选 CPU 核心数的 2~4 倍)。
  
  $ cd build-binutils
  $ ../binutils-2.29/configure --target=sh3eb-elf --prefix="$HOME/opt/sh3eb-elf/" --disable-nls --disable-werror
你可能会注意到 --target 参数,顾名思义,它制定了目标架构(我们的计算器用的是一个 SuperH-3 处理器)。你大可不必担心 SH4 ,因为 SH4 兼容 SH3(反之则不然)。--disable-nls 选项强制编译器使用英语(这也是一个古已有之的好习惯),而 --disable-werror 选项关闭了编译器的 -Werror 选项,反正你也不会去用。
然后我们就可以用 make 来编译和安装了。
  
  $ make
  $ sudo make install
如果你遇到了编译错误,检查一下你的依赖项以及它们对应的头文件是否被正确安装了。如果还是不行,就只能回到步骤 1 中重新选择 binutils 和 GCC 的版本了。
步骤 4:装甲压境(编译 GCC)
现在你已经装好了 Binutils 了,它的可执行文件应该会出现在 ~/opt/sh3eb-elf/bin 下。如果我们想要使用它们,就需要将这个目录加入系统的环境变量 PATH(运行命令时会从其记录的目录中寻找程序)。下面这个命令可以帮你临时完成这个工作。
  
  $ export PATH=$PATH:$HOME/opt/sh3eb-elf/bin
如果你需要使其永久生效,则应将上述命令加入你的 Shell 配置文件如 ~/.bash_profile。
  
  $ echo 'export PATH=$PATH:"$HOME/opt/sh3eb-elf/bin"' >> ~/.bash_profile
  $ source ~/.bash_profile
接下来的工作和上一步骤差不多。我们首先运行配置脚本,然后编译。你可以用 --enable-languages 选项来指定编译你需要的语言的编译器。一般来讲,C 和 C++ 足够了,但是如果你打算用 Ada,Go 或者 Fortran 的话也可以把它们加入进来。不过不要贪杯,除非你可以忍受漫长的编译时间(译者:何况连能用的库都没有……)。
  
  $ cd ~/opt/sh3eb-elf/build-gcc
  $ ../gcc-5.5.0/configure --target=sh3eb-elf --prefix="$HOME/opt/sh3eb-elf" --disable-nls --enable-languages=c,c++ --without-headers
选项的组织和之前类似。如果配置因为丢失头文件而失败,安装好它们之后重新运行配置脚本。如果一切顺利,那么你就已经为这场战役中最漫长的部分做好了准备(别忘了用 -j 选项来指定线程数)。
  
  $ make all-gcc
  $ sudo make install-gcc
如果你遇到了你解决不了的编译错误……抱歉,只能从步骤 1 重来了。
步骤 5:空中支援(安装 libgcc)
最后的一大任务是编译 libgcc,你需要用它来编译你的程序。
  
  $ make all-target-libgcc
  $ sudo make install-target-libgcc
如果编译又失败了……抱歉,还是只能从步骤 1 重新开始(都到了这一步,确实让人沮丧)。
祝贺!你的编译器已经安装完成,可以使用了。你可以运行一些命令来检查一下它……
  
  $ sh3eb-elf-as --version
  GNU assembler (GNU Binutils) 2.29 [...]
  $ sh3eb-elf-gcc --version
  sh3eb-elf-gcc (GCC) 5.5.0 [...]
  $ sh3eb-elf-gcc -print-file-name=libgcc.a
  /Users/mike/opt/sh3eb-elf/lib/gcc/sh3eb-elf/5.5.0/libgcc.a
如果你得到了类似的输出,那么你就可以……嗯,继续看下去了!这教程还没有结束。
第三部分:占地为王步骤 6:全副武装(Add-in 包装器)
你可能会对我所谈论的 ELF 文件格式感到困惑,因为计算器上只能使用 g1a……不过到现在为止,g1a 还只是 CASIO 专有的格式,GCC 对如何生成它一无所知。所以,我们要使用包装器(Wrapper)来将 ELF 文件打包为 g1a 格式文件。我们已经将它上传到一个 Git 仓库。你可以使用以下命令来将它安装到你的编译器所在目录(【译注】可能会有权限问题,需要使用 sudo 来运行命令)。
  
  $ cd ~/opt/sh3eb-elf
  $ git clone "https://Lephenixnoir""@""bitbucket.org/Lephenixnoir/add-in-wrapper.git"
  $ cd add-in-wrapper
  $ make
  $ cp build/g1a-wrapper ~/opt/sh3eb-elf/bin
你现在已经可以给计算器开发程序了!让我们一起来看看具体应该怎么做……
步骤 7:号令天下(项目环境)
我们将会创建一个模板工程来供你重复使用。因为这些与 GCC 的编译过程无关,所以我建议你在别的文件夹里面做这事(比方说 ~/my-awesome-project 就很棒)。不论如何,你都可以暂时关掉终端了。
我假定你已经有一定的有 C 语言程序设计的经验,所以我不会再教你如何组织一个项目……你只需要这些文件就可以了(译者:下载速度感人……)。
你一定已经迫不及待地想用你的新工具来编译它了。一个不错的选择是(【译注】当然用 CMake 什么的就更舒服了,过几天我可能会写一下怎么操作)……
  
  $ sh3eb-elf-gcc -m3 -mb -ffreestanding -nostdlib -T addin.ld crt0.s addin.c -o addin.elf -I include -lgcc -L .
这里对这些选项做些说明:
  • -m3 和 -mb 选项表明我们想要生成 SH3 上的二进制(SH3 还是有很多变种的,所以我们仍然需要指定一下),并使用大端模式(这和多字节变量每个字节在内存中的顺序相关);
  • ffreestanding 选项要求编译后的代码不会依赖任何特定的操作系统(而是由 GCC 提供一些东西);
  • -I 是包含目录标记(我们有一些头文件在 include 目录中);
  • -nostdlib 表示我们不会使用标准库(其实它已经被包含在 libfx.a 中了);
  • -O2 是优化选项(【译注】运行速度能快很多)。

这些编译选项都是在编译期使用的。由于我们的项目比较简单,所以我们一次性将它编译完成。如果你有一个大项目,最好逐个文件编译完成后再进行链接。下面这些是链接选项:
  • -T addin.ld 选项告诉编译器,链接时需要参考 addin.ld 文件中编写的规则;
  • -L . 和 lfx 选项表明我们需要链接当前目录中的 libfx.a 文件;
  • -lgcc 表示我们将要使用 libgcc(你总是需要它的!);
  • 当然 -o addin.elf 表明了我们想要的输出文件。

注意文件夹中的 crt0.s 文件是另一种源代码文件,它包含了基础代码。别忘了把它也编译了(这里我们把它和 addin.c 同时编译了)。编译器输出的文件是用于 SH3 架构的 ELF 文件(经典的 Linux 格式),这正是我们一开始所期望的。
步骤 8:强强联合(g1a 格式文件的生成)
使用 ELF 格式的文件有很多好处,不过我们想要的只是纯二进制文件。为此,我们将使用 Binutils 中的一个工具 objcopy 来改变格式。简而言之,就是要将 ELF 删除而只留下纯的二进制部分。
  
  $ sh3eb-elf-objcopy -R .comment -R .bss -O binary addin.elf addin.bin
现在我们只需要给二进制添加 add-in 文件头就可以了——这也正是 Add-in Wrapper 将要做的。你可以使用 g1a-wrapper --help 命令来查看这个工具所支持的一些选项,不过现在我们只是简单地把二进制包装一下再加个图标。
  
  $ g1a-wrapper addin.bin -o addin.g1a -i icon.bmp
大功告成!现在你只要把这个 add-in 传送到你的计算器上就好了……这里有一些好用的祖传工具可以使用:
  • Cakeisalie5 的杰出工具 P7
  • Nessotrin 的 CasioUSB

感谢阅读。


原文链接:http://www.planet-casio.com/Fr/f ... ompilateur-gcc.html

使用 GCC 交叉编译 Add-in.pdf

185.19 KB, 下载次数: 10

PDF

使用 GCC 交叉编译 Add-in.md

12.18 KB, 下载次数: 6

MarkDown

评分

参与人数 1金钱 +50 专家 +1 贡献 +1 收起 理由
ZephRay + 50 + 1 + 1 很棒!

查看全部评分

发表于 2018-1-9 05:45:20 | 显示全部楼层
这样做完的话,是否意味着可以使用一些新的特性了?(比如lambda表达式?)
 楼主| 发表于 2018-1-9 12:10:07 | 显示全部楼层
ZephRay 发表于 2018-1-9 05:45
这样做完的话,是否意味着可以使用一些新的特性了?(比如lambda表达式?)

是的…但是现在的主要问题是没有一个正经的标准库可以用。_(:з」∠)_
发表于 2018-1-10 06:26:47 | 显示全部楼层
Mike 发表于 2018-1-8 23:10
是的…但是现在的主要问题是没有一个正经的标准库可以用。_(:з」∠)_

所以说还是需要一个靠谱的newlib移植……顺便问下,Addin一般可以使用到多大的RAM呢?
 楼主| 发表于 2018-1-10 10:53:38 | 显示全部楼层
ZephRay 发表于 2018-1-10 06:26
所以说还是需要一个靠谱的newlib移植……顺便问下,Addin一般可以使用到多大的RAM呢?

9860的话,我看原文提供的project的ld文件里面给的是64k,并且认为这是“pretty safe guess”。所以应该至少有64k可以用(虽然还是少的可怜)。CG20的话,这里有讨论:https://www.cemetech.net/forum/viewtopic.php?t=9334
另外关于标准库,CG20上好像有一个libfxcg,C标准库部分挺完整的。不过我链接的时候好像只要有浮点数就会导致链接器段错误……不知道是不是环境没有配好。9860的标准库嘛,貌似原文作者写过一点,不过功能还是很弱。
 楼主| 发表于 2018-1-10 12:21:00 | 显示全部楼层
ZephRay 发表于 2018-1-10 06:26
所以说还是需要一个靠谱的newlib移植……顺便问下,Addin一般可以使用到多大的RAM呢?

ld挂掉的问题刚刚解决了,方法是换一个binutils版本_(:з」∠)_,换成2.26.1之后就好了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cnCalc计算器论坛

GMT+8, 2024-3-29 07:47 , Processed in 0.055229 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表