添加编译宏_软件开发——编译链接

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

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

编译流程分析

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

eaeed1eeb9619063ffdd0e48d5a7a006.png

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

223a81a9fa2ddbfbff69e8a88b08156b.png

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

  • 预处理(Prepressing)
  • 编译(Compilation)
  • 汇编(Assembly)
  • 链接(Linking)
e9fd27b03a04e0070e8e1d635ad7e42a.png

预编译

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

24b9de72ba08a98929f72918c846483f.png

还可以下面的表达

10d9bbe92fcc7a6852bf13da27d8bf21.png

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

  • 将所有的#define删除,并展开所有的宏定义
  • 处理所有条件预编译指令,比如#if,#ifdef,#elif,#else,#endif
  • 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。
  • 删除所有的注释//和/**/
  • 添加行号和文件名标识,比如#2 “hello.c” 2。
  • 保留所有的#pragma编译器指令

截图个大家看看效果

6405baaac89d38b261f710ce3aaaf3ec.png

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

编译(compliation)

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

dd5244b1a11a5b0667a3f01cce659c88.png
142f35277e3afd9072066b33a416579b.png

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

汇编(assembly)

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

cd24425cacc51461bd81e82432bcca1c.png

或者

027b7e26d54c51fd49d44fbb49c232dd.png

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

6ed1bb9ae16933df276b7fc961d17655.png

链接(linking)

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

7b7433454d9178db209b23f164ebc075.png

链接相应的库

6a5afd570ccc32f0a35beff811d50d07.png

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

00d3547e8e7c84d5bcc4f82ce0f951ed.png

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

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

f96fca1e907562e50cabb05cbe058a3e.png

iOS的编译器

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

  • 1.LLVM核心库:
  • LLVM提供一个独立的链接代码优化器为许多流行CPU(以及一些不太常见的CPU)的代码生成支持。这些库是围绕一个指定良好的代码表示构建的,称为LLVM中间表示(“LLVM IR”)。LLVM还可以充当JIT编译器 - 它支持x86 / x86_64和PPC / PPC64程序集生成,并具有针对编译速度的快速代码优化。。
  • 2.LLVM IR 生成器Clang: Clang是一个“LLVM原生”C / C ++ / Objective-C编译器,旨在提供惊人的快速编译(例如,在调试配置中编译Objective-C代码时比GCC快3倍),非常有用的错误和警告消息以及提供构建优秀源代码工具的平台。
  • 3.LLDB项目:
  • LLDB项目以LLVM和Clang提供的库为基础,提供了一个出色的本机调试器。它使用Clang AST和表达式解析器,LLVM JIT,LLVM反汇编程序等,以便提供“正常工作”的体验。在加载符号时,它也比GDB快速且内存效率更高。
  • 4.libc和libc++:
  • libc 和libc++ ABI项目提供了C ++标准库的标准符合性和高性能实现,包括对C ++ 11的完全支持。
  • 5.lld项目:
  • lld项目旨在成为clang / llvm的内置链接器。目前,clang必须调用系统链接器来生成可执行文件。

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

833a7595191535ec984f668b7bf491d7.png

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

  • 语法分析
  • 语义分析
  • 生成中间代码(intermediate representation )

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

c9db82b9b6d625e1b9e285d3b51e9298.png

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

iOS程序-详细编译过程

  • 1.写入辅助文件:将项目的文件结构对应表、将要执行的脚本、项目依赖库的文件结构对应表写成文件,方便后面使用;并且创建一个 .app 包,后面编译后的文件都会被放入包中;
  • 2.运行预设脚本:Cocoapods 会预设一些脚本,当然你也可以自己预设一些脚本来运行。这些脚本都在 Build Phases中可以看到;
  • 3.编译文件:针对每一个文件进行编译,生成可执行文件 Mach-O,这过程 LLVM 的完整流程,前端、优化器、后端;
  • 4.链接文件:将项目中的多个可执行文件合并成一个文件;
  • 5.拷贝资源文件:将项目中的资源文件拷贝到目标包;
  • 6.编译 storyboard 文件:storyboard 文件也是会被编译的;
  • 7.链接 storyboard 文件:将编译后的 storyboard 文件链接成一个文件;
  • 8.编译 Asset 文件:我们的图片如果使用 Assets.xcassets 来管理图片,那么这些图片将会被编译成机器码,除了 icon 和 launchImage;
  • 9.运行 Cocoapods 脚本:将在编译项目之前已经编译好的依赖库和相关资源拷贝到包中。
  • 10.生成 .app 包
  • 11.将 Swift 标准库拷贝到包中
  • 12.对包进行签名
  • 13.完成打包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/559506.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell打开wifi命令_远程执行命令的填坑记录

