首先说说交叉编译的事:一个简单的Hello World程序,在x86_64的机器上编译通过后,将其生成的可执行程序拷贝到aarch64的机器上去执行,肯定是执行不通过的,
会报文件格式不正确之类的错误,这是因为程序的编译平台环境和程序的运行平台环境不同导致的,x86_64的机器CPU是amd64架构的(复杂指令集),而aarch64机器的CPU是arm架构的(精简指令集),所以,两个不同指令集结构的机器,是不能相互解释执行的,因为他执行读取等的寻址方式是不同的。
但是为了满足对机器最大程度的利用,对于开发人员来说,又不想每种架构的指令集都搞一台机器放到身边,而是想让不同架构的机器最好在一台机器上就可以将其编译生成可执行程序,然后将执行程序交给客户(可能客户用的是arm机器,而开发大部分都是x86机器),这样既节省了资源,有满足了我们开发人员的需求,两全其美,何乐而不为呢!这就是我们本篇所介绍的方法:交叉编译。
操作系统:Linux
目标机:arm指令集的aarch64机器
宿主机:amd指令集的x86_64机器
目的:在amd的x86_64机器上编译源码,生成可执行程序,在arm的aarch64机器上运行
进阶:简单的HelloWorld没有挑战性和代表性,我们选择依赖底层较多的Qt程序去完成交叉编译
1. 交叉编译器的安装
我们知道,最终需要执行的可执行程序,是通过编译器生成的,编译器会通过机器的架构,组织相关的符号,通过编译链接生成最后的可执行程序,所以,必须得有一种编译器,他自己是可以在x86_64架构升运行的,但是能将源码编译链接生成在aarch64架构上执行的程序。老一辈程序员们已经编出了这样一款软件,其和gcc是一模一样的,只不过我们的gcc是自己运行的平台架构和通过gcc生成的可执行程序运行的平台架构是同一个架构,而aarch64-linux-gnu-gcc是自己运行的平台为x86_64,而生成的可执行程序是在aarch64上运行的,对,就是aarch64-linux-gnu-gcc(C++用aarch64-linux-gnu-g++,同g++),就是我们要用的交叉编译器,可以通过网上直接下载,或直接在线安装,都是可以的。
2. 设置交叉编译器
如果下载安装的交叉编译器系统找不到,可以通过设置环境变量PATH将aarch64-linux-gnu-gcc设置到环境变量中,这样系统就能找到了,一般安装后,在 /usr/bin中就已经存在了,同时会生成 /usr/aarch64-linux-gnu/目录,下面有bin、include、lib三个目录,lib中即为aarch64机器的基本相关库,如果编译的程序有依赖于目标机器的第三方库,则可以将其放到这个lib目录下,保证编译时能够找到。
3. 用交叉编译器编译源文件生成可执行文件
编译源文件是,一定要设置用交叉编译器aarch64-linux-gnu-gcc进行编译,这样生成的文件才能在aarch64平台上运行起来。
选择编译器有两种方式:1. 如果aarch64-linux-gnu-gcc所在的目录(可以用whereis aarch64-linux-gnu-gcc进行查看)已经设置在环境变量PATH中,则可以直接用aarch64-linux-gnu-gcc main.cpp -o main进行生成。 2. 如果aarch64-linux-gnu-gcc所在目录没有环境变量PATH中,可以将其目录设置到PATH中,然后重启或用source使其生效,然后同第一步。 3.将系统中的gcc直接软连接到aarch64-linux-gnu-gcc上,然后就像正常使用gcc编译器一样编译源码就好了。
通过以上三步,就可以在x86_64平台上编译出能在aarch64上运行的程序了。
以下为简单的HelloWorld源码的编译步骤:
int main(int argc, char* argv[])
{
printf("Hello World!\n");
return ;
}
在终端执行:aarch64-linux-gnu-gcc main.cpp -o main
生成main的可执行文件后,查看文件格式:file main,输出:
显示文件是ARM aarch64,说明交叉编译成功,且在该平台是运行不起来的,报“可执行文件格式错误”,必须到aarch64平台上运行,截图如下:
main: ELF 64-bit LSB shared object, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1,
for GNU/Linux 3.7.0, BuildID[sha1]=d933995224ec8ca652d9585e36d0130596af490b, not stripped
以上即为简单的交叉编译,没有依赖其他第三方的库,只要有aarch64平台的libc.so库即可以了。
由于以上的简单HelloWorld程序没有依赖第三方库,所以其在实际项目中没有代表性,只能说明交叉编译的基本原来,更复杂的交叉编译,是需要依赖很多相关库的,在下篇中所介绍的Qt应用程序交叉编译,即使在实际项目中所用的,敬请期待下篇【交叉编译实践-Qt应用程序交叉编译】。