重新理解Linux交叉编译及编译流程

这篇具有很好参考价值的文章主要介绍了重新理解Linux交叉编译及编译流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考书籍
1、编译原理
2、嵌入式Linux应用开发

一、交叉编译背景

当我们开发目标是一个嵌入式设备时,便需要在PC机上编译出能在该嵌入式设备上运行的可执行文件,这里编译主机与目标运行主机不是同一个设备,那么该过程就称为交叉编译;而编译是指一个源代码文件(这里指的是编译性程序源文件,与之对应的是解释性程序),如C/C++文件要经过预处理(preprocessing)、编译(compilation)、汇编(assembly)和链接(linking)等4步才能变成可执行文件,注意在日常交流中通常使用“编译”统称这4个步骤。

当我们在 Windows下利用IDE工具,即集成开发环境(比如 Visual studio、keil、IAR、Eclipse等等)进行开发时,只需要单击几个按钮即可编译,因为IDE工具已经将各种编译工具的使用封装好了。

Linux下也有很优秀的集成开发工具,但是更多的时候是直接使用编译工具;比如嵌入式开发中,运行在PC平台上的编译工具链为gcc、ld、objcopy、objdump等,它们编译出来的程序在x86平台上运行。要编译出能在 ARM 平台上运行的程序,则须使用交叉编译工具 arm-linux-gcc、arm-linux-ld、arm-linux-objcopy、arm-linux-objdump等;PC与ARM的编译工具使用方法一致,单纯就是名字不一样。

小插曲:关于开发工具的使用,搭建开发环境和熟悉工具使用是进行开发的第一步,也是一道难关,尤其面对多种多样的工具和环境,让人抓狂;其实这也无可厚非,因为各种系统、产品本身具有自己的特点以及软件工具的限制(知识产权),显然要做到一个工具通吃是不现实的,而一般在学习网络教程/公司企业工作时所使用的工具,有可能会直接采用某官方发布的软件,也有可能经过二次开发/封装而来,面对这种情况,我们其实不用去抗拒,学习开发工具本身就是开发过程中必要的一部分,熟练掌握一套工具后,同类的工具上手也会很快的,因此要积极对待。

上图更好理解:
重新理解Linux交叉编译及编译流程

二、gcc和arm-linux-gcc的常用选项

1、查询gcc帮助

先来简单认识下编译工具的使用,我们先看操作,再看原理,以gcc为例子(与arm-linux-gcc使用一致),查询使用帮助:
重新理解Linux交叉编译及编译流程

2、常用gcc选项介绍

gcc选项很多,一般大型开发项目都会使用很多控制选项,这里仅介绍简单常用选项:

-v:查看gcc编译器的版本,显示gcc执行时的详细过程
-o <file>         Place the output into <file> (指定输出文件名为file,这个名称不能跟源文件名同名)
                           
-E                       Preprocess only; do not compile, assemble or link(只预处理,不会编译、汇编、链接)
                           
-S                       Compile only; do not assemble or link(只编译,不会汇编、链接)
                           
-c                       Compile and assemble, but do not link(编译和汇编,不会链接 )

3、生成一个可执行文件的三种方法

以hello.c文件为例
重新理解Linux交叉编译及编译流程

1)方式1

gcc -E -o hello.i hello.c
gcc -S -o hello.s hello.i
gcc -c -o hello.o hello.s
gcc -o hello hello.o

重新理解Linux交叉编译及编译流程
gcc会对.c文件默认进行预处理操作,-c再来指明了编译、汇编,从而得到*.o文件(object file 即我们常说的目标文件),再通过gcc -o hello hello.o将.o文件进行链接,得到可执行应用程序。

小结:
1)输入文件的后缀名和选项共同决定gcc到底执行哪些操作。
2)在编译过程中,除非使用了-E、-S、-c选项(或者编译出错阻止了完整的编译过程),否则最后的步骤都是链接。

2)方式2 - 开发项目中常用的方式

gcc -c -o hello.o hello.c
gcc -o hello hello.o

重新理解Linux交叉编译及编译流程

3)方式3

gcc -o hello hello.c  输出hello,然后./hello来执行该应用程序。

重新理解Linux交叉编译及编译流程

注:如果不指定输出文件名,则默认生成a.out

gcc hello.c  输出一个a.out,然后./a.out来执行该应用程序。

重新理解Linux交叉编译及编译流程

三、交叉编译的四个流程及实例说明

1、预处理(preprocessing)

