作者:Cooci

https://juejin.im/post/5cd580f4e51d453ce606dbac

对于平常的应用程序开发,我们很少需要关注编译链接过程。我们平常Xcode开发就是集成的的开发环境(IDE),这样的IDE一般都将编译链接的过程一步完成,通常将这种编译链接合并在一起的过程称为构建,即使使用命令行来编译一个源代码文件,简单的一句gcc hello.c命令就包含了非常复杂的过程!

正是因为集成开发环境的强大,很多系统软件的运行机制与机理被掩盖,其程序的很多莫名其妙的错误让我们无所适从,面对程序运行时种种性能瓶颈我们束手无策。我们看到的是这些问题的现象,但是却很难看清本质,所有这些问题的本质就是软件运行背后的机理及支撑软件运行的各种平台和工具,如果能深入了解这些机制,那么解决这些问题就能够游刃有余。

编译流程分析

现在我们通过一个C语言的经典例子,来具体了解一下这些机制:

#include int main(){    printf("Hello World");    return 0;}

在linux下只需要一个简单的命令(假设源代码文件名为hello.c):

$ gcc hello.c$ ./a.outHello World

其实上述过程可以分解为四步:

  • 预处理(Prepressing)

  • 编译(Compilation)

  • 汇编(Assembly)

  • 链接(Linking)

预编译

首先是源代码文件hello.c和相关的头文件(如stdio.h等)被预编译器cpp预编译成一个.i文件。第一步预编译的过程相当于如下命令(-E 表示只进行预编译):

$ gcc –E hello.c –o hello.i

还可以下面的表达

$ cpp hello.c > hello.i

预编译过程主要处理源代码文件中以”#”开头的预编译指令。比如#include、#define等,主要处理规则如下:

  • 将所有的#define删除,并展开所有的宏定义

  • 处理所有条件预编译指令,比如#if,#ifdef,#elif,#else,#endif

  • 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。

  • 删除所有的注释///**/

  • 添加行号和文件名标识,比如#2 “hello.c” 2。

  • 保留所有的#pragma编译器指令

截图个大家看看效果

经过预编译后的文件(.i文件)不包含任何宏定义,因为所有的宏已经被展开,并且包含的文件也已经插入到.i文件中,所以当我们无法判断宏定义是否正确或头文件包含是否正确时,可以查看预编译后的文件来确定问题。

编译(compliation)

编译过程就是把预处理完的文件进行一系列的:词法分析语法分析语义分析优化后生产相应的汇编代码文件,此过程是整个程序构建的核心部分,也是最复杂的部分之一。其编译过程相当于如下命令:

$ gcc –S hello.i –o hello.s

通过上图我们不难得出,通过命令得到汇编输出文件hello.s.

汇编(assembly)

汇编器是将汇编代码转变成机器可以执行的指令,每一个汇编语句几乎对应一条机器令。所以汇编器的汇编过程相对于编译器来讲比较简单,它没复杂的语法,也没有语义,也不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译就可以了。其汇编过程相当于如下命令:

as hello.s –o hello.o

或者

gcc –c hello.s –o hello.o

或者使用gcc命令从C源代码文件开始,经过预编译、编译和汇编直接输出目标文件:

gcc –c hello.c –o hello.o

链接(linking)

链接通常是一个让人比较费解的过程,为什么汇编器不直接输出可执行文件而是输出一个目标文件呢?为什么要链接?下面让我们来看看怎么样调用ld才可以产生一个能够正常运行的Hello World程序:

注意默认情况没有gcc / 记得 :$ brew install gcc

链接相应的库

下面在贴出我们的写出的源代码是如何变成目标代码的流程图:

主要通过我们的编译器做了以下任务:扫描、语法分析、语义分析、源代码优化、代码生成和目标代码优化

到这我们就可以得到以下的文件,不知道你是否有和我一起操作,玩得感觉还是不错,继续往下面看

iOS的编译器

iOS现在为了达到更牛逼的速度和优化效果,采用了LLVM

LLVM采用三相设计,前端Clang负责解析,验证和诊断输入代码中的错误,然后将解析的代码转换为LLVM IR,后端LLVM编译把IR通过一系列改进代码的分析和优化过程提供,然后被发送到代码生成器以生成本机机器代码。

编译器前端的任务是进行:

  • 语法分析

  • 语义分析

  • 生成中间代码(intermediate representation )

在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。

以上图解内容所做的是事情和gcc编译一模模一样样!

iOS程序-详细编译过程

  • 1.写入辅助文件:将项目的文件结构对应表、将要执行的脚本、项目依赖库的文件结构对应表写成文件,方便后面使用;并且创建一个 .app 包,后面编译后的文件都会被放入包中;

  • 2.运行预设脚本:Cocoapods 会预设一些脚本,当然你也可以自己预设一些脚本来运行。这些脚本都在 Build Phases中可以看到;

  • 3.编译文件:针对每一个文件进行编译,生成可执行文件 Mach-O,这过程 LLVM 的完整流程,前端、优化器、后端;

  • 4.链接文件:将项目中的多个可执行文件合并成一个文件;

  • 5.拷贝资源文件:将项目中的资源文件拷贝到目标包;

  • 6.编译 storyboard 文件:storyboard 文件也是会被编译的;

  • 7.链接 storyboard 文件:将编译后的 storyboard 文件链接成一个文件;

  • 8.编译 Asset 文件:我们的图片如果使用 Assets.xcassets 来管理图片,那么这些图片将会被编译成机器码,除了 iconlaunchImage

  • 9.运行 Cocoapods 脚本:将在编译项目之前已经编译好的依赖库和相关资源拷贝到包中。

  • 10.生成 .app

  • 11.将 Swift 标准库拷贝到包中

  • 12.对包进行签名

  • 13.完成打包

