1. 如何设置NDK的编译选项
1. 概述
首先回顾一下 Android NDK 开发中,Android.mk 和 Application.mk 各自的职责。
Android.mk,负责配置如下内容:
(1) 模块名(LOCAL_MODULE)
(2) 需要编译的源文件(LOCAL_SRC_FILES)
(3) 依赖的第三方库(LOCAL_STATIC_LIBRARIES,LOCAL_SHARED_LIBRARIES)
(4) 编译/链接选项(LOCAL_LDLIBS、LOCAL_CFLAGS)
Application.mk,负责配置如下内容:
(1) 目标平台的ABI类型(默认值:armeabi)(APP_ABI)
(2) Toolchains(默认值:GCC 4.8)
(3) C++标准库类型(默认值:system)(APP_STL)
(4) release/debug模式(默认值:release)
由此我们可以看到,本文所涉及的编译选项在Android.mk和Application.mk中均有出现,下面我们将一个个详细介绍。
2. APP_ABI
ABI全称是:Application binary interface,即:应用程序二进制接口,它定义了一套规则,允许编译好的二进制目标代码在所有兼容该ABI的操作系统和硬件平台中无需改动就能运行。(具体的定义请参考 网络 或者 维基网络 )
由上述定义可以判断,ABI定义了规则,而具体的实现则是由编译器、CPU、操作系统共同来完成的。不同的CPU芯片(如:ARM、Intel x86、MIPS)支持不同的ABI架构,常见的ABI类型包括:armeabi,armeabi-v7a,x86,x86_64,mips,mips64,arm64-v8a等。
这就是为什么我们编译出来的可以运行于Windows的二进制程序不能运行于Mac OS/Linux/Android平台了,因为CPU芯片和操作系统均不相同,支持的ABI类型也不一样,因此无法识别对方的二进制程序。
而我们所说的“交叉编译”的核心原理也跟这些密切相关,交叉编译,就是使用交叉编译工具,在一个平台上编译生成另一个平台上的二进制可执行程序,为什么可以做到?因为交叉编译工具实现了另一个平台所定义的ABI规则。我们在Windows/Linux平台使用Android NDK交叉编译工具来编译出Android平台的库也是这个道理。
这里给出最新 Android NDK 所支持的ABI类型及区别:
那么,如何指定ABI类型呢?在 Application.mk 文件中添加一行即可:
APP_ABI := armeabi-v7a //只编译armeabi-v7a版本APP_ABI := armeabi armeabi-v7a //同时编译armeabi,armeabi-v7a版本APP_ABI := all //编译所有版本
3. LOCAL_LDLIBS
Android NDK 除了提供了Bionic libc库,还提供了一些其他的库,可以在 Android.mk 文件中通过如下方式添加依赖:
LOCAL_LDLIBS := -lfoo
其中,如下几个库在 Android NDK 编译时就默认链接了,不需要额外添加在 LOCAL_LDLIBS 中:
(1) Bionic libc库
(2) pthread库(-lpthread)
(3) math(-lmath)
(4) C++ support library (-lstdc++)
下面我列了一个表,给出了可以添加到“LOCAL_LDLIBS”中的不同版本的Android NDK所支持的库:
下面是我总结的一些常用的CFLAGS编译选项:
(1)通用的编译选项
-O2 编译优化选项,一般选择O2,兼顾了优化程度与目标大小
-Wall 打开所有编译过程中的Warning
-fPIC 编译位置无关的代码,一般用于编译动态库
-shared 编译动态库
-fopenmp 打开多核并行计算,
-Idir 配置头文件搜索路径,如果有多个-I选项,则路径的搜索先后顺序是从左到右的,即在前面的路径会被选搜索
-nostdinc 该选项指示不要标准路径下的搜索头文件,而只搜索-I选项指定的路径和当前路径。
--sysroot=dir 用dir作为头文件和库文件的逻辑根目录,例如,正常情况下,如果编译器在/usr/include搜索头文件,在/usr/lib下搜索库文件,它将用dir/usr/include和dir/usr/lib替代原来的相应路径。
-llibrary 查找名为library的库进行链接
-Ldir 增加-l选项指定的库文件的搜索路径,即编译器会到dir路径下搜索-l指定的库文件。
-nostdlib 该选项指示链接的时候不要使用标准路径下的库文件
(2) ARM平台相关的编译选项
-marm -mthumb 二选一,指定编译thumb指令集还是arm指令集
-march=name 指定特定的ARM架构,常用的包括:-march=armv6, -march=armv7-a
-mfpu=name 给出目标平台的浮点运算处理器类型,常用的包括:-mfpu=neon,-mfpu=vfpv3-d16
-mfloat-abi=name 给出目标平台的浮点预算ABI,支持的参数包括:“soft”, “softfp” and “hard”
2. 阿里平头哥宣布,自研处理器已成功落地,它的性能如何
阿里巴巴宣布旗下的平头哥半导体完成了安卓10对RISC-V的移植并开源了全部相关代码。从平头哥社区发布的信息来看,安卓10系统已经可以在玄铁910芯片上流畅运行。至于玄铁910,则是前年阿里巴巴旗下的平头哥半导体发布的一款号称是业界最强的RISC-V处理器内核IP。资料显示,玄铁910单核性能达到7.1 Coremark/MHz,主频达到2.5GHz,比当时业界最好的RISC-V处理器性能高40%以上。据介绍,玄铁910可以用于设计制造高性能端上芯片,应用于5G、人工智能以及自动驾驶等领域。
3. 华为平板上的c编译器怎么用
华为平板上的c编译器按照以下步骤使用:
1、下载安装华为平板上的c编译器并运行软件,之后编写代码,写完之后点击运行,可以进行代码的编译组建以及运行。
2、第一次运行,所以需要安装编译模块,直接点击选择安装即可。
3、点击运行之后,能够得到程序的输出,对于格式一类的,可以点击右上角有个缩进可以进行调整格式。
4. a54sxa库如何编译
步骤如下:
1、在ModelSim安装路径下建立一个子文件夹src,例老此如:D:\ModelSim\Actel_lib\VHDL\src
将库的源文件拷贝到src文件夹下
2、运行ModelSim。
3、改变工作路径到D:\ModelSim\Actel_lib\VHDL:
cd D:/ModelSim/Actel_lib/VHDL
注意斜杠方向。(该路径与src文件夹路径一致即可)
4、建立芯片路径:
vlib
例如想要编译a54sxa系列,就输入: vlib a54sxa。想编译A3P1000芯片,就输入:vlib proasic3。
5、将Actel库映射到刚才的路径下:
vmap D:/ModelSim/Actel_lib/VHDL/(其余路径亦可,用以指定编译后的文件放在哪里)
6、编译库。
vcom -work src/.vhd
以SX-A库为例:vcom -work a54sxa src/54sxa.vhd
7、(可选)编译migration library,只有在需要migration library的情况下才需要此步骤,还没搞懂什么是migration library……执行语句渣含斗是这样如磨的
vcom -work src/_mig.vhd
编译verilog库也是一样的步骤,只不过在.vhd的地方改成编译.v文件。
5. 突破封锁!国产芯片终于有了自己的指令集
在半导体芯片领域, 指令系统是一切软硬件生态的起点 。
以大家最熟悉的ARM和X86为例,它们就分别隶属于RISC精简指令集和CISC复杂指令集。
随着物联网、5G、AI新兴领域的兴起,RISC-V和MIPS两大精简指令集架构也频繁出现在我们的视野内。
所谓芯片,其实都是由半导体堆出来的硬件电路,晶体管越多往往代表性能和功能越强。但无论是超级计算机还是智能手环, 它们搭载的处理器都只能识别二进制数据 。
想让这些芯片正常运行,处理复杂的应用场景,首先就要教会它们学会类似九九乘法表的“算法口诀”和“数学公式”, 而这些算法口诀/公式其实就是所谓的“指令集” 。
换句话说, 指令集的功能和效率(算法口诀/公式的类型),在很大程度上就决定了各类芯片的成就和算力的上限 。
虽然海思麒麟、龙芯、兆芯、海光、紫光、澎湃等国产芯片都在各自领域取得了不俗的成绩,但无论是它们,还是其他采用X86、ARM、MIPS、RISC-V、Alpha和Power,选择封闭、授权还是开源的国产芯片项目,其底层的指令集根基都掌握在别人手里。
因此, 只有从指令系统的根源上实现自主,才能打破软件生态发展受制于人的枷锁 。
好消息是,日前龙芯中科就正式发布了自主指令系统架构“Loongson Architecture”,简称为“龙芯架构”或者“LoongArch”。它包括基础架构部分,以及向量扩展LSX、高级向量扩展LASX、虚拟化LVZ、二进制翻译LBT等扩展部分,总共接近2000条指令。同时不包含龙芯此前使用的MIPS指令系统, 并具有完全自主、技术先进、兼容生态三个方面的特点 。
目前,采用LoongArch的龙芯3A5000处理器芯片已经流片成功,完整操作系统也已稳定运行,它能对多种国际主流指令系统的高效二进制翻译链,并成功演示了运行基于其它主流指令系统的复杂应用程序。
LoongArch对MIPS指令的翻译效率是100%性能,对ARM指令翻译的效率是90%性能,对x86的翻译效率是80%性能。
此外,龙芯中科还在联合产业链伙伴在适当的时间建立开放指令系统联盟,在联盟成员内免费共享LoongArch及有关龙芯IP核。
所谓IP核,我们可以理解为ARM旗下的Cortex-A78和Cortex-A55等,后置都是基于ARMv8指令集打造的核心IP架构,并授权给了高通、三星、联发科等芯片商开发SoC移动平台。
目前,ARM刚刚发布了ARMv9指令集,如果不出意外将在下半年发布的Cortex-A79和Cortex-X2架构就将采用这套指令集。
近10年来32位手机处理器都是基于ARMv7指令集打造,在A75之前的处理器则是基于ARMv8-A设计,随后都是ARMv8.2-A一统江湖
ARM指令集可以细分为Cortex-A(ARMv-A)、Cortex-R(ARMv-R)和Cortex-M(ARMv-M),分别适用于不同类型的芯片
比如车载芯片使用的就是Cortex-R(ARMv-R)核心IP
总之, 设计出一个纯国产的自主指令集只是万里长征的第一步 ,关键是后续要做出懂这个指令集的CPU(已经有了龙芯3A5000),再往后还需要让和人类交互的“翻译家”——编译器懂这个指令集。也就是需要不断完善软硬件生态,让我们熟悉的系统、办公、 娱乐 和 游戏 程序都能运行在这套指令集打造的芯片之上。如果做不到这一步,国产指令集和相关芯片也只是空中楼阁而已、
作为国人,我们真心希望LoongArch这种国产指令集可以取得成功,今后无论手机、电脑、车载还是其他半导体芯片都能以使用国产指令集为荣,并走向世界。
扩展小知识
那么,指令集又是如何影响芯片执行效率的?
我们以RISC和CISC,让它们分别执行“清洁地面”的命令为例,看看其背后的指令逻辑差异。
逻辑上,“清洁地面”的大概思路是先拿起扫帚,扫地;拿起簸箕,用扫帚把垃圾扫进簸箕;放下扫帚和簸箕,润湿墩布;再用墩布擦地,直至清洁地面完成。
对CISC复杂指令集而言,很容易理解“清洁地面”这套逻辑,下达“清洁地面”命令后,就能按照规则和顺序,一步步自动完成。
对于RISC精简指令集而言,它一下子可理解不了如此复杂的逻辑,必须将复杂的逻辑顺序拆分,然后按照一项项简单的命令去完成复杂的操作。
比如,想让RISC精简指令集完成“清洁地面”命令,就必须依次下达“拿起扫帚”、“扫地”、“拿起簸箕”、“把垃圾扫进簸箕”、“放下扫帚和簸箕”、“润湿墩布”、“墩地”……
看起来CISC复杂指令集方便又强大?没错,如果要同时清洁无数房间地面,你只要对着不同的房屋说“清洁地面”、“清洁地面”、“清洁地面”……即可。
而对RISC精简指令集,你需要对着每个房间都重复一整套复杂的命令,如果下达指令的人嘴巴不够快(带宽不够大),那清洁地面的效率自然受到影响,难以和CISC复杂指令集抗衡。
但是, 现实生活中,并非所有房间的地面都需要一整套的清洁流程,比如你只需要墩地一个步骤。
对RISC精简指令集而言,你只需对着需要清洁的房间说“墩地”、“墩地”、“墩地”即可。而由于CISC复杂指令集没有单独的“墩地”动作,操作起来就要麻烦许多,完成相同的墩地操作会消耗更多资源,翻译过来就是发热更高更费电。
这就是RISC和CISC的本质区别。 说不上谁好谁坏,只能说它们所擅长的领域各不相同。
以ARM架构为代表的RISC精简指令集,最适合针对常用的命令进行优化,赋予它更简洁和高效的执行环境,对不常用的功能则通过各种精简指令组合起来完成。
RISC是将复杂度交给了编译器,牺牲了程序大小和指令带宽,从而换取了简单和低功耗的硬件实现。
对以X86架构为代表的CISC复杂指令集,则适合更加复杂的应用环境。
CISC是以增加处理器本身复杂度作为代价,以牺牲功耗为代价去换取更高的性能。不过,X86架构则可通过对新型指令集的支持(如SSE4.1、AVX-512等),在一定程度上提高指定任务的执行效率和降低功耗。
现在芯片领域是RISC攻,CISC守的格局。以苹果M1为代表的ARM架构RISC指令集芯片正在染指传统的X86 PC市场,而且大概率会取得成功。虽然以英特尔为代表的X86阵营曾多次试图反击Android生态(如早期的Atom芯片),但最终却都以失败告终。ARM最新发布的ARMv9指令集,就给了ARM芯片入侵X86 PC大本营更多弹药,也许用不了多久Windows ARM版PC也将成为一个更加重要的PC品类。
6. 请问有没有DSP芯片的免费编译器
有啊,各芯片公司都自己提供。
比如TI公司的CCS,这些都是不收费的。