编译器就是将“高级语言”翻译为“机器语言(低级语言)”的程序,在之前的博客3月25日 编译的四个过程不明白的可以看看。
几个常见的编译器:
(1)GCC(GNU Compiler Collection) 是一个针对于Linux和OS X的编译器。
(2)MinGW(Minimalist GNU for Windows)是一个GCC和GNU Binutils的原生软件端口,用于在Windows上开发原生的Microsoft Windows应用程序。MinGW和Qt Creator以及Qt installers for Windows一起发布。
(3)MSVC:微软的可视C++开发平台。在qt5.9以前,windows版本细分了一些版本,包括MinGW和MSVC,其中MSVC用的VS编译器,还需要安装一些Visual C++的库什么的,总之,如果你的电脑中没有安装VS那就不要安装这个版本了,否则使用时编译通不过。而在之后的版本中,就没有了这种细分,所以我们可以发现5.9之后的安装包都要比之前的大不少。
(4)Linux ICC (Intel C++ Compiler)是针对于Linux的C和C ++编译器。
(5)Clang是一个针对于Windows、Linux和OS X的C、C++、Objective C轻量级编译器。
(6)QCC是编译QNX的C++应用程序的接口。
(7)Custom自定义编译器,需手动添加编译器路径。
想要使用GCC、MinGW、Clang或QCC构建一个应用程序:
例如设置,编译器类型为GCC
想要复制所选择的编译器,可以选择Clone。
在Name字段中,输入编译器的名称以便在Qt Creator中定义它。
在Compiler path字段中,输入路径到编译器所在的目录中。
在Platform codegen flags字段中,检查在目标平台中指定架构传递给编译器的标志。
在Platform linker flags字段中,检查在目标平台上指定架构传递给连接器的标志,当构建Qbs时只能使用连接器标志。其他设置依赖于编译器的指定。
在ABI字段中,为目标架构提供一个标识,用来警告包中错误的ABI配置。
ABI(Application Binary Interface):应用程序二进制接口,描述了应用程序和操作系统之间,一个应用和它的库之间,或者应用的组成部分之间的低接口。它描述了应用程序与OS之间的底层接口。
一套完整的ABI(比如:Intel Binary Compatibility Standard (iBCS)),可以让程序在所有支持该ABI的系统上运行,而无需对程序进行修改。
ABI掩盖了各种细节,例如:
一个完整的ABI,像 Intel二进制兼容标准 (iBCS) ,允许支持它的操作系统上的程序不经修改在其他支持此ABI的操作系统上运行。
其他的 ABI 标准化细节包括C++ name decoration和同一个平台上的编译器之间的调用约定,但是不包括跨平台的兼容性。在Unix的操作系统中,存在很多运行在同一件平台上互相相关但是不兼容的操作系统(尤其是80386兼容系统)。
简单介绍一下API、ABI、系统调用是什么,以及这三个词的区别。
这些词在习惯于像 C 这样的低级编程语言的工程师中是众所周知的,它必须考虑程序的二进制表达式。然而,最近大多数开发人员通常不知道这类知识,因为他们通常使用 Python 等高级语言。
我猜 API 对大多数开发人员来说意味着 Web API。此外,他们听说过 ABI 和系统调用,但不知道这些是什么。为了缓解这种情况,我会尽量简单地解释这些词的含义。
ABI不同于API ,API定义了源代码和库之间的接口,因此同样的代码可以在支持这个API的任何系统中编译 ,然而ABI允许编译好的目标代码在使用兼容ABI的系统中无需改动就能运行。
API 是(Application Programming Interface)应用程序编程接口的首字母缩写。它是对源代码级别的函数(包括 OOPL 中的方法)的规范,这个函数是什么,应该设置什么样的参数,以及返回值是什么。它不负责这些的二进制表达式。
该示例是我在第一节中描述的 Web API。它定义了我们应该访问什么 URL 以及应该设置什么样的数据来从网站获取服务。现在的API和Web API都在使用,没有区别,现在我们理解Web API就是Web服务的API。换句话说,API 是比 Web API 更广泛的词。
我将使用以下 C 源代码再展示一个 API 示例。
int plus(int x, int y) {
return x + y;
}
int main(void) {
int a = 1;
int b = 2;
..
plus(a, b):
..
}
在本源代码中,plus() 函数的 API 如下。
这里 API 并不关心更多的细节,比如 int 类型有多少字节。
ABI 来自应用程序二进制接口。它定义了函数和数据的二进制表达式。它定义了比 API 更详细的规范。它负责一个参数占用多少字节以及数据应该设置在哪里,例如堆栈顶部或 CPU 的寄存器。在某些情况下,它还定义了数据的字节序。
如果您对 x86_64 CPU 架构有基本的了解,还请参见以下 URL。
calling convention
维基百科页面例如,当从非 C 语言调用像 C 库这样的二进制库时,您应该考虑 ABI
理解 API 和系统调用之间的区别有点困难。但是,现在您可以理解它,因为您知道 API 和 ABI 是什么。
我将解释 POSIX C API、Linux 的 C API 和 Linux 的系统调用之间的区别。首先,POSIX 是类 Unix 操作系统的国际标准。 POSIX API 定义了很多东西,比如 POSIX C API,即访问操作系统服务的 C API。
Linux C API 是访问 Linux 服务的 C API。 Linux 尽量提供 POSIX C API 以兼容 POSIX C API。但是,这些与以下不同。
系统调用是操作系统的接口。 Linux 为开发人员提供了许多系统调用,也提供了许多 C API 来使用这些系统调用。此外,本质上,我们必须执行特殊的 CPU 指令才能使用具有 CPU 相关系统调用 ABI 的系统调用。如果你对 Linux 的系统调用 API 感兴趣,请参考这个文档的 A.2.1 调用约定。它定义了 x86_64 CPU 的系统调用 ABI。
有趣的是,Linux 的 C API 中有许多函数不使用与这些函数同名的系统调用。比如Linux提供了fork()
函数,但是这个函数是通过clone()
系统调用来实现的。
描述了以下内容。
如今,这种知识对许多开发人员来说并不重要。但是,总有一天,您必须与低层编程作斗争。那么这篇文章会对你很有帮助。
开发Qt for Android程序的时候,不知道如何选择套件的版本,乱选一通,经常是程序开发完,到了运行选择设备的时候告诉我设备不匹配,不支持这个ABI。下面就来讲讲这些版本。
Qt中套件对应的版本
在我们安装Qt的时候,会有Android相关的选项供我们勾选,我选择了如下图所示的三个选项:
从名字已经可以很直观的看到 ,每个版本对应的是哪个ABI和CPU架构。我记得当时是全选了,5.12.2版的Qt貌似只提供了这三个Android的版本。
套件版本和CPU的关系
对于这两者之间的关系,有一个向下兼容的原则。选择哪个套件来构建工程,取决于你的手机CPU的架构,比如你的安卓手机CPU的架构是ARMv7,那么它可以运行armeabi-v7a编译生成的程序,也能兼容ARMv5,但是Qt没有提供这个版本。如果CPU架构是ARMv8,那么套件可以选择arm64-v8a,也能选择armeabi-v7a。
总而言之一个原则,构建工程的套件版本不能高于手机CPU架构的版本,它只能兼容比它低的版本。
详细的对应关系,如下图所示 (图片来源网络,抱歉我忘记是哪篇博客了,如果侵权请联系):
引入第三方库
如果想要引入第三方库,并且是用Android相关套件编译生成的库,那么同样需要注意版本的问题。跟上面一样,也是向下兼容。编译库文件所选择的套件版本,不能高于引入它的工程的套件版本。
比如我有个库文件叫libAndroid.a,我的工程要引入它,如果我的工程用的是arm64-v8a,那么编译库文件的时候套件可以选择arm64-v8a,也能选择armeabi-v7a;如果工程用的是armebi-v7a,那么编译库文件的时候套件就不能选择arm64-v8a了。
总结
以上就是在选择构建套件版本的选择问题,不是太深,但是作为C++人员来说,进行Qt for Android的开发应当是够用了。如果有存在问题的地方请不吝赐教,感谢!
https://blog.csdn.net/xi_gua_gua/article/details/56999099
https://blog.csdn.net/xi_gua_gua/article/details/56999099
https://devpress.csdn.net/linux/62eed4a0c6770329307f4243.html
https://blog.51cto.com/xiaohaiwa/5437306
https://blog.csdn.net/zhounixing/article/details/89886636/