Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >clang 源码导读(2): clang driver 流程简介

clang 源码导读(2): clang driver 流程简介

作者头像
酷酷的哀殿
发布于 2021-03-18 01:48:46
发布于 2021-03-18 01:48:46
2.5K01
代码可运行
举报
文章被收录于专栏:酷酷的哀殿酷酷的哀殿
运行总次数:1
代码可运行

前言

本文会对 clang driver 的内部流程做一个简单的介绍。

clang driver 流程简介

clang Driver 负责拼接编译器命令和 ld 命令。

注意:clang driver 自身不会对源码进行编译

clang Driver 的处理逻辑分为以下几步:

Parse: Option Parsing:解析传入的参数

Pipeline: Compilation Action Construction:根据每个输入的文件和类型,组建 action(比如 PreprocessJobAction

可以通过 clang -ccc-print-phases 可以查看需要处理的 action

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
  clang -ccc-print-phases -c t0.c t1.c
              +- 0: input, "t0.c", c
           +- 1: preprocessor, {0}, cpp-output
        +- 2: compiler, {1}, ir
     +- 3: backend, {2}, assembler
  +- 4: assembler, {3}, object
  5: bind-arch, "x86_64", {4}, object
              +- 6: input, "t1.c", c
           +- 7: preprocessor, {6}, cpp-output
        +- 8: compiler, {7}, ir
     +- 9: backend, {8}, assembler
  +- 10: assembler, {9}, object
  11: bind-arch, "x86_64", {10}, object

Bind: Tool & Filename Selection:根据 action 选择对应的工具文件名信息

通过 clang -ccc-print-bindings 可以查看对应的工具文件名信息

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
clang -ccc-print-bindings -c t0.c t1.c -arch arm64 -arch armv7
# "aarch64-apple-darwin19.6.0" - "clang", inputs: ["t0.c"], output: "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t0-9a2aac.o"
# "arm-apple-darwin19.6.0" - "clang", inputs: ["t0.c"], output: "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t0-7a4059.o"
# "arm-apple-darwin19.6.0" - "darwin::Lipo", inputs: ["/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t0-9a2aac.o", "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t0-7a4059.o"], output: "t0.o"
# "aarch64-apple-darwin19.6.0" - "clang", inputs: ["t1.c"], output: "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t1-950abb.o"
# "arm-apple-darwin19.6.0" - "clang", inputs: ["t1.c"], output: "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t1-044386.o"
# "arm-apple-darwin19.6.0" - "darwin::Lipo", inputs: ["/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t1-950abb.o", "/var/folders/4j/jqzrrjzn0nvgm4pyxrqddxnmm530jm/T/t1-044386.o"], output: "t1.o"

Translate: Tool Specific Argument Translation:根据输入的参数转为不同 tool 的参数

xcrun --sdk iphoneos clang -arch arm64 main.m -v-arch arm64 参数为例:

原始命令:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
xcrun --sdk iphoneos clang -arch arm64  main.m -v

各个 tool 的参数:

image

  • usr/bin/clang -cc1 的参数:-triple arm64-apple-ios14.4.0

Execute:调用不同的 tool 执行任务。

该步骤会通过创建子进程方式调用tool

仍然以 xcrun --sdk iphoneos clang -arch arm64 main.m -v 为例,clang driver 最终会创建两个子线程 clang -cc1ld 执行最终的编译任务和链接任务

  • clang -cc1 可以将源码转为对象文件。本例中,clang -cc1 会将 .m 文件转为 .o 文件

为了方便理解,我们可以将下面的图片和上面的流程对应:

DriverArchitecture

更多相关内容可以参考笔者之前的文章 Ruby 与 clang 的 "Clang driver" 部分 或者 Driver Design & Internals


clang driver 源码概览

首先,我们以 xcrun -l clang main.m -v -O2 -o demo 为例对整个流程做一个简单的介绍

  1. 第一步:clang 会以 driver 模式被调用
  2. 第二步,clang driver 会根据传入的 main.m 参数构建为两个 Job
    1. 第一个任务是编译任务clang 接收 -cc1 参数后会以编译器的身份执行编译任务,输入文件是 main.m,输出文件是 main.o 对象文件
    2. 第二个任务是链接任务ld 会将 main.o 链接为 demo 可执行文件
  3. 最后,会根据上面的两个 Job 创建新的进程执行上面的两个 Job

image

正式分享前,我们先对本文涉及的 流程图 进行初步分享。读者可以结合流程图辅助记忆。

注意:随着源码的逐渐分析,流程图的细节会被逐渐完善

  1. main 函数会先创建诊断 (DiagnosticsEngine)实例 诊断是编译器与开发者进行交互的重要部分。编译器通过诊断可以提供错误、警告或建议。

image

  1. 随后,开始创建 Driver (clang::driver::Driver) 的实例:TheDriverTheDriver 负责后续的 clang driver 相关任务

image

  1. 通过 DriverBuildCompilation 方法生成需要执行的命令

image

  1. Driver 构造完 Jobs 后,会通过 DriverExecuteCompilation 方法执行命令

image

构建 Compilation

下面,我们再对 BuildCompilation 的流程进一步拆解。

BuildCompilation 方法主要包含以下步骤:

参数处理

调用 ParseArgStrings 函数 处理程序接收的参数 和 对配置文件解析

image

通过 computeTargetTriple 函数获取 triple 并通过 getToolChain 函数获取对应的 ToolChain

image

getToolChain 函数逻辑比较简单,对于 iOS 开发者,该函数会返回根据 triple 的系统信息返回 DarwinClang 的实例

image

创建 Commpilation 持有参数

image

通过 BuildInputs 函数获取输入文件

image

clang driver 支持一次性编译多个文件,比如下面的命令可以同时编译 main.mtest.m 两个源码文件

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
xcrun -l -sdk iphoneos clang main.m -arch arm64 -target x86_64-apple-ios8.0 test.m -v

BuildInputs 方法会遍历所有的参数,并筛选 Option::InputClass 类型的参数,最后会调用函数 types::ID types::lookupTypeForExtension(llvm::StringRef Ext) 获取对应的 types::ID

image

types::ID types::lookupTypeForExtension(llvm::StringRef Ext) 函数会根据输入文件 main.m 的扩展名 m 获取该文件的类型 TY_OBJC

image

输入文件处理完成后,会通过 BuildUniversalActions 函数构建 Action

image

随后再通过 BuildJobs 函数构建 Jobs

image

经过本节分析后,我们的流程图节点也膨胀了一倍,并且能够和之前分享的 clang driver 流程图片基本一一对应。

本文总结

本文结合实际的例子,对 clang driver 流程进行了简单的分享。

下一篇开始,我们会对 clang driver 的各种细节逐一介绍。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 酷酷的哀殿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Ruby 与 clang
笔者在使用 `rbenv`[1] 安装 ruby 时,遇到一个头文件缺失导致无法编译失败的问题。
酷酷的哀殿
2021/01/04
2K0
Ruby 与 clang
clang 源码导读(1): clang 入门
本系列文章会通过对 clang 源码进行拆解的方式,逐步对 clang 内部的各种逻辑进行介绍。
酷酷的哀殿
2021/03/18
5.4K0
clang 源码导读(1): clang 入门
clang 源码导读(3): clang driver 参数解析
为了控制 clang 的运行,clang 必须支持不同的参数对各种行为进行控制,所以,clang driver 启动后的第一个主要任务就是 参数解析
酷酷的哀殿
2021/03/18
2.2K0
clang 源码导读(3): clang driver 参数解析
clang 源码导读(4): clang driver 构建 Actions
本篇文章会对 clang driver 的 构建 Actions 流程进行详细的讲解
酷酷的哀殿
2021/03/18
2.5K1
clang 源码导读(4): clang driver 构建 Actions
「类与对象」揭秘本质的第一步
若想了解Objective-C一些API具体实现以及一些对象真实的数据结构等,就需要将Objective-C语言转化成C/C++语言。
Jacklin
2019/11/25
4700
llvm 编译器高级用法:第三方库插桩
最近看到一篇有意思的技术文章:《抖音研发实践:基于二进制文件重排的解决方案 APP启动速度提升超15%》。
酷酷的哀殿
2021/01/04
3.8K0
llvm 编译器高级用法:第三方库插桩
clang 源码导读(7):编译器前端流程简介
clang 编译器前端负责从源码生成中间码,它通常由 clang 模块驱动,并通常包含以下几个步骤:
酷酷的哀殿
2021/04/09
3.7K0
OC底层探索06-isa本身藏了多少信息你知道吗?OC底层探索06-isa本身藏了多少信息你知道吗?
一直都说类最终都会编译为struct,可是怎么验证呢?编译后的结构体内部都会有些什么东西呢?
用户8893176
2021/08/09
4070
OC底层探索06-isa本身藏了多少信息你知道吗?OC底层探索06-isa本身藏了多少信息你知道吗?
OC底层探索14-方法名Type EncodingsOC底层探索14-方法名Type Encodings
在对cpp文件进行查看的时候,发现有一些特殊的符号很是常见,像这样的方法Sel-"v16@0:8"到底代表什么意义,这次决定把它搞搞清楚到底是什么。
用户8893176
2021/08/09
3550
OC底层探索14-方法名Type EncodingsOC底层探索14-方法名Type Encodings
Objective-C源文件编译过程
Objective-C文件的编译过程主要包括clang前端的预处理、编译、后端优化中间表示、生成汇编指令、链接、生成机器码这几个步骤。我们可以借助clang -ccc-print-phases xxx.m命令查看某个OC源文件的编译的过程,如下: 输入命令
VV木公子
2019/10/14
9.8K0
Objective-C源文件编译过程
深入剖析 iOS 编译 Clang / LLVM
2000年,伊利诺伊大学厄巴纳-香槟分校(University of Illinois at Urbana-Champaign 简称UIUC)这所享有世界声望的一流公立研究型大学的 Chris Lattner(他的 twitter @clattner_llvm ) 开发了一个叫作 Low Level Virtual Machine 的编译器开发工具套件,后来涉及范围越来越大,可以用于常规编译器,JIT编译器,汇编器,调试器,静态分析工具等一系列跟编程语言相关的工作,于是就把简称 LLVM 这个简称作为了正式的名字。Chris Lattner 后来又开发了 Clang,使得 LLVM 直接挑战 GCC 的地位。2012年,LLVM 获得美国计算机学会 ACM 的软件系统大奖,和 UNIX,WWW,TCP/IP,Tex,JAVA 等齐名。
用户7451029
2020/06/16
8.4K0
深入剖析 iOS 编译 Clang / LLVM
iOS底层原理之LLVM & Clang
今天开始,我们对编译器架构系统LLVM进行一个简单的了解和分析,了解完LLVM的编译流程之后,简单实现一个Clang插件玩玩。下面就开始今天的内容。
CC老师
2022/01/14
1.7K0
iOS底层原理之LLVM & Clang
(1)Objective-C的本质
众说周知,我们平时编写的OC代码,底层都是C/C++实现的 我们可以通过一个终端指令,将我们的OC代码转换成C/C++代码 xcrun -sdk iphoneos clang -arch arm64
czjwarrior
2018/05/28
4180
Swift Module Interfaces
今天看到一篇讲 Swift Crash 的文章一个 Swift Crash 引发的讨论...原文作者从Swift源码和UIKitCore -[UIView(UIKitManual) autorelease] 汇编代码的角度对 crash 的原因进行了分析。
酷酷的哀殿
2020/10/26
1.7K0
Swift Module Interfaces
iOS底层原理--OC对象的本质
分析: OC代码的底层实现实质是C/C++代码,继而编译成汇编代码,最终变成机器语言。 打开终端,进入main.m所在的文件夹,通过clang rewirte-objc main.m -o main.cpp或xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp 代码,生成cpp文件。 在cpp文件中找到如下代码:
谦谦君子修罗刀
2019/03/22
6960
iOS底层原理--OC对象的本质
Xcode 常见 CLI 工具
在咱们日常开发中,或多或少都会用到 Xcode 内置的一些CLI工具,但是大部分小伙伴可能只是会用到一些具体的命令,今天我们就一起来聊一聊 Xcode 内置的常见Command Lines Tool。
CoderStar
2022/09/23
4.1K0
一个NSObject对象占用多少个字节
在Objective-C中,我们可以通过一些方法来获取一个NSObject对象占用多少字节 代码获取NSObject实例对象的成员变量字节大小 * 获取一个NSObject实例对象的成员变量所占用的字节大小,可以用`runtime`的api, `class_getInstanceSize`来获取,得到`8` /** * Returns the size of instances of a class. * * @param cls A class object. * * @retur
ruochen
2021/11/22
7250
iOS 进阶之 Block 的本质及原理
相信稍微有点开发经验的开发者,应该都对 block 有一定的了解。刚开始使用 block 的时候,可能觉得很方便。知道怎么去用,但是知其然知其所以然的态度来分析一下 block 的原理和内部结构是什么。
网罗开发
2021/01/29
7110
iOS 进阶之 Block 的本质及原理
OC 对象的本质
一个 NSObject 对象占用多少内存? 一个指针变量所占用的大小(64bit->8个字节,32bit->4个字节) 我们平时编写的Objective-C代码,底层实现都是C/C++代码,Objective-C的面向对象都是基于C/C++的数据结构实现的。 Objective-C -> C/C++ -> 汇编语言 -> 机器语言 如果想研究一些本质问题,最好将Objective-C代码转化成C/C++代码,才比较容易分析出来原理。 Objective-C的对象、类主要是基于C/C++的什么数
用户1890628
2018/05/10
1.2K0
定量分析 static 字符串对二进制体积的影响
今天交流群有网友遇到 linkmap 文件无法准确分析 static 字符串对二进制的体积的问题。
酷酷的哀殿
2021/03/22
6680
定量分析 static 字符串对二进制体积的影响
相关推荐
Ruby 与 clang
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档