当前位置: 首页 > 科技观察

iOS前端编译器扩展——Clang

时间:2023-03-22 16:19:44 科技观察

Part01.理解Clang众所周知,编译器一般分为前端和后端。编译器前端主要负责预处理、词法分析、语法分析、语法检查和中间代码生成。独立于底层计算机体系结构工作。后端以中间代码为输入,先进行架构无关的代码优化,然后针对不同的机器架构生成不同的机器码进行组装和链接。Clang主要用于iOS代码编译中的C/C++和Objective-C的前端编译。Clang是llvm编译链的一部分,是llvm的前端编译器。我们可以通过Clang开放的API接口对源码进行自定义,比如静态代码检查、编译过程控制、代码搜索提示补全等功能。Clang工具的对象是AST——语法分析的结果,抽象语法树(abstractsyntaxtree)。AST的一个简单例子:Clang工具可以遍历读取AST上的每一个节点,查询和修改该节点对应的代码。Clang插件可以直接集成到iOS的编译过程中,控制自定义编译警告和错误的输出,控制编译过程。Part02、Clang工具选择Clang一般包括三种不同的工具,libClang、Clang插件和libTooling。Clang插件类似于libTooling代码,所有关于AST的信息都是通过ASTContext上下文返回的,它对AST有完全的控制权。与libClang不同,它通过封装稳定的高层CAPI来访问,使用Cursor和Token递归遍历,不能完全控制AST。三者的优缺点如下:1.libClanglibClang是一个稳定的Clang高级C语言包。当您不需要完全控制AST时,libClang是最简单、最适合使用的工具,应该首先考虑。其次,它只能作为一个独立的工具使用,不能嵌入到当前项目的编译过程中。优点:可以使用XCode或者Python进行集成开发,具有稳定的高层API,简单易用;缺点:不能完全控制AST,不能嵌入编译过程。2.Clang插件Clang插件允许在代码编译过程中插入额外的操作,例如在编译过程中打印特殊字符或警告,甚至中断编译。优点:可以嵌入到编译过程中启动或中断编译,打印自定义警告和错误,完全控制AST;缺点:代码编写复杂,集成Clang插件会降低原有的编译速度。3.libToolinglibTooling是一个基于C的Clang工具,用于编写独立的工具,与libClang类似,但只能用C编写,功能更强大,可以完全控制AST。优点:完全处理工程文件,完全控制AST;缺点:不能嵌入编译过程,对Clang升级敏感,API不稳定。这三个工具,从上到下,兼容性越来越差,对Clang升级变化越来越敏感,使用越来越复杂,但功能却越来越强大。Part03,Clang的具体应用Clang在和家琴的应用尚处于初步阶段。我们使用libClang遍历项目中的每一个源文件,找到项目中所有图片名称的字符串描述。图片名称往往以固定字符串的形式出现,以此来判断我们项目中哪些图片已经使用,哪些没有使用,优化包的大小。我们使用Clang插件对项目中已经定义但没有在项目中使用的类和方法进行告警。方法是:先使用Clang插件的VisitObjCInterfaceDecl和VisitObjCMethodDecl方法找到项目中所有的类定义和方法定义,然后使用VisitObjCMessageExpr和VisitObjCSelectorExpr找到所有的消息发送。在iOS中,方法调用是以消息发送的形式进行的。对于那些没有出现在消息发送列表中的类和方法,我们认为这些类和方法没有被使用,所以我们会在编译时直接发出警告提示。它可以通过在编译器中集成插件来使用。