华为鲲鹏云 KBengine arm64编译问题实践报告
1. 问题描述
在华为鲲鹏云环境上,有客户诉求将云游戏引擎KBengine移植到arm64环境,编译过程中出现多个与编译选项,架构适配,内嵌汇编,gcc变量定义等问题,在此将移植攻关过程中的问题整理记录,并给出详细的解决方案与思路;为后续同类型问题提供指导.
2. 环境
类别 | 子项 | 版本 | 获取地址(方法) |
华为云 | 虚拟机 | RC3(916) | NA |
OS |
CentOS |
7.6.1810 | http://mirrors.huaweicloud.com/centos/7.6.1810/isos/x86_64/CentOS-7-x86_64-DVD-1810.iso
|
Kernel | 4.14.0-49.el7a.aarch6464 | iso 自带 | |
软件包 |
kbengine |
2.5.5 | |
gcc/g++ |
4.8.5 |
3. 问题分析及修改
KEengine 底层使用c++实现,编译过程符合一般c/c++程序编译流程,此处不再赘述,主要记录在编译过程中遇到的具体问题和解决方法,不同平台问题不尽相同,此处只说明在arm64环境下遇到的问题。
3.1 g++: error: unrecognized command line option ‘-m32’
l 问题描述
编译过程中在kbengine-2.5.5/kbe/src/lib/dependencies/fmt/src/ 这层目录中的某个Makefile文件中出现 -m32参数,当前编译环境g++不支持该参数
l 定位分析
1) vim ./kbengine-2.5.5/kbe/src/lib/dependencies/fmt/src/Makefile, 如下,需要以来 kbe/src/build/common.mak文件
2) Vim ./kbe/src/build/common.mak
如下图, 该文件是在编译过程中根据当前编译平台确定gcc/g++ 编译参数, 很明显, 若不是x86_64环境, 默认位x86 32位环境。
这里就要说下 -m32/-m64 这两个参数了,这两个参数用来在32位或64位环境下编译代码使用:
-m32 设置int/long/指针位32位
-m64 设置int/long/指针为64位
-m32/-m64支持的平台有Intel i386, AMD x86-64, IBM RS/6000, PowerPC, SPARC ,TILE-Gx ,TILEPro . 很不幸,他们不支持arm平台, 在 参考了《Using the GNU Compiler Collection For gcc version 4.8.5 --3.17.3 ARM Options》后, 很遗憾的发现,Arm gcc/g++ 的-m 编译参数中并不支持32位或64位,只能去掉该参数。
l 解决方案
如下所示,此处修改只使用用arm环境下的编译, 若是在其他平台上, 还是需要在进行适配。
3.2 buildconf: libtoolize not found.
l 问题描述
这个错误可以说是很清晰了, 缺少 >= libtoolsize 1.4.2 的命令
l 定位分析
配置上合适的yum源(推荐华为源,速度很赞),安装即可, 注意安装时对libtoolize的版本要求。
如是不知道libtoolize 是那个rpm包提供的,可以使用repoquery查询下即可:
l 解决方案
yum -y install libtool
3.3 configure: error: cannot guess build type; you must specify one
l 问题描述
从错误信息来看, ./configure 时获取的os 信息与预期不符
l 定位分析
由错误可见, 当前处在configure阶段, 仍在检查编译平台的信息确定使用的gcc工具, 且当前编译环境不满足kbengine要求,从
/home/src/kbengine-2.5.5/kbe/src/lib/dependencies/log4cxx/config.guess可以佐证这种猜测,这是在检查当前环境OS 版本、内核、架构等信息,并且不支持CentOS ,节选其中一段可以更加清晰:
l 解决方案
方案一:
修改或者同步最新代码中的config.guess ,让其支持CentOS Arm64平台,最终这个方案因当前已是最新代码, 不支持CentOS Arm64, 适配量大且而放弃
方案二:
根据提示路径找到makefile, 并修改./configure 参数,让其支持CentOS Arm64平台, 如下:
那么,只需要在CONFG_ARGS处添加 arm参数,让automake可以知道当前平台为Arm64即可。
3.4 error: impossible constraint in ‘asm’
l 问题描述
编译输出显示, 在KBEngine:timestamp()中 有不支持的内联汇编语句
l 问题分析
vim ./kbengine-2.5.5/kbe/src/lib/common/timestamp.h, 如下:
这一段代码是计算UNIX平台下的64位TSC时间,即时钟周期计数,不区分平台。
其中 :
rdtsc : X86指令,Load时间戳到EDX:EAX。Load当前进程的64位寄存器MSR中 时间戳计数到到X86 32位通用寄存器中EDX:EAX中去, 其中MSR的高32位 Load 到EDX中,低32位Load到EAX中。按位或执行重置EDX/EAX, 并将其 存入本地变量。
rethi : 32 位无符号整形, 用来存储从EDX 寄存器中读取的时间戳计数。
retlo: 32 位无符号整形, 用来存储从EAX 寄存器中读取的时间戳计数。
最后,将从MSR中获取的高32位数据强转成64位无符号整形在左移32位,得到当前进程的高32位时间戳,在或上低32位的retlo, 就可以获取当前环境子开机置现在的CPU cycle总数。
l 解决方案
《Arm® Architecture Reference Manual Armv8, for Armv8-A architecture profile --D11.2 The AArch64 view of the Generic Timer》提供了方法, Armv8环境下使用CNTVCT_EL0 获取系统虚拟时间。
我们所要做的事就是区分平台,在aarch64下实现同等功能的函数, 需要注意的是:
1) MSR 指令需要一个系统寄存器。
2) CNTVCT_EL0 是64位寄存器,本地获取寄存器数据的变量也必定是64位的。
最终修改如下:
3.5 db_interface_mysql.h:14:25: fatal error: mysql/mysql.h: No such file or directory
l 问题现象
Hybridy模块依赖包含mysql.h
l 问题分析
mysql.h 一般会有mysql 编译出来的devel包提供, 安装即可
l 解决方案
yum install -y mysql++.aarch64 mysql++-devel.aarch64
3.6 error: case label value is less than minimum value for type [-Werror]
l 问题现象
case 语句中的label值超出了预期范围
l 定位分析
vim kbengine-2.5.5/kbe/src/lib/server/telnet_handler.cpp, 结合上下文可以知道case 的label value是char型的,arm下char类型 默认为unsigned char,case label value 范围在[0-256], -1不符合预期。 如下:
l 修改方案
方案一:
g++参数CXXFLAGS 中添加 -fsigned-char/ -fno-unsigned-char , 在arm64平台,所有的char类型为sigend char。
vim kbengine/kbe/src/build/common.mak
需要注意该方案涉覆盖全局,或许会导致未可知的错误.
方案二:
局部修改,将 case -1 修改为 case (char) -1即可.
4. 参考信息
4.1 GCC 手册-- -m32/-m64
https://gcc.gnu.org/onlinedocs/gcc-4.8.5/gcc.pdf
4.2 rdtsc 指令
https://c9x.me/x86/html/file_module_x86_id_278.html
4.3 MRS 指令
C6.2.192 MRS
4.4 ARMV8-A 定时器
D11.1 About the Generic Timer
D11.2 The AArch64 view of the Generic Timer
4.5 CNTVCT_EL0 寄存器
D13.8.26 CNTVCT_EL0, Counter-timer Virtual Count register
- 点赞
- 收藏
- 关注作者
评论(0)