精华内容
下载资源
问答
  • 编译
    千次阅读
    2021-02-23 13:31:29

    第 1 章 交叉编译简介

    1.1 什么是交叉编译

    对于没有做过嵌入式编程的人,可能不太理解交叉编译的概念,那么什么是交叉编译?它有什么作用?

    在解释什么是交叉编译之前,先要明白什么是本地编译。

    本地编译

    本地编译可以理解为,在当前编译平台下,编译出来的程序只能放到当前平台下运行。平时我们常见的软件开发,都是属于本地编译:

    比如,我们在 x86 平台上,编写程序并编译成可执行程序。这种方式下,我们使用 x86 平台上的工具,开发针对 x86 平台本身的可执行程序,这个编译过程称为本地编译。

    交叉编译

    交叉编译可以理解为,在当前编译平台下,编译出来的程序能运行在体系结构不同的另一种目标平台上,但是编译平台本身却不能运行该程序:

    比如,我们在 x86 平台上,编写程序并编译成能运行在 ARM 平台的程序,编译得到的程序在 x86 平台上是不能运行的,必须放到 ARM 平台上才能运行。

    1.2 为什么会有交叉编译

    之所以要有交叉编译,主要原因是:

    • Speed: 目标平台的运行速度往往比主机慢得多,许多专用的嵌入式硬件被设计为低成本和低功耗,没有太高的性能
    • Capability: 整个编译过程是非常消耗资源的,嵌入式系统往往没有足够的内存或磁盘空间
    • Availability: 即使目标平台资源很充足,可以本地编译,但是第一个在目标平台上运行的本地编译器总需要通过交叉编译获得
    • Flexibility: 一个完整的Linux编译环境需要很多支持包,交叉编译使我们不需要花时间将各种支持包移植到目标板上

    1.3 为什么交叉编译比较困难

    交叉编译的困难点在于两个方面:

    不同的体系架构拥有不同的机器特性

    • Word size: 是64位还是32位系统
    • Endianness: 是大端还是小端系统
    • Alignment: 是否必修按照4字节对齐方式进行访问
    • Default signedness: 默认数据类型是有符号还是无符号
    • NOMMU: 是否支持MMU

    交叉编译时的主机环境与目标环境不同

    • Configuration issues:
    • HOSTCC vs TARGETCC:
    • Toolchain Leaks:
    • Libraries:
    • Testing:

    详细的对比可以参看这篇文章,已经写的很详细了,在这就不细说了:Introduction to cross-compiling for Linux

    第 2 章 交叉编译链

    2.1 什么是交叉编译链

    明白了什么是交叉编译,那我们来看看什么是交叉编译链。

    首先编译过程是按照不同的子功能,依照先后顺序组成的一个复杂的流程,如下图:

    编译流程

    那么编译过程包括了预处理、编译、汇编、链接等功能。既然有不同的子功能,那每个子功能都是一个单独的工具来实现,它们合在一起形成了一个完整的工具集。

    同时编译过程又是一个有先后顺序的流程,它必然牵涉到工具的使用顺序,每个工具按照先后关系串联在一起,这就形成了一个链式结构。

    因此,交叉编译链就是为了编译跨平台体系结构的程序代码而形成的由多个子工具构成的一套完整的工具集。同时,它隐藏了预处理、编译、汇编、链接等细节,当我们指定了源文件(.c)时,它会自动按照编译流程调用不同的子工具,自动生成最终的二进制程序映像(.bin)。

    注意:严格意义上来说,交叉编译器,只是指交叉编译的gcc,但是实际上为了方便,我们常说的交叉编译器就是交叉工具链。本文对这两个概念不加以区分,都是指编译链

    2.2 交叉编译链的命名规则

    我们使用交叉编译链时,常常会看到这样的名字:

    arm-none-linux-gnueabi-gcc
    arm-cortex_a8-linux-gnueabi-gcc
    mips-malta-linux-gnu-gcc
    

    其中,对应的前缀为:

    arm-none-linux-gnueabi-
    arm-cortex_a8-linux-gnueabi-
    mips-malta-linux-gnu-
    

    这些交叉编译链的命名规则似乎是通用的,有一定的规则:

    arch-core-kernel-system
    
    • arch: 用于哪个目标平台。
    • core: 使用的是哪个CPU Core,如Cortex A8,但是这一组命名好像比较灵活,在其它厂家提供的交叉编译链中,有以厂家名称命名的,也有以开发板命名的,或者直接是none或cross的。
    • kernel: 所运行的OS,见过的有Linux,uclinux,bare(无OS)。
    • systen:交叉编译链所选择的库函数和目标映像的规范,如gnu,gnueabi等。其中gnu等价于glibc+oabi;gnueabi等价于glibc+eabi。

    注意:这个规则是一个猜测,并没有在哪份官方资料上看到过。而且有些编译链的命名确实没有按照这个规则,也不清楚这是不是历史原因造成的。如果有谁在资料上见到过此规则的详细描述,欢迎指出错误。

    第 3 章 包含的工具

    3.1 Binutils

    Binutils是GNU工具之一,它包括链接器、汇编器和其他用于目标文件和档案的工具,它是二进制代码的处理维护工具。

    Binutils工具包含的子程序如下:

    • ld GNU连接器the GNU linker.
    • as GNU汇编器the GNU assembler.
    • addr2line 把地址转换成文件名和所在的行数
    • ar A utility for creating, modifying and extracting from archives.
    • c++filt Filter to demangle encoded C++ symbols.
    • dlltool Creates files for building and using DLLs.
    • gold A new, faster, ELF only linker, still in beta test.
    • gprof Displays profiling information.
    • nlmconv Converts object code into an NLM.
    • nm Lists symbols from object files.
    • objcopy Copys and translates object files.
    • objdump Displays information from object files.
    • ranlib Generates an index to the contents of an archive.
    • readelf Displays information from any ELF format object file.
    • size Lists the section sizes of an object or archive file.
    • strings Lists printable strings from files.
    • strip Discards symbols

    binutils介绍

    3.2 GCC

    GNU编译器套件,支持C, C++, Java, Ada, Fortran, Objective-C等众多语言。

    3.3 GLibc

    Linux上通常使用的C函数库为glibc。glibc是linux系统中最底层的api,几乎其它任何运行库都会依赖于glibc。glibc除了封装linux操作系统所提供的系统服务外,它本身也提供了许多其它一些必要功能服务的实现。

    glibc 各个库作用介绍

    因为嵌入式环境的资源及其紧张,所以现在除了glibc外,还有uClibc和eglibc可以选择,三者的关系可以参见这两篇文章:

    uclibc eglibc glibc之间的区别和联系

    Glibc vs uClibc Differences

    3.4 GDB

    GDB用于调试程序

    第 4 章 如何得到交叉编译链

    既然明白了交叉编译链的功能,那么在针对嵌入式系统开发时,我们需要的交叉编译链从哪儿得到?

    主要有三个方式可以获取

    4.1 下载已经做好的交叉编译链

    使用其他人针对某些CPU平台已经编译好的交叉编译链。我们只需要找到合适的,下载下来使用即可。

    常见的交叉编译链下载地址:

    1. 在 http://ftp.arm.linux.org.uk/pub/armlinux/toolchain/ 下载已经编译好的交叉编译链
    2. 在 http://www.denx.de/en/Software/WebHome 下载已经编译好的交叉编译链
    3. https://launchpad.net/gcc-arm-embedded下载已经编译好的交叉编译链
    4. 一些制作交叉编译链的工具中,包含了已经制作好的交叉编译链,可以直接拿来使用。如crosstool-NG
    5. 如果购买了某个芯片或开发板,一般厂商会提供对应的整套开发软件,其中就包含了交叉编译链。

    厂家提供的工具一般是经过了严格的测试,并打入了一些必要的补丁,所以这种方式往往是最可靠的工具来源。

    4.2 使用工具定制交叉编译链

    使用现存的制作工具,以简化制作交叉编译链这个事情的复杂度。我们只需要了解有哪些工具可以实现,并选个合适的工具,搞懂它的操作步骤即可。

    1. crosstool-NG
    2. Buildroot
    3. Embedded Linux Development Kit (ELDK)

    工具还有很多,各有各的优势和劣势,大家可以慢慢研究,在这就不细说了。

    4.3 从零开始构建交叉编译链

    这个是最困难也最耗时间的,毕竟制作交叉编译链这样的事情,需要对嵌入式的编译原理了解的比较透彻,至少要知道出了问题要往哪个方面去翻阅资料。而且,也是最考耐心和细心的地方,配错一个选项或是一个步骤,都可能出现以前从来没见过的问题,而且这些问题往往还无法和这个选项或步骤直接联系起来。

    当然如果搭建出来,肯定也是收获最大的,至少对于编译的流程和依赖都比较清楚了,细节上的东西可能还需要去翻看相应的协议或标准,但至少骨架会比较清楚。

    详细的搭建过程可以参看后续的文章,这里面有详细的参数和步骤:
    交叉编译详解 二 从零制作交叉编译链

    为了方便大家搭建交叉编译链,我写了一个一键生成的脚本(包括源码下载和自动编译)。如果大家自己一直搭建不成功,不妨试试这个脚本,然后对比下自己的流程是否一致,参数是否有差异,也许能帮大家迈过这个障碍:
    交叉编译详解 三 使用脚本自动生成交叉编译链

    4.4 对比三种构建方式

    项目使用已有交叉编译链自己制作交叉编译链
    安装一般提供压缩包需要自己打包
    源码版本一般使用较老的稳定版本,对于一些新的GCC特性不支持可以使用自己需要的GCC特性的版本
    补丁一般都会打上修复补丁普通开发者很难辨别需要打上哪些补丁,资深开发者可以针对自己的需求合入补丁
    源码溯源可能不清楚源码版本和补丁情况一切都可以定制
    升级一般不会升级可以随时升级
    优化一般已经针对特定CPU特性和性能进行优化一般无法做到比厂家优化的更好,除非自己设计的CPU
    技术支持可以通过FAE进行支持,可能需要收费只能通过社区支持,免费
    可靠性验证已经通过了完善的验证自己验证,肯定没有专业人士验证的齐全

    参考资料

    [1] Introduction to cross-compiling for Linux

    [2] binutils介绍

    [3] glibc 各个库作用介绍

    [4] uclibc eglibc glibc之间的区别和联系

    [5] Glibc vs uClibc Differences

    [6] 交叉编译链下载地址

    更多相关内容
  • C++反编译工具

    2018-05-15 11:43:19
    C++反编译工具,用来显示与一个可执行文件(exe或者dll)相关的依赖项(dll),以及该exe或dll引用了这些dll中的哪些接口。
  • C# 所有dll反编译工具超强大可下载

    热门讨论 2017-01-03 10:58:39
    C# 所有dll反编译工具超强大 ,编译后的直接复制可用! C# 所有dll反编译工具超强大 ,编译后的直接复制可用!
  • 1. 课程简介 2. 本节课内容大纲 3. 机器学习编译的定义 4. 机器学习编译的目标 5. 为什么要学习机器学习编译? 6. 机器学习编译的核心要素 6.1. 备注:抽象和实现 7. 总结

    1. 课程简介

      该门课程是由XGBoost的作者陈天奇进行授课的。 从2022年6月18日正式开始(新鲜出炉的),每周讲授一节课程。具体内容可参考链接:中文官网或者英文官网。如果有相关问题也可以在讨论区进行留言:中文讨论区英文讨论区

    课程目录如下所示:

    1. 机器学习编译概述
    2. 张量算子函数
    3. 张量函数与整网模型的整合
    4. 整合自定义计算库
    5. 自动化程序优化
    6. 与机器学习框架的整合
    7. 自定义硬件后端
    8. 自动张量化
    9. 计算图优化:算子融合和内存优化
    10. 部署模型到服务环境
    11. 部署模型到边缘设备

      客观来说,本课程并不适合机器学习或者深度学习的初学者。但强烈推荐同学们先学习第一课:机器学习编译概述。然后再决定是否进行更加深入的学习。

      本节课的slides链接如下:https://mlc.ai/summer22-zh/slides/1-Introduction.pdf;notes链接如下:https://mlc.ai/zh/chapter_introduction/

    2. 本节课内容大纲

    1. 什么是机器学习编译?
    2. 机器学习编译的目标是什么?
    3. 为什么要学习机器学习编译?
    4. 机器学习编译的核心要素是什么?

    3. 机器学习编译的定义

      机器学习编译 (machine learning compilation, MLC) 是指,将机器学习算法从开发形态,通过变换和优化算法,使其变成部署形态。简单来说,就是将训练好的机器学习模型应用落地,部署在特定的系统环境之中的过程。

    转换
    开发形态
    部署形态

      开发形态是指我们在开发机器学习模型时使用的形态。典型的开发形式包括用 PyTorch、TensorFlow 或 JAX(主要指的是深度学习学习模型)等通用框架编写的模型描述,以及与之相关的权重。

      部署形态是指执行机器学习应用程序所需的形态。它通常涉及机器学习模型的每个步骤的支撑代码、管理资源(例如内存)的控制器,以及与应用程序开发环境的接口(例如用于Android 应用程序的Java API)。

    在这里插入图片描述
      不同的AI应用对应的部署环境是互不相同的。以下图为例:电商平台不可或缺的推荐系统算法通常是部署在云平台(服务器)上;自动驾驶算法通常是部署在车辆上的专用计算设备;手机的各种APP以语音转文字的输入法为例,最终是部署在手机上的计算设备的。
    在这里插入图片描述
      在进行机器学习模型部署时,不仅要考虑硬件系统环境,与此同时也需要考虑软件环境(如操作系统环境、机器学习平台环境等)。

    4. 机器学习编译的目标

      机器学习编译的直接目标包括两点:最小化依赖和利用硬件加速。机器学习编译的最终目的是实现性能(时间复杂度、空间复杂度)优化。

      最小化依赖可以认为是集成(Integration)的一部分,提取出与应用相关的库(删除与应用无关的库),从而减少应用的大小,达到节省空间的目的。

      利用硬件加速指的是利用硬件本身的特性进行加速。可以通过构建调用原生加速库的部署代码或生成利用原生指令(如 TensorCore)的代码来做到这一点。

    5. 为什么要学习机器学习编译?

    • 构建机器学习部署的解决方案。
    • 对现有机器学习框架形成更加深刻的理解。

    6. 机器学习编译的核心要素

    • 张量 (Tensor) 是执行中最重要的元素。张量是表示神经网络模型执行的输入、输出和中间结果的多维数组。

    • 张量函数 (Tensor functions) 神经网络的“知识”被编码在权重和接受张量和输出张量的计算序列中。我们将这些计算称为张量函数。值得注意的是,张量函数不需要对应于神经网络计算的单个步骤。部分计算或整个端到端计算也可以看作张量函数。也就是说,不仅单个函数可以认为是张量函数,也可以把其中一部分(或者整个整体)看作是张量函数。

    在这里插入图片描述
      下图中举了个实际的例子,第一个linear层和relu计算被折叠成一个linear_relu 函数,这需要有一个特定的linear_relu的详细实现。
    在这里插入图片描述

    6.1. 备注:抽象和实现

      对同样的目标有不同颗粒度的表示。例如对linear_relu而言,既可以使用左边两个框图进行表示,也可以用右边的循环进行表示。
    在这里插入图片描述
      我们使用抽象 (Abstraction)来表示我们用来表示相同张量函数的方式。不同的抽象可能会指定一些细节,而忽略其他实现(Implementations)细节。例如,linear_relu 可以使用另一个不同的 for 循环来实现。

      抽象实现可能是所有计算机系统中最重要的关键字。抽象指定“做什么”,实现提供“如何”做。没有具体的界限。根据我们的看法,for 循环本身可以被视为一种抽象,因为它可以使用 python 解释器实现或编译为本地汇编代码。

      机器学习编译实际上是在相同或不同抽象下转换和组装张量函数的过程。我们将研究张量函数的不同抽象类型,以及它们如何协同工作以解决机器学习部署中的挑战。

      在后续课程中分别会涉及到四种类型的抽象:

    • 计算图
    • 张量程序
    • 库(运行时)
    • 硬件专用指令

    7. 总结

    • 机器学习编译的目标

      • 集成与最小化依赖
      • 利用硬件加速
      • 通用优化
    • 为什么学习机器学习编译

      • 构建机器学习部署解决方案
      • 深入了解现有机器学习框架
      • 为新兴硬件建立软件栈
    • 机器学习编译的关键要素

      • 张量和张量函数
      • 抽象和实现是值得思考的工具
    展开全文
  • ijkplayer0.6.1编译版本

    热门讨论 2016-08-24 16:10:04
    在Ubuntu下编译的ijkplayer0.6.1版本 提供百度云下载地址 在Ubuntu下编译的ijkplayer0.6.1版本 提供百度云下载地址
  • 编译软件ILSpy

    热门讨论 2017-01-23 22:30:22
    编译软件,使用教程看连接:
  • 编译原理_第2版_张素琴

    热门讨论 2014-03-16 22:45:41
    编译原理_第2版_张素琴等_清华大学 由张素琴和吕映芝等编著的《编译原理》介绍编译系统的一般构造原 理、基本实现技术和一些自动构造工具。主要由语言基础知识、词法分析 、语法分析、中间代码生成、代码优化、目标...
  • C++ 程序编译过程

    万次阅读 2021-06-23 22:31:29
    C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作...

    前言

    C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程。链接是把目标文件、操作系统的启动代码和用到的库文件进行组织,形成最终生成可执行代码的过程。过程图解如下:

    在这里插入图片描述

    从图上可以看到,整个代码的编译过程分为编译和链接两个过程,编译对应图中的大括号括起的部分,其余则为链接过程。

    1. 编译过程

    编译过程又可以分成两个阶段:编译和汇编。

    编译
    编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,源文件的编译过程包含两个主要阶段:

    编译预处理
    读取c源程序,对其中的伪指令(以# 开头的指令)和特殊符号进行处理。
    伪指令主要包括以下四个方面:

    1. 宏定义指令,如# define Name TokenString,# undef等。
      对于前一个伪指令,预编译所要做的是将程序中的所有Name用TokenString替换,但作为字符串常量的 Name则不被替换。对于后者,则将取消对某个宏的定义,使以后该串的出现不再被替换。
    2. 条件编译指令,如# ifdef,# ifndef,# else,# elif,# endif等。
      这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。预编译程序将根据有关的文件,将那些不必要的代码过滤掉。
    3. 头文件包含指令,如# include “FileName” 或者# include < FileName> 等。
      在头文件中一般用伪指令# define定义了大量的宏(最常见的是字符常量),同时包含有各种外部符号的声明。
      采用头文件的目的主要是为了使某些定义可以供多个不同的C源程序使用。因为在需要用到这些定义的C源程序中,只需加上一条# include语句即可,而不必再在此文件中将这些定义重复一遍。预编译程序将把头文件中的定义统统都加入到它所产生的输出文件中,以供编译程序对之进行处理。
      包含到c源程序中的头文件可以是系统提供的,这些头文件一般被放在/ usr/ include目录下。在程序中# include它们要使用尖括号(< >)。另外开发人员也可以定义自己的头文件,这些文件一般与c源程序放在同一目录下,此时在# include中要用双引号("")。
    4. 特殊符号,预编译程序可以识别一些特殊的符号。
      例如在源程序中出现的LINE标识将被解释为当前行号(十进制数),FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换。

    预编译程序所完成的基本上是对源程序的“替代”工作。经过此种替代,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。这个文件的含义同没有经过预处理的源文件是相同的,但内容有所不同。下一步,此输出文件将作为编译程序的输入而被翻译成为机器指令。

    编译、优化阶段
    经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main, if , else , for , while , { , } , + , - , * , \ 等等。

    编译程序所要作得工作就是通过词法分析和语法分析,在确认所有的指令都符合语法规则之后,将其翻译成等价的中间代码表示或汇编代码。

    优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化一部分是对中间代码的优化。这种优化不依赖于具体的计算机。另一种优化则主要针对目标代码的生成而进行的。

    对于前一种优化,主要的工作是删除公共表达式、循环优化(代码外提、强度削弱、变换循环控制条件、已知量的合并等)、复写传播,以及无用赋值的删除,等等。

    后一种类型的优化同机器的硬件结构密切相关,最主要的是考虑是如何充分利用机器的各个硬件寄存器存放有关变量的值,以减少对于内存的访问次数。另外,如何根据机器硬件执行指令的特点(如流水线、RISC、CISC、VLIW等)而对指令进行一些调整使目标代码比较短,执行的效率比较高,也是一个重要的研究课题。

    经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。

    汇编
    汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。

    目标文件由段组成。通常一个目标文件中至少有两个段:

    1. 代码段:该段中所包含的主要是程序的指令。该段一般是可读和可执行的,但一般却不可写。
    2. 数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。

    UNIX环境下主要有三种类型的目标文件:

    1. 可重定位文件
      其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。
    2. 共享的目标文件
      这种文件存放了适合于在两种上下文里链接的代码和数据。
      第一种是链接程序可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个目标文件;
      第二种是动态链接程序将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象。
    3. 可执行文件
      它包含了一个可以被操作系统创建一个进程来执行之的文件。

    汇编程序生成的实际上是第一种类型的目标文件。对于后两种还需要其他的一些处理方能得到,这个就是链接程序的工作了。

    2. 链接过程

    由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。

    例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。

    链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。

    根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:

    1. 静态链接
      在这种链接方式下,函数的代码将从其所在的静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码。
    2. 动态链接
      在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。

    对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。

    3. GCC的编译链接

    我们在linux使用的gcc编译器便是把以上的几个过程进行捆绑,使用户只使用一次命令就把编译工作完成,这的确方便了编译工作,但对于初学者了解编译过程就很不利了,下图便是gcc代理的编译过程:
    在这里插入图片描述
    从上图可以看到:

    1. 预编译
      将.c 文件转化成 .i文件
      使用的gcc命令是:gcc –E
      对应于预处理命令cpp
    2. 编译
      将.c/.h文件转换成.s文件
      使用的gcc命令是:gcc –S
      对应于编译命令 cc –S
    3. 汇编
      将.s 文件转化成 .o文件
      使用的gcc 命令是:gcc –c
      对应于汇编命令是 as
    4. 链接
      将.o文件转化成可执行程序
      使用的gcc 命令是: gcc
      对应于链接命令是 ld

    总结起来编译过程就上面的四个过程:预编译处理(.c) --> 编译、优化程序(.s、.asm)--> 汇编程序(.obj、.o、.a、.ko) --> 链接程序(.exe、.elf、.axf等)。

    4. 总结

    C语言编译的整个过程是非常复杂的,里面涉及到的编译器知识、硬件知识、工具链知识都是非常多的,深入了解整个编译过程对工程师理解应用程序的编写是有很大帮助的,希望大家可以多了解一些,在遇到问题时多思考、多实践。

    一般情况下,我们只需要知道分成编译和链接两个阶段,编译阶段将源程序(*.c) 转换成为目标代码(一般是obj文件,至于具体过程就是上面说的那些阶段),链接阶段是把源程序转换成的目标代码(obj文件)与你程序里面调用的库函数对应的代码连接起来形成对应的可执行文件(exe文件)就可以了,其他的都需要在实践中多多体会才能有更深的理解。




    C/C++编译过程
    C/C++编译过程主要分为4个过程
    1) 编译预处理
    2) 编译、优化阶段
    3) 汇编过程
    4) 链接程序

    一、编译预处理
    (1)宏定义指令,如#define Name TokenString,#undef等。 对于前一个伪指令,预编译所要做的是将程序中的所有Name用TokenString替换,
    但作为字符串常量的 Name则不被替换。对于后者,则将取消对某个宏的定义,使以后该串的出现不再被替换。
    (2)条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。 这些伪指令的引入使得程序员可以通过定义不同的宏来决定编译程序对哪些代码进行处理。
    预编译程序将根据有关的文件,将那些不必要的代码过滤掉
    (3) 头文件包含指令,如#include “FileName"或者#include 等。 在头文件中一般用伪指令#define定义了大量的宏(最常见的是字符常量),
    同时包含有各种外部符号的声明。 包含到c源程序中的头文件可以是系统提供的,这些头文件一般被放在/usr/include目录下。
    在程序中#include它们要使用尖括号(< >)。
    另外开发人员也可以定义自己的头文件,这些文件一般与c源程序放在同一目录下,此时在#include中要用双引号(”")。
    (4)特殊符号,预编译程序可以识别一些特殊的符号。 例如在源程序中出现的#line标识将被解释为当前行号(十进制数),
    上面程序实现了对宏line的运用
    (5)预处理模块 预处理工作由#pragma命令完成,#Pragma命令将设定编译器的状态或者是指示编译器完成一些特定的动作。
    #pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。
    依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。
    打开C标准库函数,如stdio.h,我们总能找到下面这一句指示编译器初始化堆栈

    #include "iostream"
    #line 100
    using namespace std;
    int main(int argc, char* argv[])
    {
    cout<<"__LINE__:"<<__LINE__<<endl;
    return 0;
    }
    

    /*--------------------

    • 输出结果为:
    • LINE:103
    • 本来输出的结果应该是 7,但是用#line指定行号之后,使下一行的行号变为,
    • 到输出语句恰为行103
      ---------------------*/
      C/C++编译过程
      或者程序指示编译器去链接系统动态链接库或用户自定义链接库

    二、编译、优化阶段
    经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义,以及C语言的关键字,如main,if,else,for,while,{,}, +,-,*,\等等。
    《编译原理》 中我们可以了解到一个编译器对程序代码的编译主要分为下面几个过程:

    a) 词法分析
    b) 语法分析
    c) 语义分析
    d) 中间代码生成
    e) 代码优化
    f) 代码生成
    g) 符号表管理
    h) 将多个步骤组合成趟
    i) 编译器构造工具

    在这里我们主要强调对函数压栈方式(函数调用约定)的编译处理
    C与C++语言调用方式大体相同,下面是几种常用的调用方式:
    __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,
    这些参数由调用者清除,称为手动清栈。被调用函数不需要求调用者传递多少参数,调用者传递过多或者过少的参数,
    甚至完全不同的参数都不会产生编译阶段的错误。
    _stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,
    最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X表示参数占用的字节数,
    CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,
    并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。
    PASCAL 是Pascal语言的函数调用方式,在早期的c/c++语言中使用这种调用方式,
    参数压栈顺序与前两者相反,但现在我们在程序中见到的都是它的演化版本,其实

    #pragma comment(lib,_T("GDI32.lib"))
    #ifdef _MSC_VER
    /*
    * Currently, all MS C compilers for Win32 platforms default to 8 byte
    * alignment.
    */
    #pragma pack(push,_CRT_PACKING)
    #endif /* _MSC_VER */
    

    C/C++编译过程
    质是另一种调用方式
    _fastcall是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。
    _thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。
    _fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。
    C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。简单的我们可以从printf函数看出
    printf使用从从左至右压栈,返回int型并由_CRTIMP指定封在动态链接库中。
    通过金典的hello world程序我们可以知道编译器对其argc和argv[]这两个参数进行了压栈,并且argc留在了栈顶
    优化处理是编译系统中一项比较艰深的技术。它涉及到的问题不仅同编译技术本身有关,而且同机器的硬件环境也有很大的关系。优化处理主要分为下面几个过程:

    1) 局部优化
    a) 基本块的划分
    b) 基本块的变换
    c) 基本块的DAG表示
    d) DAG的应用
    e) 构造算法讨论
    2) 控制流分析和循环优化
    a) 程序流图与循环

    /*经典的hello world*/
    #include <stdio.h>
    int main(int argc, char* argv[])
    {
    printf("hello world");
    return 0;
    }
    _Check_return_opt_ _CRTIMP int __cdecl printf(_In_z_ _Printf_format_string_ const char * _Format, ...);
    #define CALLBACK _stdcall /* Windows程序回调函数*/
    #define WINAPI _stdcall
    #define WINAPIV _cdecl
    #define PASCAL _stdcall /*在c++语言中使用了StandardCall调用方式*/
    #define PASCAL _cdecl/*在c语言中使用了C DECLaration调用方式*/
    

    C/C++编译过程

    b) 循环
    c) 循环的查找
    d) 可归约流图
    e) 循环优化
    3) 数据流的分析与全局优化
    a) 一些主要的概念
    b) 数据流方程的一般形式
    c) 到达一定值数据流方程
    d) 可用表达式及其数据流方程
    e) 活跃变量数据流方程
    f) 复写传播

    经过优化得到的汇编代码必须经过汇编程序的汇编转换成相应的机器指令,方可能被机器执行。

    三、汇编过程
    汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。对于被翻译系统处理的每一个C语言源程序,
    都将最终经过这一处理而得到相应的目标文件。目标文件中所存放的也就是与源程序等效的目标的机器语言代码。
    目标文件由段组成。通常一个目标文件中至少有两个段: 代码段:该段中所包含的主要是程序的指令。
    该段一般是可读和可执行的,但一般却不可写。 数据段:主要存放程序中要用到的各种全局变量或静态的数据。一般数据段都是可读,可写,可执行的。

    四、链接程序
    由汇编程序生成的目标文件并不能立即就被执行,其中可能还有许多没有解决的问题。
    例如,某个源文件中的函数可能引用了另一个源文件中定义的某个符号(如变量或者函数调用等);
    在程序中可能调用了某个库文件中的函数,等等。所有的这些问题,都需要经链接程序的处理方能得以解决。
    链接程序的主要工作就是将有关的目标文件彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,
    使得所有的这些目标文件成为一个能够诶操作系统装入执行的统一整体。
    根据开发人员指定的同库函数的链接方式的不同,链接处理可分为两种:
    (1)静态链接 在这种链接方式下,函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。
    这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。静态链接库实际上是一个目标文件的集合,
    其中的每个文件含有库中的一个或者一组相关函数的代码。
    (2) 动态链接
    在此种方式下,函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数代码。C/C++编译过程对于可执行文件中的函数调用,可分别采用动态链接或静态链接的方法。使用动态链接能够使最终的可执行文件比较短小,并且当共享对象被多个进程使用时能节约一些内存,因为在内存中只需要保存一份此共享对象的代码。但并不是使用动态链接就一定比使用静态链接要优越。在某些情况下动态链接可能带来一些性能上损害。
    ----------------------------------------------------作者 张彦升

    文章转载自:https://www.cnblogs.com/mickole/articles/3659112.html

    谢谢,创作不易,大侠请留步… 动起可爱的双手,来个赞再走呗 <( ̄︶ ̄)>

    展开全文
  • Android反编译工具包(升级)官方绿色版

    万次下载 热门讨论 2012-10-10 19:18:30
    Android反编译工具包,内含图形和命令两种反编译方式,命令支持windows和linux平台,亲测验证成功!详见博客:Android APK反编译详解(附图) http://blog.csdn.net/sunboy_2050/article/details/6727581
  • 重新理解Linux交叉编译编译流程

    万次阅读 多人点赞 2022-03-12 23:18:42
    文章目录一、背景二、gcc和arm-linux-gcc的常用选项二、交叉编译的四个流程及实例说明1、预处理(preprocessing)2、编译(compilation)3、汇编(assembly)4、链接(linking) 参考书籍 1、编译原理 2、嵌入式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的编译工具使用方法一致,单纯就是名字不一样。

    上图更好理解:
    在这里插入图片描述

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

    1、查询gcc帮助

    先来简单认识下编译工具的使用,我们先看操作,再看原理,以gcc为例子(与arm-linux-gcc使用一致),查询使用帮助:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sVGTABYv-1647098293080)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312211258526.png)]

    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文件为例
    在这里插入图片描述

    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
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j6Djo2jB-1647098293085)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312215503760.png)]
    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
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jgbLRjoG-1647098293087)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312215956177.png)]

    3)方式3

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TQGKkt0b-1647098293087)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312220125123.png)]

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iuF8bn91-1647098293088)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312220207527.png)]

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

    1、预处理(preprocessing)

    问:什么是预处理?

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

    问:为什么需要预处理?

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

    对比hello.i与hello.c文件内容:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W3zylFPg-1647098293089)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312220805414.png)]
    对比hello.i与hello.c大小:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uCFeUudT-1647098293091)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312220946568.png)]
    明显hello.i大很多,原因是从其他文件拷贝了很多代码。

    2、编译(compilation)

    问:什么是编译?

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

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

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

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

    查看hello.s文件
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JSnlKdLy-1647098293091)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312223635993.png)]

    3、汇编(assembly)

    问:什么是汇编

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

    查看hello.o,需要用readelf工具查看
    在这里插入图片描述

    问:什么是反汇编文件?

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

    生成反汇编文件
    在这里插入图片描述

    查看
    在这里插入图片描述

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

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

    4、链接(linking)

    问:什么是链接?

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

    查看hello,需要用readelf工具
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fGs8jYuz-1647098293094)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312225906363.png)]

    问:什么是系统库文件?

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

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

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

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MEIwa5uz-1647098293094)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312231007888.png)]
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xhohe0DU-1647098293095)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312231106971.png)]

    问:什么是标准库文件?

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

    问:什么是动态链接?

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

    gcc默认使用动态库链接

    问:什么是静态链接?

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

    gcc静态链接需加入选项-static
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHJZ7ZQE-1647098293095)(C:\Users\Anson\AppData\Roaming\Typora\typora-user-images\image-20220312231622957.png)]
    很明显静态链接比动态链接生成的可执行文件大很多。

    最后,编译原理还有很多值得深究的问题,比如ELF格式是什么?系统如何支持动态链接的?边实践边学习,由浅及深,通过现象理解本质才能不急不躁。

    展开全文
  • 编译原理 三大神书 龙书 虎书 鲸书。学习编译原理者必备。 用了都说好。
  • GCC编译优化应用预编译

    千次阅读 2022-03-19 17:21:15
    服务器编译优化记录 对项目编译优化过程中一些思路和脚本工具实现。对内存受限的编译环境有一些帮助。 环境 32G内存,16核,Makefile,gcc9.2 效果 选择了代码比较多的三个目录进行预编译头优化,进行下述...
  • 1、参考书籍:《编译原理》第三版 清华大学出版社 1、本文内容全部来源于开源社区 GitHub和以上博主的贡献,本文也免费开源(可能会存在问题,评论区等待大佬们的指正) 2、本文目的:开源共享 抛砖引玉 一起学习 3...
  • 编译系统入门篇-Android10.0编译系统(一)

    万次阅读 多人点赞 2020-10-14 20:32:39
    Android10.0编译系统(二) make编译过程-Android10.0编译系统(三) Image打包流程-Android10.0编译系统(四) Kati详解-Android10.0编译系统(五) Blueprint简介-Android10.0编译系统(六) Blueprint代码详细...
  • jar包反编译工具

    热门讨论 2011-12-15 11:40:19
    jar包反编译工具 很实用! 功能特点: 1、XJad是基于Jad核心的Java源程序反编译软件,内置Jad1.5.8e2; 2、可处理多个*.class文件,可以处理文件夹内的所有文件,甚至可以处理*.jar文件; 3、带有多页面文本编辑器,...
  • g++编译详解

    万次阅读 多人点赞 2019-12-24 18:50:20
    g++编译详解 资料准备: 为了方便演示和讲解,在这里提前准备好几个简单的文件:test.cpp test.h main.cpp 文件内容如下: main.cpp //main.cpp int main (int argc, char **argv) { return 0; } test.h //test....
  • 文章目录编译工具链交叉编译工具链 编译工具链 做C/C++开发特别是嵌入式方向的肯定会涉及编译工具链和交叉编译工具相关内容。 C/C++的程序需要经过 gcc 等编译成二进制程序才能被计算机使用,这里的 gcc 通常是泛指...
  • 编译openjdk

    千次阅读 2021-11-27 21:39:51
    编译openjdk 1. 下载openjdk源码 openjdk的官网是OpenJDK (java.net) 在网站左侧就能看到它的源码位置的链接 从图上可以看到,它的源码在两个位置有托管,Mercurial、GitHub这两个网站都有。我们点击GitHub,进去到...
  • iOS之性能优化·提高App的编译速度

    万次阅读 2021-07-06 20:35:02
    经过多年的开发和迭代,我相信很多的 iOS 项目代码已经达到几十万行甚至上百万行的规模,所使用的 Pod 库的数量可以达到几十个甚至上百个,App Store 安装包也变得越来越大,在这么大的项目规模下,打包和编译问题...
  • python文件编译与pyc反编译

    万次阅读 2020-07-10 17:02:41
    pyc是编译py之后生成的二进制文件。当我们发布系统的时候不想让别人看到源代码,就需要将py文件编译生成pyc文件,对外只提供pyc文件。同样,如果拿到一个python程序,只有pyc文件,我们就无法看到源码,希望有办法反...
  • java如何进行反编译

    千次阅读 2021-03-04 00:12:49
    编译的过程与编译刚好相反,就是将已编译好的编程语言还原到未编译的状态,也就是找出程序语言的源代码。就是将机器看得懂的语言转换成程序员可以看得懂的语言。Java语言中的反编译一般指将class文件转换成java...
  • Java| 编译和反编译

    万次阅读 多人点赞 2018-04-20 15:49:18
    什么是编程语言?... 在介绍编译和反编译之前,我们先来简单介绍下编程语言(Programming Language)。编程语言(Programming Language)分为低级语言(Low-level Language)和高级语言(High-level La...
  • 编译Apk(包括apktool、dex2jar和JD-GUI)下载

    千次下载 热门讨论 2017-01-05 16:21:14
    首先要使用到下载的这两个工具:dex2jar和JD-GUI,前者是将apk中的classes.dex转化成Jar文件,而JD-GUI是一个反编译工 具,可以直接查看Jar包的源代码。 具体步骤: 首先将apk文件,将后缀改为zip,解压,得到其中的...
  • 编译 openwrt

    千次阅读 2020-09-09 14:00:57
    使用 Linux, BSD 或 MacOSX 系统来进行编译. 1.1 安装编译所需依赖的软件包 依赖软件包安装官方示例 通用的 Linux 系统 CentOS # 某些软件包会依赖 EPEL sudo yum install binutils bzip2 gcc gcc-c++ gawk gettext ...
  • openCV编译

    千次阅读 2022-03-26 11:24:50
    最近编译opencv总是出错,收集资料整理了一个如下: 编译命令: cmake \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_INSTALL_PREFIX=/home/caizc/project/A-work/flowserver/tar/flowserver/openCv/openCV4.5/opencv-...
  • 预处理器编译工具

    千次阅读 2022-04-02 10:50:22
    预处理器编译方式与工具
  • Android高版本P/Q/R源码编译指南

    万次阅读 多人点赞 2021-01-04 20:27:17
    文章目录        AndroidP/Q/R编译系统引言一.Android编译整体概述1.1 Kati构建编译系统1.2 Blueprint和Soong构建编译系统1.2.1 Soong简介1.2.2 Blueprint简介1.2.3 Android.bp简介1.2.4 Ninja简介二....
  • win10编译OpenCV4Android系列2-编译OpenCV4.5.2+opencv_contrib 前言 一、编译环境 二、cmake编译 1.生成Makefile 2.使用mingw编译 三、编译问题 问题1:undefined reference to `__imp_GetACP‘ 问题2:error: '::...
  • 上一篇,是使用Qt提供的安装包安装的,有些场景需要使用到从源码编译的Qt,所以本篇如何在银河麒麟系统V4上编译Qt5.12源码。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,528,203
精华内容 1,811,281
关键字:

编译

友情链接: 161345_saves.rar