前言本文主要记录 bash 四种模式的细节,以便于遇到问题时查阅。远程执行出错了最近使用 ansible 比较多,在某次使用 shell 模块远程执行命令的时候老是报 ‘command not found’。但是手动登录到远端机器执行命令是成功的,于是开始思考里面的…

nodejs express use 传值_再也不怕面试官问你express和koa的区别了

前言用了那么多年的express.js,终于有时间来深入学习express,然后顺便再和koa2的实现方式对比一下。老实说,还没看express.js源码之前,一直觉得express.js还是很不错的,无论从api设计,还是使用上都是可以的…

没有工作经验找it_校招和社招有什么区别?没有工作经验,如何找工作?

我们的招聘一般分为社招和校招。社招就是社会上招聘,绝大多数都要有相关的工作经验。而校招则是针对在校大学生的,所以应届毕业生的身份很重要,失去了这个身份,就要进入社招的渠道,面临的压力和要求都要高得多。那么&a…

python输入个人所得税计算_个税起征点上调至5000,用Python算一算少交多少税

原标题:个税起征点上调至5000,用Python算一算少交多少税今天出了一个重磅消息,个税起征点从3500上调到5000啦! 广大IT农民工的生活压力又减轻了一些,有没有 晚上加一个鸡腿,要不要~ 开心归开心,…

hive 行转列和列转行的方法_面试常考!SQL行转列和列转行

关注上方“数据挖掘工程师”,选择星标,关键时间,第一时间送达!行转列,列转行是我们在开发过程中经常碰到的问题。行转列一般通过CASE WHEN 语句来实现,也可以通过 SQL SERVER 的运算符PIVOT来实现。用传统的…

.net core 装了没生效_王者荣耀:辅助装出现惊天bug?辅助光环对自己无效?

大家好,我是老刘备。今天说的这个bug我已经发现许久,从新版本以来就一直在出现,起初我以为是辅助装的光环改动了,但是最近和我的小伙伴开黑之后也遇到这个bug,才发现不是如此。本期我就来带大家一起看看。辅助光环技我…

python sns绘制回归线_Python数分实战:员工流失情况预测

在很久之前,我有写一个Excel数据分析的实战项目,不晓得大家还记不记得,感兴趣的童鞋可以回看:A九姑娘:Excel数分实战:员工流失率分析​zhuanlan.zhihu.com本次的项目数据依旧是这个,但是我们这次…

go var 一个整数_Go语言学习基础-值、变量、常量

Hello world第一个程序是打印经典的“hello world”信息。保存为hello-world.go文件,在命令行中使用go run命令运行程序。若要构建为二进制文件,则使用go build来实现,然后直接执行二进制文件。结果:$ go run hello-world.gohello…

怎么取消自动格式化_iPhone自动扣费怎么取消?App Store、微信、支付宝关闭自动扣费教程...

经常有网友反馈,自己的手机每月会被不知不觉的被扣钱,但又不知道如何关闭,烦恼不已。其实,现在很多视频、音乐、购物等APP都有会员充值功能,其中不少还包含“自动续费”功能,一旦开启会员,今后就…

c# selenium chrome 文件下载_Selenium 框架原理以及环境安装

Selenium 框架原理图片来自转载 蓝色的图Selenium Language Binding就是我们平时使用的编码语言,包括java、python、C#等。可以看到这些语言并没有直接与Browser Drivers进行通信,而是通过了JSON WireProtocol,这就是webdriver协议 &#xff…

