Xcode Run之后发生的事

本文详细介绍了从点击Run开始,App构建过程中的各个阶段,包括编译、汇编、链接、代码签名及启动执行等关键步骤,并深入探讨了编译器的工作原理及其内部组件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文:点击 Run 之后发生了什么?

简单来说,点击 Run 之后 App 进行编译、汇编、链接、代码签名以及启动执行等操作
这里写图片描述

一 编译

编译主要依靠编译器来完成一系列的操作

主要操作有

  • 预处理
  • 词法分析
  • 语法分析
  • 语义分析
  • 生成中间代码
  • 生成目标代码
  • 优化目标代码

OS X 现在使用的编译器是 LLVM (Low Level Virtual Machine),在最初使用的是 GCC作为官方的编译器,但是由于下面的众多限制,apple 使用了自己的一套编译器

  • GCC 原名为GNU C语言编译器,它原本只能处理 C语言,后来扩展了Objective-C、Java等语言,但是对于Objective-C的处理还是存在众多不便
  • GCC 效率低下、性能不强
  • 苹果开发自己的编译器,有利于开展自己的工具链,比如后期做 Swift、lldb 等
llvm 的基本架构

这里写图片描述

1 编译器
  • 编译器前端(clang)
    • 负责产生机器无关的中间代码
  • 编译器后端
    • 负责对中间代码进行优化并转化为目标机器代码

中间代码(IR:intermediate representation)也称为中间表示

  • 通过中间代码为不同的语言针对诸多架构生成代码
    这里写图片描述
2 预处理
  • 处理源文件中以 #开头的预编译命令,比如#include等
3 词法分析

将输入分解为一个个独立的词法符号,也叫单词符号(token)

  • 注释、宏、空格、换行等都不是单词

例子:

// 1 find a zero
float  matchZero(char *s) {

}
//2 返回下列单词流
//大概了解即可,觉得背这些词法符号定义对目前 iOS 开发用处不大
FLOATID(MATCHZERO)、LPAREN、CHARID(S) 、RPAREN  
4 语法分析
  • 将符号化的字符串,转化抽象为能被计算机存储的树形结构(即抽象语法树(AST))
  • 验证语法的正确性
    • 例如:忘记带分号
  • 只能完成语法层面的分析,无法判别整个语句的真正意义
    • 比如类型不匹配就无法检查
5 语义分析
  • 类型检查、以及符号表管理
6 生成中间代码
  • 编译器前端
    • 负责产生机器无关的中间代码
7 目标代码的生成与优化

编译器后端包括

  • 代码生成器
    • 代码生成器将中间代码转换为目标代码
  • 代码优化器
    • 代码优化器主要是进行一些优化,比如删除多余指令,选择合适寻址方式等

二 汇编

  • 目标代码经过汇编器处理,变成机器上可以执行的指令。生成对应的.o文件

三 链接

  • 链接器(这里指的是静态链接器)将多个目标文件合并为一个可执行文件
  • 在 OS X 和 iOS中的可执行文件是 Mach-O

链接又分为静态链接和动态链接

  • 静态链接
    • 在编译链接期间,把目标文件和静态库一起链接形成可执行文件
    • 静态库如果多个程序都用到了一个库,那么每个程序都要将其链接到可执行文件中,非常冗余
    • 不方便升级,必须重新编译

这里写图片描述

  • 动态链接
    • 在运行时,把目标文件和动态库一起链接形成可执行文件
    • 多个程序可以共享同一段代码,不需要在磁盘上存多份拷贝
    • 增加启动时间,影响性能
      • 因为动态链接发生在启动或运行时
    • 方便升级

整个过程如下图

这里写图片描述

四 代码签名

  • 应用构建(build)完成之后会自动调用命令行工具codesign 进行签名,形成一个可以在系统上跑起来的可执行程序
  • 程序一旦签名,就没有办法更改其中的任何东西,包括资源文件,可执行文件等,iOS系统会检查这个签名
  • 我们每次build之后,都会发现工程目录下多了一个.app文件
    • .app目录中,包含一个叫_CodeSignature的子目录 ,它是一个 plist文件
      • 包含了程序的代码签名
        这里写图片描述