问:什么是预处理?

C/C++源文件中,以“#“开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些代码输出到一个".i"文件,也就是说还是源代码文件;

问:为什么需要预处理?

一般预处理都是些简单的替换、拷贝和选择,这些涉及多个文件,预处理的结果是将每个源文件所需要的代码都放在自己文件里,然后方便下一步处理(ps:因为编译时,编译器每次读入一个文件,输出一个文件,不支持同时处理多个文件 - 来源于“编译原理”);

对比hello.i与hello.c文件内容:
重新理解Linux交叉编译及编译流程
对比hello.i与hello.c大小:
重新理解Linux交叉编译及编译流程
明显hello.i大很多,原因是从其他文件拷贝了很多代码过来。

2、编译(compilation)

问:什么是编译?

编译就是把C/C++代码(比如上述的“.i”文件)翻译成汇编代码,这部分涉及复杂的编译器原理,有兴趣可以自行去看书深究;

问:为什么要翻译成汇编,而不直接生成机器码?

1、其一由于最开始的底层开发语言是汇编,而高级语言是在底层语言基础上发展的,自然而然会将成熟的工具(汇编器)利用起来,同时实现软件分层可以有效地减弱编译器编写的复杂性,“编译”所拆分的四大步骤也是如此道理;

2、其二有一个好处是方便优化和调试,汇编语言是机器指令的助记 符,一个汇编指令就对应一条机器指令,因此汇编语言更贴近机器特性,因此比高级语言调试起来更有优势;

查看hello.s文件
重新理解Linux交叉编译及编译流程

3、汇编(assembly)

问:什么是汇编

汇编(注意这里的汇编指的是编译器的一个编译动作,不是汇编语言)是利用汇编器将第二步输出的汇编代码翻译成符合一定格式的机器代码,就是我们熟悉的目标文件(*.o),在Linux系统上一般表现为ELF格式文件;如果开发代码是汇编,则汇编+链接就可以生成可执行文件了;

查看hello.o,需要用readelf工具查看
重新理解Linux交叉编译及编译流程

问:什么是反汇编文件?

反汇编文件是由可执行文件逆向解析而来,内容是按照实际内存分布来排布的,包含地址信息,一般用来调试分析用,非常有用;

生成反汇编文件
重新理解Linux交叉编译及编译流程

查看
重新理解Linux交叉编译及编译流程

问:汇编文件与反汇编文件的区别?

反汇编文件比汇编文件多了调试信息,如物理地址、机器码等,而汇编文件单纯只是汇编代码;

4、链接(linking)

问:什么是链接?

链接就是将汇编生成的OBJ文件、系统库的OBJ文件、库文件链接起来,即将各个ELF文件重新排序成一个ELF文件,最终生成可以在特定平台运行的可执行程序。

查看hello,需要用readelf工具
重新理解Linux交叉编译及编译流程

问:什么是系统库文件?

系统库文件:一个应用程序要运行在系统上,就需要系统标准启动文件,提供给系统用的;注意裸机bootloader、linux内核等程序是不能使用启动文件以及标准库文件(因为启动文件和库文件的使用是需要系统支持)。

一般gcc自动加入的系统标准启动文件有:crt1.o、crti.o、crtbegin.o、crtend.o、crtn.o
对于一般应用程序,这些启动是必需的。

通过查看gcc详细编译过程可以看到

重新理解Linux交叉编译及编译流程
重新理解Linux交叉编译及编译流程

问:什么是标准库文件?

很好理解,即库文件,如果代码用到标准库函数,而gcc集成了常用的库,链接时自动检索加入;

问:什么是动态链接?

动态链接使用动态链接库进行链接,生成的程序在执行的时候需要加载所需的动态库才能运行。
动态链接生成的程序体积较小,但是必须依赖所需的动态库,否则无法执行。

gcc默认使用动态库链接

问:什么是静态链接?

静态链接使用静态库进行链接,生成的程序包含程序运行所需要的全部库,可以直接运行,
不过静态链接生成的程序体积较大。

gcc静态链接需加入选项-static
重新理解Linux交叉编译及编译流程
很明显静态链接比动态链接生成的可执行文件大很多。

最后,编译原理还有很多值得深究的问题,比如ELF格式是什么?系统如何支持动态链接的?边实践边学习,由浅及深,通过现象理解本质才能不急不躁。文章来源地址https://www.toymoban.com/news/detail-400904.html