怎么打包图片_怎么将许多张照片打包发到邮箱?

怎么将许多张照片打包发到邮箱?所谓的打包,就是需要你把大量照片文件变成一个压缩文件,类似于放到一个文件夹内,也可以理解为把多张纸质照片装订成一个相册,而在装订过程中需要相应工具才能完成。使用压缩包发送文件&a…

dram sram利用 利用_使用量子力学技术的新型超低功耗存储器或将取代DRAM和Flash...

雷锋网按:业界普遍认为未来从数据中将能挖掘出最大的价值,但要挖掘数据的价值除了需要很强的计算能力之外,数据的存储也非常关键。目前,新型存储器也是领先的企业非常关注的一个方向,兰开斯特大学(Lancaster Universit…

mac地址转换_mac电脑格式转化工具

软件下载【软件名称】:Permute【系统支持】:MAC电脑【位数支持】:32位/64位软件下载地址:链接:https://pan.baidu.com/s/1OAEpnvmkQgqd9MMq3Rucow提取码:tgt7注:阿狸提供用户下载的所有内容均来…

电脑怎么打出冒号符号_Mac小技巧:教你如何在Mac电脑打出command?、option?等特殊符号...

很多Mac新用户不知道该如何打出command⌘、option⌥等特殊符号,而网上好多关于打出Mac特殊符号的教程已经过期,或者繁琐看不懂。今天为大家分享一份简单,一看就懂的Mac电脑怎么打出command⌘、option⌥等特殊符号教程。1.我们打开系统偏好设置…

arraylist下标从几开始_漫画:为什么计算机从 0 开始计数,而不是从 1 开始?

作者 | 漫话编程来源 | 漫话编程当我们想要写一个循环体&#xff0c;期望执行10次的时候&#xff0c;我们会使用以下方式&#xff1a;for (int i0; i<10; i){}可以看到&#xff0c;为了保证循环10次&#xff0c;我们定义了一个整数变量从0开始。还有&#xff0c;当我们定义数…

python 爬虫代码_Python 你见过三行代码的爬虫吗

Python 使用Lassie库&#xff0c;仅编写三行代码就能爬取静态页面上的图片和视频。Python实战教程每次讲爬虫的时候都会从“发送请求” 开始讲&#xff0c;讲到解析页面的时候可能大部分读者都会卡住&#xff0c;因为这部分确实需要一点XPATH或者CSS选择器的前置知识。那么有没…

接口传值后不起作用_聊一聊 API 接口测试

知其然亦知其所以然&#xff0c;接口测试没有那么复杂&#xff0c;但也没有那么简单。本文作者&#xff1a;张敏&#xff0c;软件测试工程师&#xff0c;就职于一家容器平台解决方案公司&#xff0c;负责 DevOps 产品的测试。什么是 APIAPI(Application Programming Interface)…

服务器无法在发送 http 标头之后设置内容类型。_python socket编程预知内容

socket&#xff1a;运用IP地址协议端口 标识一个进程我们知道两个进程如果需要进行通讯最基本的一个前提能能够唯一的标示一个进程&#xff0c; 在本地进程通讯中我们可以使用PID来唯一标示一个进程&#xff0c;但PID只在本地唯一&#xff0c;网络中的两个进程PID冲突几率很大 …

自定义键盘组件_一文读懂!iOS系统组件的设计规范全解

一说到组件&#xff0c;大部分初级设计师和中级设计师的脑海里只会蹦出弹窗、Toast及操作列表等具体的概念&#xff0c;没有一套属于自己的组件分类体系&#xff0c;这样对于视觉设计、交互设计或产品设计的系统学习来说都是不利的。iOS14概念设计iOS官方设计指南在介绍组件时是…

anaconda安装python视频_怎么安装anaconda?

安装 Anaconda步骤&#xff1a; 1、双击下载好的 Anaconda2-5.2.0-Windows-x86_64.exe文件&#xff0c;出现如下界面&#xff0c;点击 Next 即可。2、点击 I Agree &#xff08;我同意&#xff09;3、Install for: Just me还是All Users&#xff0c;假如你的电脑有好几个 Users…