五 启动

  • 其实在启动过程中,dyld(动态链接器) 起了很重要的作用,进行动态链接,进行符号和地址的一个绑定

dyld 主要在启动过程中主要做了以下事情:

  • 加载所依赖的dylibs
  • Fix-ups:Rebase修正地址偏移,因为 OS X和 iOS 搞了一个叫 ASLR的东西来做地址偏移(随机化)来避免收到攻击
  • Fix-ups:Binding确定 Non-Lazy Pointer地址,进行符号地址绑定。
  • ObjC runtime初始化:加载所有类
  • Initializers:执行load 方法和_attribute_((constructor))修饰的函数

对于如何减少启动时间,今年的 WWDC 也有详细的阐述,可以在参考链接中找到相关的资料。

总结

编译 - 汇编 - 静态链接 - 签名 - 启动(动态链接等操作)- 跑起来了

这里写图片描述

参考链接

  • 虎书
  • 程序员的自我修养
  • MDCC 2016 - 孙源(Sunnyxx)- clang 概述
  • iDev 2016 - 孙源(Sunnyxx)- 把玩链接器
  • 优化 App 的启动时间
  • WWDC 2016 Session 406

名词解释

  • SPARC

    • 全称为“可扩充处理器架构”(Scalable Processor ARChitecture),是RISC微处理器架构之一
  • MIPS(Million Instructions Per Second):

    • 单字长定点指令平均执行速度 Million Instructions Per Second的缩写,每秒处理的百万级的机器语言指令数。这是衡量CPU速度的一个指标
  • Pentium

    • Pentium(奔腾)是英特尔第五代x86架构的微处理器
### 关于在Mac上构建PyArrow轮子文件时遇到的问题 当尝试在 macOS 上通过 `pip` 安装依赖项(如 PyAudio 或 PyArrow),并收到错误提示 `ERROR: Could not build wheels for ...` 时,这通常表明缺少必要的编译工具链或依赖库。以下是针对此问题的解决方案: #### 缺少开发环境配置 在 macOS 平台上,构建某些 Python 扩展模块可能需要 Xcode 命令行工具的支持。如果尚未安装这些工具,则可以通过运行以下命令来安装它们[^1]: ```bash xcode-select --install ``` #### 配置 C++ 编译器支持 对于像 PyArrow 这样的项目来说,它不仅依赖基础的 C/C++ 工具集,还特别要求具备现代标准兼容性的编译器版本。因此建议确认已启用最新版 Clang/LLVM 支持。 另外需要注意的是,部分扩展包会读取系统路径中的特定头文件以及共享对象(.so)/动态链接库(.dylib),所以还需要额外准备 Apache Arrow 的本地资源副本作为辅助材料之一[^2]: - **Homebrew 方法**: 使用 Homebrew 来简化获取所需外部组件的过程。 ```bash brew install apache-arrow ``` - **手动指定参数法**: 如果不想完全依靠包管理程序自动处理一切事情的话,也可以自行下载对应平台预编译二进制发行档,并将其解压至合适位置之后再告知 setup.py 文件所在确切地址。 ```python export ARROW_HOME=/path/to/unpacked/apache_arrow/ export PKG_CONFIG_PATH=$ARROW_HOME/lib/pkgconfig:$PKG_CONFIG_PATH python -m pip install pyarrow --no-binary :all: ``` 以上两种方式均能有效缓解因缺乏底层实现细节而导致无法顺利完成 Wheel 构建工作的困境。 --- ### 示例代码片段展示如何调整环境变量以适应不同情况下的需求 假设当前目录下存在名为 "apache_arrow" 的子文件夹存储着刚才提到的手动提取出来的资料结构体实例化过程如下所示: ```python import os os.environ['ARROW_HOME'] = './apache_arrow' os.environ['PKG_CONFIG_PATH'] += f"{os.path.join(os.getcwd(), 'apache_arrow', 'lib', 'pkgconfig')}:" print(f"Updated PKG_CONFIG_PATH={os.getenv('PKG_CONFIG_PATH')}") ``` 上述脚本的作用在于临时修改全局范围内生效的相关设置以便后续操作能够顺利执行下去而不会再次触发类似的异常状况发生. ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值