到了这里,关于重新理解Linux交叉编译及编译流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 一文搞懂交叉编译,Windows和Linux的交叉编译

    在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码,我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说,就是在一个平台上生成另一个平台上的可执行代码。这里需要注意的是所谓平台,实际上包含两个概念:体系结构(

    2024年02月07日
    浏览(61)
  • 【交叉编译环境】安装arm-linux交叉编译环境到虚拟机教程(简洁版本)

    就是看到了好些教程有些繁琐,我就写了一个 我这个解压安装的交叉编译环境是Linaro GCC的一个版本,可以用于在x86_64的主机上编译arm-linux-gnueabihf的目标代码 步骤来了 在你的Ubuntu系统中 创建一个目录 ,例如/usr/local/arm,然后将下载好的gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueab

    2024年02月03日
    浏览(38)
  • ARM_Linux的交叉开发以及交叉编译器

    目录 为什么要使用交叉开发 为什么要使用交叉编译 交叉编译器的安装 交叉编译器的使用 交叉开发是指在通用的电脑上吧程序编写,编译,调试好,再下载到嵌入式产品中去运行,对于一些简单的程序的话,直接在电脑上编译调试好即可,但是对于一些需要操作硬件的开发

    2024年01月23日
    浏览(47)
  • Linux——ARM交叉编译环境搭建

    可依据自己当前的环境进行选择下载,官网如下​​​ Downloads | GNU-A Downloads – Arm Developer 我这边选择如下,用于4412开发板的 gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz mkdir  /usr/local/arm tar -xvf gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz 在 vim /root/.bashrc 或 vim /etc/profi

    2024年02月21日
    浏览(49)
  • ARM & Linux 基础学习 / 配置交叉编译工具链 / 编译 Linux 应用和驱动 / 编译内核

    编辑整理 by Staok。 本文部分内容摘自 “100ask imx6ull” 开发板的配套资料(如 百问网的《嵌入式Linux应用开发完全手册》,在 百问网 imx6ull pro 开发板 页面 中的《2.1 100ASK_IMX6ULL_PRO:开发板资料》或《2.2 全系列Linux教程:在线视频与配套资料》里面可以下载到),还有参考 菜

    2024年02月04日
    浏览(47)
  • 虚拟机-Linux开发板交叉编译问题记录

    遇到一堆很久之前见过的问题,重新解决一次。 1、虚拟机没法上网 发现虚拟机浏览器上不了网,运行ifconfig查看,发现要么没有IP地址,要么只有IPv6的地址。最后发现是昨天VMware卡死了,启动任务管理器把相关任务全停了,dhcp服务没启动。于是点进计算机-管理-服务,重新

    2024年04月12日
    浏览(39)
  • 使用CMake交叉编译Arm Linux程序

    注意,工具链文件的指定一定要紧跟cmake命令之后,不能放到 … 后面构建arm架构cmake 工程里新建一个文件叫arm_linux_setup.cmake arm_linux_setup.cmake内容如下

    2024年02月03日
    浏览(52)
  • LuaJit交叉编译移植到ARM Linux

    Lua与LuaJit的主要区别在于LuaJIT是基于JIT(Just-In-Time)技术开发的,可以实现动态编译和执行代码,从而提高了程序的运行效率。而Lua是基于解释器技术开发的,不能像LuaJIT那样进行代码的即时编译和执行。因此,在运行速度方面,LuaJIT要比Lua快得多。此外,LuaJIT还支持更多的

    2024年02月05日
    浏览(37)
  • Linux交叉编译opencv并移植ARM端

    Linux交叉编译opencv并移植ARM端 - 知乎 目标平台为arm7l,此为32位ARM架构,要安装合适的编译器 注意:64位ARM架构的编译器与32位ARM架构的编译器不能通用 opencv的交叉编译工具链在../opencv3.2.0/platforms/linux 路径下,linux文件夹下是一些.cmake文件,对应不同的移植对象,我需要在rv

    2024年02月12日
    浏览(42)
  • 嵌入式Linux Qt交叉编译环境搭建

    TinkerBoard2主板,BuildRoot根文件系统,package自带的Qt版本为5.14.2,所以安装的版本也是5.14.2 安装的组件看个人需求,我都要了 默认安装路径/opt/Qt5.14.2/ 源码路径/opt/Qt5.14.2/5.14.2/Src/ 安装后选定的打包工具路径/opt/Qt5.14.2/5.14.2/(我的默认有gcc_64和android) 这种方法容易导致version `G

    2024年01月25日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包