精华内容
下载资源
问答
  • c++编译过程

    千次阅读 2018-03-03 14:58:48
    c++编译过程简介了解编译过程的益处c++工程相关的问题什么是库?静态库和动态库又有什么区别?头文件起什么作用?编译过程简介名词:编译:把源文件中的源代码翻译成机器语言,保存到目标文件中。如果编译通过,就会...

    c++编译过程简介

    • 了解编译过程的益处
      • c++工程相关的问题
        • 什么是库?静态库和动态库又有什么区别?
        • 头文件起什么作用?
    • 编译过程简介
      • 名词:
        • 编译:把源文件中的源代码翻译成机器语言,保存到目标文件中。如果编译通过,就会把CPP转换成OBJ文件。
        • 编译单元:
          • 每个cpp就是一个编译单元,每个编译单元相互之间是独立且相互不知的。一个编译单元(Translation Unit)是指一个.cpp文件以及这所include的所有.h文件,.h文件里面的代码将会被扩展到包含它的.cpp文件里,然后编译器编译该.cpp文件为一个.obj文件,后者拥有PE(Portable Executable,即Windows可执行文件)文件格式,并且本身包含的就是二进制代码,但是不一定能执行,因为并不能保证其中一定有main函数。当编译器将一个工程里的所有.cpp文件以分离的方式编译完毕后,再由链接器进行链接成为一个.exe或.dll文件。
        • 目标文件:编译后生成的文件,以机器码的形式包含了编译单元里所有的函数和数据、导出符号表、未解决符号表、地址重定向表
          • 目标文件的类型:
            • 可重定位文件(.o、.obj文件):其中包含有适合于其它目标文件链接来创建一个可执行的或者共享的目标文件的代码和数据。每个cpp会被编译成一个.o文件
            • 共享的目标文件(库文件)
              • 这种文件存放了适合于在两种上下文里链接的代码和数据。
                • 第一种是链接程序(静态库)可把它与其它可重定位文件及共享的目标文件一起处理来创建另一个目标文件
                  • 静态链接库实际上是一个目标文件的集合,其中的每个文件含有库中的一个或者一组相关函数的代码
                • 第二种是动态链接程序(动态库)将它与另一个可执行文件及其它的共享目标文件结合到一起,创建一个进程映象
                  • 动态链接库在程序执行时才被调用
            • 可执行文件
              • 一个可以被操作系统创建一个进程来执行之的文件
          • .o文件在编译后就能获得,但是库文件、可执行文件都需要在链接后才能获得
      • c++程序编译过程图
        •  
      • 编译过程
        • 作用:编译是读取源程序(字符流),对之进行词法和语法的分析,将高级语言指令转换为功能等效的汇编代码,再转换为机器代码,生成目标文件(.obj)
        • 分为两个过程
          • 编译: 
            • 预处理阶段
              • 宏#define
              • 条件编译指令,如#ifdef,#ifndef,#else,#elif,#endif等。
              • 头文件包含,#include <iostream>
              • 特殊符号
                • LINE标识将被解释为当前行号(十进制
                  数)
                • FILE则被解释为当前被编译的C源程序的名称。预编译程序对于在源程序中出现的这些串将用合适的值进行替换
            • 编译、优化阶段
              • 针对代码优化,不依赖具体计算机
              • 针对计算机优化
          • 汇编
            • 把汇编语言代码翻译成目标机器指令,生成目标文件(.o文件、.obj文件)。此过程会依赖机器的硬件和操作系统环境。
        • 3张表:.o文件至少要提供3张表
          • 导出符号表:即该目标文件可以提供的符号及地址
          • 未解决符号表:即找不到地址的符号的列表,告诉链接器这些符号没找到地址
          • 地址重定向表:
            • 链接的时候,链接器会为目标文件的“未解决符号表”里的符号在其他目标文件中寻找地址,但是每个目标文件的地址都是从0x0000开始的,这样直接将对方文件中符号的地址拿过来用显然会是不正确的,为了区分不同的文件,链接器在链接时就会对每个目标文件的地址进行调整。在这个例子中,假如B.obj的0x0000被定位到可执行文件的0x00001000上,而A.obj的0x0000被定位到可执行文件的0x00002000上,那么实现上对链接器来说,A.obj的导出符号地地址都会加上0x00002000,B.obj所有的符号地址也会加上0x00001000。这样就可以保证地址不会重复。
            • 因为被加上了起始地址,所以符号在自身文件中的实际地址就不对了,需要再用一张地址重定向表记录符号相对自身文件的地址
        • 例子:
      • 链接过程
        • 链接:链接程序的主要工作就是将有关的目标文件(库文件、.o文件)彼此相连接,也即将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。
        • 具体工作: 
          当链接器进行链接的时候,首先决定各个目标文件在最终可执行文件里的位置。然后访问所有目标文件的地址重定义表,对其中记录的地址进行重定向(加上一个偏移量,即该编译单元在可执行文件上的起始地址)。然后遍历所有目标文件的未解决符号表,并且在所有的导出符号表里查找匹配的符号,并在未解决符号表中所记录的位置上填写实现地址。最后把所有的目标文件的内容写在各自的位置上,再作一些另的工作,就生成一个可执行文件。
        • 链接方式
          • 静态链接:函数的代码将从其所在地静态链接库中被拷贝到最终的可执行程序中。这样该程序在被执行时这些代码将被装入到该进程的虚拟地址空间中。
          • 动态链接:函数的代码被放到称作是动态链接库或共享对象的某个目标文件中。链接程序此时所作的只是在最终的可执行程序中
            记录下共享对象的名字以及其它少量的登记信息。在此可执行文件被执行时,动态链接库的全部内容将被映射到运行时相应进程的虚地址空间。动态链接程序将根据可执行程序中记录的信息找到相应的函数
            代码。
      • 两种链接方式的比较
    • C/C++中提供的一些特性
      • extern:这就是告诉编译器,这个变量或函数在别的编译单元里定义了,也就是要把这个符号放到未解决符号表里面去(外部链接)。
      •  static:如果该关键字位于全局函数或者变量的声明前面,表明该编译单元不导出这个函数或变量,因些这个符号不能在别的编译单元中使用(内部链接)。如果是static局部变量,则该变量的存储方式和全局变量一样,但是仍然不导出符号。
      • 默认链接属性:对于函数和变量,默认链接是外部链接,对于const变量,默认内部链接。
      • 外部链接的利弊:外部链接的符号在整个程序范围内都是可以使用的,这就要求其他编译单元不能导出相同的符号(不然就会报 duplicated external symbols)。
      • 为什么头文件里一般只可以有声明不能有定义:头文件可以被多个编译单元包含,如果头文件里面有定义的话,那么每个包含这头文件的编译单元都会对同一个符号进行定义,如果该符号为外部链接,则会导致duplicated external symbols链接错误。
      • 为什么公共使用的内联函数要定义于头文件里:因为编译时编译单元之间互不知道,如果内联被定义于.cpp文件中,编译其他使用该函数的编译单元的时候没有办法找到函数的定义,因些无法对函数进行展开(内联函数不展开,即不采用在使用处标记函数代码再跳转的方式,而是直接将代码嵌入)。所以如果内联函数定义于.cpp里,那么就只有这个.cpp文件能使用它。
      • .h中的inline 函数可以被多个cpp包含而不造成符号冲突,因为它会被直接嵌入到调用的地方,内部联结不形成外部符号,对外不可见
    • 常见编译器
    • makefile及make工具
    • 常见编译器使用方法
    • 编译错误解析

    ***?为什么函数默认是外部链接?

    答:

    如果函数默认是内部链接,那么大家会倾向于把函数连同其定义都放入头文件中。然而,函数是多变的,可能会经常修改,这样一来,所以包含它的模块都需要被重新编译,很麻烦。另外一方面,如果函数中定义了静态变量,这样每一个包含该函数的模块都会有一个静态变量(因为假设是默认内部链接),导致不一致。


    ***?为什么const常量默认是内部链接而变量(全局)默认是外部链接?

    答:

    因为它是常量,初始化后就不能改变,这样即使每一个包含它的模块都有一份它的复制,那也不会导致不一致。如果变量默认是内部链接,它是可变的量,所以在每个包含它的模块中,它的值可能会被改变,从而导致不一致的状况出现。


    ***?为什么类的静态数据成员不可以就地初始化?

    答:

    因为类体一般是放在头文件中的,如果允许其静态成员就地初始化,那就相当于允许在头文件中定义变量了。

    展开全文
  • python编译过程和执行原理

    万次阅读 多人点赞 2017-09-26 17:46:10
    python编译过程和执行原理 (1)python执行原理 这里的解释执行是相对于编译执行而言的。我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的机器语言,经过链接器链接之后形成了...

    python编译过程和执行原理

    (1)python执行原理

     这里的解释执行是相对于编译执行而言的。我们都知道,使用C/C++之类的编译性语言编写的程序,是需要从源文件转换成计算机使用的机器语言,经过链接器链接之后形成了二进制的可执行文件。运行该程序的时候,就可以把二进制程序从硬盘载入到内存中并运行。

          但是对于Python而言,python源码不需要编译成二进制代码,它可以直接从源代码运行程序。当我们运行python文件程序的时候,python解释器将源代码转换为字节码,然后再由python解释器来执行这些字节码。这样,python就不用担心程序的编译,库的链接加载等问题了。

          对于python解释语言,有以下3方面的特性:

    1. 每次运行都要进行转换成字节码,然后再有虚拟机把字节码转换成机器语言,最后才能在硬件上运行。与编译性语言相比,每次多出了编译和链接的过程,性能肯定会受到影响;而python并不是每次都需要转换字节码,解释器在转换之前会判断代码文件的修改时间是否与上一次转换后的字节码pyc文件的修改时间一致,若不一致才会重新转换。
    2. 由于不用关心程序的编译和库的链接等问题,开发的工作也就更加轻松啦。
    3. python代码与机器底层更远了,python程序更加易于移植,基本上无需改动就能在多平台上运行。

          在具体计算机上实现一种语言,首先要确定的是表示该语言语义解释的虚拟计算机,一个关键的问题是程序执行时的基本表示是实际计算机上的机器语言还是虚拟机的机器语言。这个问题决定了语言的实现。根据这个问题的回答,可以将程序设计语言划分为两大类:编译型语言和解释型语言。

    1.   编译实现的语言,如:C、C++、Fortran、Pascal、Ada。由编译型语言编写的源程序需要经过编译,汇编和链接才能输出目标代码,然后由机器执行目标代码。目标代码是有机器指令组成,不能独立运行,因为源程序中可能使用了一些汇编程序不能解释引用的库函数,而库函数又不在源程序中,此时还需要链接程序完成外部引用和目标模板调用的链接任务,最后才能输出可执行代码。
    2.  解释型语言,解释器不产生目标机器代码,而是产生中间代码,这种中间代码与机器代码不同,中间代码的解释是由软件支持的,不能直接使用在硬件上。该软件解释器通常会导致执行效率较低,用解释型语言编写的程序是由另一个可以理解中间代码的解释程序执行的。和编译的程序不同的是, 解释程序的任务是逐一将源代码的语句解释成可执行的机器指令,不需要将源程序翻译成目标代码再执行。对于解释型语言,需要一个专门的解释器来执行该程序,每条语句只有在执行是才能被翻译,这种解释型语言每执行一次就翻译一次,因而效率低下。
    3.  Java解释器,java很特殊,java是需要编译的,但是没有直接编译成机器语言,而是编译成字节码,然后在Java虚拟机上用解释的方式执行字节码。Python也使用了类似的方式,先将python编译成python字节码,然后由一个专门的python字节码解释器负责解释执行字节码。
    4.   python是一门解释语言,但是出于效率的考虑,提供了一种编译的方法。编译之后就得到pyc文件,存储了字节码。python这点和java很类似,但是java与python不同的是,python是一个解释型的语言,所以编译字节码不是一个强制的操作,事实上,编译是一个自动的过程,一般不会在意它的存在。编译成字节码可以节省加载模块的时间,提高效率。
    5.   除了效率之外,字节码的形式也增加了反向工程的难度,可以保护源代码。这个只是一定程度上的保护,反编译还是可以的。

    (2)Python内部执行过程

    一、编译过程概述

      当我们执行Python代码的时候,在Python解释器用四个过程“拆解”我们的代码,最终被CPU执行返回给用户。

      首先当用户键入代码交给Python处理的时候会先进行词法分析,例如用户键入关键字或者当输入关键字有误时,都会被词法分析所触发,不正确的代码将不会被执行。

      下一步Python会进行语法分析,例如当"for i in test:"中,test后面的冒号如果被写为其他符号,代码依旧不会被执行。

      下面进入最关键的过程,在执行Python前,Python会生成.pyc文件,这个文件就是字节码,如果我们不小心修改了字节码,Python下次重新编译该程序时会和其上次生成的字节码文件进行比较,如果不匹配则会将被修改过的字节码文件进行覆盖,以确保每次编译后字节码的准确性。

      那么什么是字节码?字节码在Python虚拟机程序里对应的是PyCodeObject对象。.pyc文件是字节码在磁盘上的表现形式。简单来说就是在编译代码的过程中,首先会将代码中的函数、类等对象分类处理,然后生成字节码文件。有了字节码文件,CPU可以直接识别字节码文件进行处理,接着Python就可执行了。

    二、过程图解

    三、编译字节码

      Python中有一个内置函数compile(),可以将源文件编译成codeobject,首先看这个函数的说明:

      compile(...) compile(source, filename, mode[, flags[, dont_inherit]]) -> code object

      参数1:源文件的内容字符串

      参数2:源文件名称

      参数3:exec-编译module,single-编译一个声明,eval-编译一个表达式 一般使用前三个参数就够了

      使用示例:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    #src_file.py

    #some function

    def f(d=0):

        c=1

        print "hello"

    a=9

    b=8

    f()

     

    >>> a=open('src_file.py','r').read()    #命令行模式中打开源文件进行编译

    >>> co=compile(a,'src_file','exec')

    >>> type(co)

    <type 'code'>    #编译出了codeobject对象

    四、codeobject对象的属性

      codeobject有哪些变量,接上节的内容分析一下:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    >>> print co.co_names    #所有的符号名称

    ('f', 'a', 'b')

     

    >>> print co.co_name    #模块名、函数名、类名

    <module>

     

    >>> print co.co_consts    #常量集合、函数f和两个int常量a,b,d

    (0, <code object f at 0xb7273b18, file "src_file", line 2>, 9, 8, None)

     

    >>> print co.co_consts[1].co_varnames    #可以看到f函数也是一个codeobject,打印f中的局部变量

    ('c',)

     

    >>> print co.co_code    #字节码指令

    dZdZdZedS

     

    >>> print co.co_consts[1].co_firstlineno    #代码块在文件中的起始行号

    2

     

    >>> print co.co_stacksize    #代码栈大小

    2

     

    >>> print co.co_filename    #文件名

    src_file    #模块名、函数名、类名

      codeobject的co_code代表了字节码,这个字节码有什么含义?我们可以使用dis模块进行python的反编译:

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    import dis

    dis.dis(co)

    >>> output

     2        0 LOAD_CONST               0 (0)

              3 LOAD_CONST               1 (<code object f at 0xb7273b18, file "src_file", line 2>)

              6 MAKE_FUNCTION            1

              9 STORE_NAME               0 (f)

     5        12 LOAD_CONST              2 (9)

              15 STORE_NAME              1 (a)

     

     6        18 LOAD_CONST              3 (8)

              21 STORE_NAME              2 (b)

     

     7        24 LOAD_NAME               0 (f)

              27 CALL_FUNCTION           0

              30 POP_TOP            

              31 LOAD_CONST              4 (None)

              34 RETURN_VALUE

      从反编译的结果来看,python字节码其实是模仿的x86的汇编,将代码编译成一条一条的指令交给一个虚拟的cpu去执行。

    • 第一列:行号
    • 第二列:指令在代码块中的偏移量
    • 第三列:指令
    • 第四列:操作数
    • 第五列:操作数说明
    展开全文
  • Android源码编译过程及刷机过程详解

    千次阅读 2020-09-01 13:55:35
    本文将详细介绍Android源码编译过程,以及编译完成后如何进行刷机。

    Android编译环境进行初始化


    我们完成AOSP源码下载之后,就可以准备源码进行编译了。但编译之前,首先要对编译环境进行初始化工作。

    在这个过程中,主要是指定编译的类型和目标设备的型号。

    Android的编译类型主要有eng、userdebug和user三种,而支持的目标设备型号则是不确定的,它们由当前的源码配置情况所决定。为了确定源码支持的所有目标设备型号,Android编译系统在初始化的过程中,需要在特定的目录中加载特定的配置文件。

    清除缓存(如果需要的话)

    如果之前执行过编译工作,或者编译出错了,可以执行清除命令:

    $ make clobber
    

    执行envsetup.sh,配置编译环境

    打开一个终端(bash),cd到源码根目录,并且将build/envsetup.sh加载到该终端中:

    $ source build/envsetup.sh
    或
    $ . ./build/envsetup.sh 
    
    including device/generic/car/vendorsetup.sh
    including device/generic/mini-emulator-arm64/vendorsetup.sh
    including device/generic/mini-emulator-armv7-a-neon/vendorsetup.sh
    including device/generic/mini-emulator-mips/vendorsetup.sh
    including device/generic/mini-emulator-mips64/vendorsetup.sh
    including device/generic/mini-emulator-x86/vendorsetup.sh
    including device/generic/mini-emulator-x86_64/vendorsetup.sh
    including device/generic/uml/vendorsetup.sh
    including device/google/crosshatch/vendorsetup.sh
    including device/google/cuttlefish/vendorsetup.sh
    including device/google/marlin/vendorsetup.sh
    including device/google/muskie/vendorsetup.sh
    including device/google/taimen/vendorsetup.sh
    including device/linaro/hikey/vendorsetup.sh
    including sdk/bash_completion/adb.bash
    

    我们来看命令的输出,文件build/envsetup.sh在加载的过程中又会加载一些其他文件。

    • 在device目录中加载那些名称为vendorsetup.sh的文件。

    • 在sdk/bash_completion目录下的adb.bash文件也会加载到当前终端来。

      它是用来实现adb命令的bash completion功能的。也就是说,加载了该文件之后,我们在运行adb相关的命令的时候,通过按tab键就可以帮助我们自动完成命令的输入。

    执行lunch命令

    执行命令lunch,选择编译的目标:

    $ lunch
    
    You're building on Darwin
    
    Lunch menu... pick a combo:
         1. aosp_arm-eng
         2. aosp_arm64-eng
         3. aosp_mips-eng
         4. aosp_mips64-eng
         5. aosp_x86-eng
         6. aosp_x86_64-eng
         7. aosp_car_arm-userdebug
         8. aosp_car_arm64-userdebug
         9. aosp_car_x86-userdebug
         10. aosp_car_x86_64-userdebug
         11. mini_emulator_arm64-userdebug
         12. m_e_arm-userdebug
         13. m_e_mips-userdebug
         14. m_e_mips64-eng
         15. mini_emulator_x86-userdebug
         16. mini_emulator_x86_64-userdebug
         17. uml-userdebug
         18. aosp_crosshatch-userdebug
         19. aosp_blueline-userdebug
         20. aosp_cf_x86_auto-userdebug
         21. aosp_cf_x86_phone-userdebug
         22. aosp_cf_x86_tablet-userdebug
         23. aosp_cf_x86_tablet_3g-userdebug
         24. aosp_cf_x86_tv-userdebug
         25. aosp_cf_x86_wear-userdebug
         26. aosp_cf_x86_64_auto-userdebug
         27. aosp_cf_x86_64_phone-userdebug
         28. aosp_cf_x86_64_tablet-userdebug
         29. aosp_cf_x86_64_tablet_3g-userdebug
         30. aosp_cf_x86_64_tv-userdebug
         31. aosp_cf_x86_64_wear-userdebug
         32. cf_x86_auto-userdebug
         33. cf_x86_phone-userdebug
         34. cf_x86_tablet-userdebug
         35. cf_x86_tablet_3g-userdebug
         36. cf_x86_tv-userdebug
         37. cf_x86_wear-userdebug
         38. cf_x86_64_phone-userdebug
         39. cf_x86_64_tablet-userdebug
         40. cf_x86_64_tablet_3g-userdebug
         41. cf_x86_64_tv-userdebug
         42. cf_x86_64_wear-userdebug
         43. aosp_marlin-userdebug
         44. aosp_marlin_svelte-userdebug
         45. aosp_sailfish-userdebug
         46. aosp_walleye-userdebug
         47. aosp_walleye_test-userdebug
         48. aosp_taimen-userdebug
         49. hikey-userdebug
         50. hikey64_only-userdebug
         51. hikey960-userdebug
    

    lunch命令输出了一个Lunch菜单,该菜单列出了当前Android源码支持的所有设备型号及其编译类型。

    编译的类型:

    • user: limited access; suited for production(有限的访问权限,一般用于发布版)。
    • eng:具有开发配置,并且有额外的调试工具(注:工程师模式engineer)。
    • userdebug: 这个和user类似,但是可以获取root权限,并且能够调试。

    当我们选定了一个Lunch菜单项序号(1-51)之后,按回车键,就可以完成Android编译环境的初始化过程。

    注:lunch命令也可以直接这么用 $ lunch aosp_arm-eng

    编译环境初始化结果

    Android编译环境初始化完成之后,获得了以下三样东西:

    1. 将vendor和device目录下的vendorsetup.sh文件加载到了当前终端。
    2. 新增了lunch、m、mm和mmm等命令。
    3. 通过执行lunch命令设置好了TARGET_PRODUCT、TARGET_BUILD_VARIANT、TARGET_BUILD_TYPE和TARGET_BUILD_APPS等环境变量。

    AOSP源码编译


    对整个系统进行编译

    使用make命令开始整个系统的编译:

    make -j8
    

    这里的-j参数后面的数字是编译需要的线程数,建议电脑的CPU数量的1~2倍来设置。

    然后就是漫长的等待过程了……

    分模块编译

    我们也可以用m/mm/mmm/make命令编译源代码。

    当然,这要求每一个模块都有一个Android.mk文件。Android.mk实际上是一个Makefile脚本,用来描述模块编译信息。Android编译系统通过整合Android.mk文件完成编译过程。

    m、mm和mmm命令也分别是由定义在build/envsetup.sh文件中的函数m、mm和mmm提供的,而这三个函数又都是通过make命令来对源代码进行编译的。

    m/mm/mmm使用简介

    • m: Makes from the top of the tree.
    • mm: Builds all of the modules in the current directory, but not their dependencies.
    • mmm: Builds all of the modules in the supplied directories, but not their dependencies.
      To limit the modules being built use the syntax: mmm dir/:target1,target2.
    • mma: Builds all of the modules in the current directory, and their dependencies.
    • mmma: Builds all of the modules in the supplied directories, and their dependencies.

    事实上,命令m就是对make命令的简单封装,并且是用来对整个Android源代码进行编译,而命令mm和mmm都是通过make命令来对Android源码中的指定模块进行编译。

    m的实现:

    function m()
    {
        local T=$(gettop)
        if [ "$T" ]; then
            _wrap_build $T/build/soong/soong_ui.bash --make-mode $@
        else
            echo "Couldn't locate the top of the tree.  Try setting TOP."
            return 1
        fi
    }
    

    当在Android源码中定义的各个模块都编译好之后,我们还需要将编译得到的文件打包成相应的镜像文件,例如system.img、boot.img和recorvery.img等,这样我们才可以将这些镜像烧录到目标设备去运行。

    安装系统


    系统编译完成之后,我们可以通过使用模拟器来运行,或者使用真机进行刷机。

    模拟机启动

    $ source build/envsetup.sh
    $ lunch //(选择刚才设置的目标版本,例如如果之前我们选择1,那就是aosp_arm-eng)
    $ emulator //模拟器启动
    

    刷真机

    1. 进入fastboot模式
    $ adb reboot bootloader
    
    1. 把img文件刷进去
    $ fastboot flashall -w  //这个 -w 是为了wipes the /data partition擦除/data分区
    

    **PS:更多精彩内容,请查看 --> 《AOSP 专栏》
    **PS:更多精彩内容,请查看 --> 《AOSP 专栏》
    **PS:更多精彩内容,请查看 --> 《AOSP 专栏》

    展开全文
  • Android编译过程

    千次阅读 2018-08-21 18:36:13
    当前目录下编译执行,相当于在android目录下执行make 本文介绍Android的编译过程及各种mk文件的导入 1.编译 a.编译步骤 清理 sh $ make clobber 初始化环境 sh $ source ./build/envetup.sh # 这个...

    当前目录下编译执行,相当于在android目录下执行make 本文介绍Android的编译过程及各种mk文件的导入

    1.编译

    a.编译步骤

    • 清理
      sh
      $ make clobber
    • 初始化环境
      sh
      $ source ./build/envetup.sh
      # 这个命令是用来将envsetup.sh里的所有用到的命令加载到环境变量里去
    • 选择编译目标
      sh
      $ lunch aosp_arm-eng
    • 编译
      sh
      $ make -j16

      参数N表示并行编译的任务数,一般N为cpu线程数的1-2倍.例如,在一台双核 E5520 计算机(2 个 CPU,每个 CPU 4 个内核,每个内核 2 个线程)上,要实现最快的编译速度,可以使用介于 make -j16 到 make -j32 之间的命令

    b.编译结果及目录

    • out/ :所有的编译产物都将位于out目录下,该目录下主要有以下几个子目录
    • -out/host/ :该目录下包含了针对主机的 Android 开发工具的产物。即 SDK 中的各种工具,例如:emulator,adb,aapt 等
    • out/target/common/ :该目录下包含了针对设备的共通的编译产物,主要是 Java 应用代码和 Java 库。
    • out/target/product// :包含了针对特定设备的编译结果以及平台相关的 C/C++ 库和二进制文件。其中,是具体目标设备的名称。

    c.编译生成的主要镜像文件

    ramdisk.img

    • 是一个最基础的小型文件系统,它包括了初始化系统所需要的全部核心文件;
    • 在启动时将被 Linux 内核挂载为只读分区,它包含了 /init 文件和一些配置文件。它用来挂载其他系统镜像并启动 init 进程

    boot.img

    • 由boot header、kernel和ramdisk三部分打包在一起组成
    • 启动时,由bootloader解析后引导kernel启动

    system.img

    • 被挂载到/system目录下
    • 包含了 Android OS 的系统文件,库,可执行文件以及预置的应用程序

      userdata.img

    • 被挂载到/data目录下

    • 包含了应用程序相关的数据以及和用户相关的数据
    • 可以预制一些可删除的应用软件

    2.编译过程详解

    a.source 过程

    source命令:在当前bash环境下 读取并执行 FileName中的命令;$ source ./build/envsetup.sh 读取envsetup.sh 中的函数,并执行脚本 。

    • 加载的函数有
    函数 说明
    m 当前目录下编译执行,相当于在android目录下执行make
    mm 执行当前目录下最近的make文件
    mmm 在android目录下,执行某个文件夹下的make文件
    mma 编译当前目录下所有的模块和他们的依赖
    make update-api 更新 API。在 framework API 改动之后,需要首先执行该命令来更新 API
    printconfig 打印配置
    lunch 配置lunch
    croot 回到根目录
    cgrep 在所有 C/C++ 文件上执行 grep
    jgrep 在所有 Java 文件上执行 grep
    resgrep 在所有 res/*.xml 文件上执行 grep

    - 执行脚本:1.执行add_lunch_combo xxxxx 2.检查shell是否为bash,3.查找 vendorsetup.sh,并 include ;4.输出所有的include文件 5,执行addcompletions() 检查bash版本;

    b. lunch过程

    lunch <product_name>-<build_variant>,选择平台编译选项

    c. Make 过程

    makefile的相关语法请参考Makefile语法一文或其他书籍。

    入口文件是源码树根目录下名称为Makefile的文件,当在源代码根目录上调用 make 命令时,make 命令首先将读取该文件。Makefile 文件的内容只有一行:include build/core/main.mk。作用仅为包含 build/core/main.mk文件。在 main.mk 文件中又会去包含其他的文件,其他文件中又会包含更多的文件,这样就引入了整个 Build 系统。

    Makefile文件

    比较重要的make文件介绍:

    • devices/xxxxx/BoardConfig.mkAndroidBoard.mk
      • BoardConfig.mk设备硬件配置及目标架构配置文件.
      • AndroidBoard.mk设备属性和键值映射配置文件.
      • TARGET_KERNEL_CONFIG/KERNEL_DEFCONFIG:定义默认kernelconfig文件;
    展开全文
  • 我们的代码会经过这4个环节,从而形成最终文件,c语言作为编译语言,用来向计算机发出指令。让程序员能够准确地定义计算机所需要使用的数据,并精确地定义在不同情况下所应当采取的行动。 预处理, 展开头文件/宏...
  • Javac编译过程

    千次阅读 2016-03-04 17:50:02
    Javac编译过程大致分为4个过程,分别是: 词法分析 语法分析 语义分析 代码生成 词法分析   词法分析是将源代码的字符流转变为标记(Token)集合,单个字符是程序编写过程的最小元素,而标记则是编译过程的...
  • 编译原理_编译过程概述

    千次阅读 2019-04-11 01:26:12
    文章目录概述词法分析语法分析语义分析中间代码生成代码优化目标代码生成符号表管理(表格管理)出错处理 概述 编译程序即是将高级语言书写的源程序翻译成与之等价的目标...以中间代码为分水岭的原因是把编译过程分解...
  • C语言编译过程

    千次阅读 2018-04-01 12:14:06
    C语言编译过程为:预处理--&gt;编译--&gt;汇编--&gt;链接1、预处理(Pre-processing) 对源程序中的伪指令(以#开头的指令)和特殊符号进行处理。伪指令包括:宏定义指令、条件编译指令、头文件包含...
  • javac编译过程

    千次阅读 2018-08-15 15:39:15
     JVM规范定义了Class文件结构格式,但没有定义如何从java程序文件转化为Class文件,所以不同... 从javac编译器源码来看,其编译过程可以分为3个子过程:  1、解析与填充符号表过程:解析主要包括词法分析...
  • C++的编译过程及原理

    万次阅读 多人点赞 2018-09-27 20:25:03
    目录 文章目录目录C和C++的编译 本次内容是关于编译过程的,内容如下: C和C++的编译 C和C++的编译
  • java编译过程

    千次阅读 2018-06-10 21:29:06
    摘自:深入理解JVM虚拟机A、解析与...而标记则是编译过程的最小元素,关键字、变量名、字面量、运算符都可以成为标记语法分析:根据Token序列构造抽象语法树的过程2、填充符号表完成语法分析和词法分析后,就是填...
  • 编译过程概述: 编译程序完成从源程序到目标程序的翻译工作,是一个复杂的整体的过程。从概念上来讲,一个编译程序的整个工作过程是划分成阶段进行的,每个阶段将源程序的一种表示形式转换成另一种表示形式,各个...
  • emq 源码编译过程

    千次阅读 2018-06-26 18:39:44
    本人在编译是在ubuntu16环境下编译的,然后看到官网有windows下的编译过程,可以自己去看看->WINDOWS编译 然后再编译emq之前,那肯定要先配置下编译环境。 make emq采用Makefile的方式编译,没有的话,直接 ...
  • GCC编译过程,了解编译原理

    千次阅读 2018-12-09 20:00:16
    1、GCC编译过程分解 以HelloWorld程序为例 2、预编译 规则: 命令:gcc -E XXX.c -o XXX.i   3、编译 词法分析、语法分析、语义分析及优化 ---------------&gt;&gt; 汇编代码文件 命令:...
  • DCMTK编译过程详解

    千次阅读 2018-01-29 15:52:03
    医学图像开发免不了要使用DCMTK包做DICOM图像的解析和相关操作,在使用DCMTK工具包时,首先需要CMAKE编译源码,生成我们开发需要的文件,笔者根据自身编译的实战经验,详细讲述一下DCMTK的编译过程。 准备工作: ...
  • C语言编译过程详解

    千次阅读 2018-12-07 00:01:08
      前言 C语言程序从源代码到二进制行程序都经历了...本文以Linux下C语言的编译过程为例,讲解C语言程序的编译过程。 编写hello world C程序: // hello.c #include &lt;stdio.h&gt; int main(){ p...
  • C/C++程序编译过程详解

    万次阅读 多人点赞 2017-11-13 14:51:06
    C/C++程序编译过程详解 C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接。编译就是把文本形式源代码翻译为机器语言形式的目标文件...
  • gcc程序的编译过程和链接原理

    万次阅读 多人点赞 2017-10-24 17:02:07
    一、C/C++文件的编译过程:先来看一下gcc的使用方法和常用选项 提示:gcc --help Ⅰ、使用方法:gcc [选项] 文件名Ⅱ、常用选项: 选项 含义 -v 查看gcc编译器的版本,显示gcc执行时的详细过程 -o ...
  • java的编译过程

    千次阅读 2018-08-05 17:07:59
    一、java类的编译过程 这是由.java源码文件转为 .class二进制字节码文件的过程。 编译过程主要有三步:词法分析和输入到符号表;注解处理;语义分析和生成字节码 详细过程: 源代码文件*.java -&gt; 词法...
  • 一:一般的C++应用程序的编译过程。  一般说来,C++应用程序的编译过程分为三个阶段。模板也是一样的。 在cpp文件中展开include文件。 将每个cpp文件编译为一个对应的obj文件。 连接obj文件成为一个exe文件...
  • arduino编译过程

    千次阅读 2015-11-23 11:05:42
    arduino多个文件 把所有的.ino文件都给串联起来把所有的.c , .cpp 文件都给单独的编译对于那些.h文件在...arduino编译过程 其实是把所哟的.ino文件串联起来放到一个叫main.cpp文件中,然后再让avr-gcc去
  • java编译过程与c/c++编译过程不同

    千次阅读 2009-07-18 21:53:00
    1、java编译过程与c/c++编译过程不同java编译程序将java源程序编译成jvm可执行代码--java字节码.c/c++编译过程:当C编译器编译生成一个对象的代码时,该代码是为在某一特定硬件平台运行而生成的。因此在编译过程中,...
  • 接着之前的一篇简要的ijkplayer的编译过程,这一遍主要是详细描述ijkplayer编译的详细过程,跟着编译的脚本详细分析在ijkplayer从开源库的clone到完整地编译android共享库的过程。下载最新版的源码git clone ...
  • Github下载go语言编译项目编译过程

    千次阅读 2018-03-13 09:17:49
    Github下载go语言编译项目编译过程1. Go语言简介Go语言专门针对多处理器系统应用程序的编程进行了优化,使用Go编译的程序可以媲美C或C++代码的速度,而且更加安全、支持并行进程。Google对Go寄予厚望。其设计是...
  • pcshare远控软件编译过程

    千次阅读 2018-10-12 10:57:36
    参考链接:PCSHARE最终版本源代码编译教程,PcShare远程管理编译过程!
  • C语言再学习 -- GCC编译过程

    万次阅读 2016-11-25 21:04:42
    参看:GCC编译过程分解 一、GCC简介: gcc的原名叫做GNU C语言 编译器(GNU C Compile),只能编译C语言程序,后来很快就做了扩展,支持了更多的编程语言,比如C+ Object-c ...,改名为GNC 编译器 套件(GNU ...
  • gcc -c -o编译过程

    千次阅读 2019-07-19 21:36:30
    在使用GCC编译程序时,编译过程可以被细分为四个阶段,包括预处理、编译、汇编、链接。 分步处理 一、预处理 在预处理阶段,编译器主要作加载头文件、宏替换、条件编译的作用。一般处理带“#”的语句。 我们可以...
  • C++程序编译过程

    千次阅读 2013-10-13 10:56:18
    首先是编译过程整体简介 编译过程主要分为4个过程  1) 编译预处理 预编译程序完成的工作,可以说成是对源程序的“替换”工作。经过这个过程,生成一个没有宏定义、没有条件编译指令、没有特殊符号的输出文件。 ...
  • openwrt单个ipk编译过程

    千次阅读 2017-01-23 22:35:56
    前一篇博客中,我们已经知道整个openwrt的编译顺序,本文我们来探讨与开发者息息相关的单个ipk的编译过程.在开发者进行二次开发的时候,我们既可以单个编译ipk也可以完整编译整个镜像文件.在完整编译的时候,我们选中的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 118,833
精华内容 47,533
关键字:

编译过程