分享

交叉编译中的build、host和target

 开花结果 2022-03-10

build、host和target

   在交叉编译中比较常见的一些参数就是build、host和target了,正确的理解这三者的含义对于交叉编译是非常重要的,下面就此进行解释
  --build=编译该软件所使用的平台
  --host=该软件将运行的平台
  --target=该软件所处理的目标平台

1> build: 执行代码编译的主机,正常的话就是你的主机系统。这个参数一般由config.guess来猜就可以。当然自己指定也可以。

2> host: 编译出来的二进制程序所执行的主机,因为绝大多数是如果本机编译,本机执行。所以这个值就等于build。只有交叉编译的时候(也就是本机编译,其他系统机器执行)才会build和host不同。用host指定运行主机。

3> target: 这个选项只有在建立交叉编译环境的时候用到,正常编译和交叉编译都不会用到。他用build主机上的编译器,编译一个新的编译器(binutils, gcc,gdb等),这个新的编译器将来编译出来的其他程序将运行在target指定的系统上。

  我们以 gcc 为例子来 讲解 这三者的作用
  在gcc编译中我们使用
  ./configure --build=编译平台 --host=运行平台 --target=目标平台 [各种编译参数]
  来配置gcc的源代码,以让其编译出我们需要的gcc编译器。

  那么在这组配置参数中:
    --build:
       表示目前我们正在运行的平台名称是什么,如果当前我们是在intel的pentium机器中编译该系统,那么我们的--build就可能是 i686-pc-linux-gnu,当然如果我们在其它种类的机器上编译那么这个build就应该是那个机器所对应的平台名称。
     该参数在不指定的情况下将自动尝试猜测目前平台的名称。

    --host:
      表示我们把这个编译好的gcc在什么样的平台下运行,在交叉编译过程中这个需要我们来指定,因为机器自己是不能知道我们心里是怎么想的,那 么我们可以明确的告诉它,我们要做出来的程序是运行在“龙芯”上的,但是目前还不能直接指定“龙芯”,因此我们这里指定为mips64el- unknown-linux-gnu(如果你省点事情那么就用这个名字好了,如果你想用个有个性的名字,那么请你想明白它的含义再动手,并且做好后面的过 程需要多出一些手续的麻烦的心理准备)。
    --host也可以不指定,那么host将自动使用build来定义自己,不过那将不再是交叉编译。
    注:--build和--host在不同的时候就被配置文件认定为交叉编译方式。

    --target:
     该参数的目的是让配置程序知道这个软件被编译后使用来处理什么平台上的文件的。
     target这个参数只有在为数不多的几个包中有用处,虽然在./configure --help中经常能看到该参数,但实际上绝大多数软件包都是不需要该参数的。
     从这个参数的含义来看,说明其处理的目标只有在不同平台下表现为不同的时候才有作用,而这些文件通常都跟目标平台 的指令系统直接或间接有关:比如可执行文件,对于不同平台下使用的可执行文件的编码可以是完全不同的,因此必须使用 对应能处理该编码的程序才能正确处理,而如果错误的使用则可能导致程序错误或者破坏文件,对于这样要处理不同平台下会 出现不同编码的软件,我们就应当对它指定目标平台,以免另其错误处理;而对于文本文件,对于不同的平台同样的内容表达的 含义都是相同的,因此我们不需要专门针对平台来处理,这样的软件我们就可以不必对它指定需要处理的平台了。

    我们来总结一下:
    build:自动测试在用平台名称,若无法检测出来则需要指定。
    host:若无指定,自动使用build的结果。
    build和host相同时表示本地编译,若不相同则表示交叉编译。
    target:表示需要处理的目标平台名称,若无指定使用host相同名称,gcc、binutils等于平台指令相关软件有此参数,多数软件此参数无用处。

    综合的例子:
        我们需要在x86下编译一个运行于arm上的编译器gcc,这个gcc产生mips平台的目标代码。那么我们的配置方式是:
        --build=x86   --host=arm    --target=mips

        (仅是示意,方便理解,具体写法请google)

举例说明如下:

64位:

./autogen.sh --prefix=/path/ --build=x86_64-linux-gnu --host=aarch64-linux-gnu --target=aarch64-linux-gnu --enable-arch=arm64 --with-android-headers=/path/android-headers --enable-adreno-quirks --enable-experimental --with-default-hybris-ld-library-path=/vendor/lib:/system/lib

32位:--host=arm-linux-gnueabi

总的来说,只有host !=build的时候编译才是交叉编译。否则就是正常编译。

配置交叉编译环境

1> 将压缩包复制到 /opt 目录解压, tar -xvJf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz

2> 解压成功后配置环境变量,切换到root权限,vim ~/.bashrc 在最后一行加入

export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH

 3> 执行 source ~/.bashrc 或者 重启系统(/etc/profile也可以配置环境变量,首选)

4> 重新打开终端,切换到root权限,输入aarch64 按 tab 键即可补全说明安装成功,输入 aarch64-linux-gnu-gcc -v 可以查看编译器信息

arm32成功如下

aarch64成功如下

测试程序

#include <stdio.h>

int main(int argc, char **argv)

{

    printf("Hello, you do it succeed!!!\n");

    return 0;

}

  • 先使用arm32编译

  编译完成后,看到文件是32位的。

  移植到arm32板子上,可以运行成功。

  • aarch64编译

编译完成后,看到文件是arm 64位的。

  移植到aarch64的板子上,可以运行成功。

由此可见,两种交叉编译工具都安装成功,可以使用。

在程序编译的时候加上参数-Wl,-rpath,指定编译好的程序在运行时动态库的目录。这种方法会将动态库路径写入到elf文件中去。 -Wl 的意思是将逗号后面的内容传递给 linker链接器。

  -Wa,<options>            Pass comma-separated <options> on to the assembler

  -Wp,<options>            Pass comma-separated <options> on to the preprocessor

  -Wl,<options>             Pass comma-separated <options> on to the linker 

-I /home/test/include 表示将 /home/test/include 目录作为第一个寻找头文件的目录,其寻找的顺序是:

/home/test/include --> /usr/include --> /usr/local/include

-L/home/test/lib 表示将 /home/test/lib 目录作为第一个寻找库文件的目录,其寻找的顺序是:

/home/test/lib --> /lib -> /usr/lib --> /usr/local/lib

-ltest 表示在上面的lib的路径中寻找 libtest.so 动态库文件(如果 gcc 编译选项中加入了“-static”表示寻找 libtest.a 静态库文件),程序链接的库名是test。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多