编译过程的确是个比较复杂的过程,还有链接!并不是说难就不需要掌握,我个人建议每一个进阶路上iOS开发人员,都是要了解一下的。不需要你多么牛逼,但是你能在平时的交流讨论,面试中能点出一个两个相应的点,我相信绝对是逼格满满!

iOSSir公众号技术交流微信群!

需要进群可以添加公众号助理“kele22558!”

客官!在看一下呗~

vc通过编译指令传参_iOS开发你不知道的事编译amp;链接相关推荐

  1. 编译丨迅为iTOP4412开发板Makefile编译

    在前面入门视频第十期 "搭建编译环境 uboot_linux_Android" 中,只介绍了输入 Make 命令就可以编译出内核,并没有介绍它是如何运行的.在向内核中添加驱动的时候 ...

  2. JSP基本语法、3个编译指令、7个动作指令、9个内置对象

    一.jsp概述 JSP是java server page的缩写,其本质是一个简化的servlet,是一种动态网页技术标准.jsp页面是在HTML页面中嵌入java程序段,使用jsp开发的应用程序可以跨 ...

  3. axios 上传文件 封装_axios封装和传参

    axios封装和传参 1.开发环境 vue+typescript 2.电脑系统 windows10专业版 3.在开发的过程中,我们会经常使用到 axios进行数据的交互,下面我来说一下,axios封装 ...

  4. Delphi编译指令说明

    Delphi快速高小的编译器主要来自Object PASCAL的严谨,使用Delphi随时都在与编译器交流,大部分情况下不需要干涉编译器的运行,但是有时也需要对编译器进行必要的设置. ******** ...

  5. Flutter开发之路由跳转与传参(七)

    参考练习:https://book.flutterchina.club/chapter2/flutter_router.html 路由(Route)在移动开发中通常指页面(Page),这跟web开发中 ...

  6. 微信小程序开发:学习笔记[8]——页面跳转及传参

    微信小程序开发:学习笔记[8]--页面跳转及传参 页面跳转 一个小程序拥有多个页面,我们可以通过wx.navigateTo推入一个新的页面.在首页使用2次wx.navigateTo后,页面层级会有三层 ...

  7. 【php7扩展开发四】函数的参数 ,引用传参 ,返回值

    函数参数解析 之前我们定义的函数没有接收任何参数,那么扩展定义的内部函数如何读取参数呢?用户自定义函数在编译时会为每个参数创建一个zend_arg_info结构,这个结构用来记录参数的名称.是否引用传 ...

  8. Python测试开发django5.templates模板变量传参

    上一篇,我们学习了Python测试开发django4.templates模板配置 templates模板中html文件是一个静态页面,写四的,如果有时我们想动态的传入一些不同的参数,想实现在一个固定的 ...

  9. Linux应用开发3 字符串处理,字符串与其他数字类型的转换,向应用程序传参

    标准C库提供的对字符串的处理函数,分为字符串的输入.输出.合并.修改.比较.转换.复制.搜索等几类(ps 越学越像java了) 字符串输入/输出 字符串输出(字符串专用) 常用的字符串输出函数有 pu ...

  10. vue2项目复习01-关闭elint检校,src文件别名,路由传参的对象写法,代理解决跨域问题,nprogress,vuex状态管理库,store的模块式开发,节流与防抖,编程式导航+事件委托路由跳转

    1.关闭elint语法校验 创建vue.config.js //关闭elint语法校验 {lintOnSave:false; } 2.src文件夹配置别名 jsconfig.json配置别名 @代表s ...

最新文章

  1. 在CentOS 6.8 x86_64上安装ATS 6.2.1实录
  2. 翻译连载 | 第 9 章:递归(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇...
  3. 将枚举值转换为DropDownList等的选项值
  4. 【PAT乙级】 1018 锤子剪刀布 (20 分)
  5. winrar皮肤的更换
  6. ES6基础之——对象表达式
  7. 5799元!OPPO Find X5 Pro天玑版即将开卖:性能比肩骁龙8
  8. 接口测试--apipost中cookie管理器的使用
  9. SAP License:分摊、分配、定期重过账
  10. VC下关于debug和release的不同的讨论(收藏-转载)
  11. 如何将秘钥分发到多台机器
  12. java 一年 周数_Java时间:获取特定年份的最大周数
  13. SVD 详解 与 spark实战
  14. vscode设置中文流程
  15. 安卓吃鸡玩家专属:教你电脑玩刺激战场匹配手机最简单的方式
  16. OBLOG Accesss 转SQL Server 常见问题及解决方法
  17. HDU 2246 考研路茫茫——考试大纲
  18. android 屏幕滚动字幕,LED灯牌显示屏滚动字幕
  19. android 数据图标的刷新通知流程
  20. Delphi写游戏外挂

热门文章

  1. git 删除已经 add 的文件
  2. Win8 开发者训练营第一天的过程,感受和收获
  3. mysql主从同步图
  4. 1.阿里云短信验证操作步骤
  5. Package.json 属性说明
  6. 获取选择的当前天、周、月、年的时间段
  7. 个人项目需求与分析——点菜系统App
  8. ajax 调用asp.net后台方法
  9. C#条件编译,发布多平台和多种选择性的项目
  10. String.resize()