iOS开发之常用技术点iOS 中间件开发

iOS学习笔记 利用Clang 为App提升质量

2019-03-30  本文已影响82人  DrunkenMouse

基于Clang可以开发出在线网页代码导航工具,比如DXR
用于代码增量分析、代码可视化、代码质量报告的保障App质量的系统平台CodeChecker

什么是Clang

Clang是C、C++、OC的编译前端 ,Swift有自己的编译前端SIL optimizer

简单说,Clang是把C、OC、C++源码编译成为AST的编译前端。
AST:抽象语法树,代码更精简,更适合静态检查

Clang的优势:

  1. 对于使用者来说,Clang编译的速度非常快,对内存的使用率非常低,并且兼容GCC(XCode5之前的编译器)

  2. 对于代码诊断来说,Clang也非常强大。使用Clang编译前端,可以精确的显示出问题所在的行和具体位置,并可以准确说明出现问题的原因,指出错误类型是什么,使我们快速掌握问题的细节。

  3. Clang对typedef的保留和展开也处理的非常好。typedef可以缩写很长的类型,保留typedef对于粗粒度诊断分析很有帮助。当需要了解细节时,展开typedef即可。

  4. Fix-it提示也是Clang提供的一种快捷修复源码问题的方式。在宏处理上,很多宏都是深度嵌套的,Clang会自动打印实例化信息和嵌套范围信息来帮助宏的诊断和分析。

  5. Clang的架构是模块化的。除了代码静态分析外,利用其输出的接口还可以开发用于代码转义、代码生成、代码重构的工具,方便与IDE进行集成。

与Clang相比,GCC对于OC的支持比较差,效率和性能不达标,难以推动GCC团队发展。于是,苹果开发了LLVM工具套件,将GCC全面替换成了LLVM。

Clang源码

Clang提供了一个易用性很高的黑盒 Driver,用于封装前端命令和工具链的命令,使其易用性得到了提升。

Clang做了什么事?
首先,Clang会对代码进行词法分析,将代码切分成Token。

如查看main.m函数的所有Token:

clang -fmodules -E -Xclang -dump-tokens main.m

这个命令可以显示每个Token的类型、值,以及位置。
查看所有的Token类型
Clang定义的Token类型,大致可以分四类:

词法分析完后会进行语法分析,将输出的Token按照语法组合成语义,生成类似VarDecl这样的节点,然后将节点按照层级关系构成AST。

查看main.m的语法树

clang -fmodules -fsyntax-only -Xclang -ast-dump main.m

TranslationUnitDecl是根节点,表示一个编译单元。
Decl表示一个声明
Expr表示这是一个表达式
Literal表示字面量,一个特殊的Expr
Stmt表示陈述

Clang还有众多的节点类型。Clang里,节点主要分成Type类型、Decl声明、Stmt陈述这三种,其余都是这三种的派生。

总结:先做词法分析,将代码切分成Token。在进行语法分析,将输出的Token按照语法组合成语义,生成类似VarDecl这样的节点,然后将节点按照层级关系构成AST。

示列如下:

TranslationUnitDecl 0xc75b450 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0xc75b740 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list ‘char *’
`-FunctionDecl 0xc75b7b0 <test.cpp:1:1, line:7:1> line:1:5 main ‘int (void)’
  `-CompoundStmt 0xc75b978 <line:2:1, line:7:1>
    |-DeclStmt 0xc75b870 <line:3:2, col:7>
    | `-VarDecl 0xc75b840 <col:2, col:6> col:6 used a ‘int’
    |-DeclStmt 0xc75b8d8 <line:4:2, col:12>
    | `-VarDecl 0xc75b890 <col:2, col:10> col:6 used b ‘int’ cinit
    |   `-IntegerLiteral 0xc75b8c0 <col:10> ‘int’ 10

<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< a = b <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    |-BinaryOperator 0xc75b928 <line:5:2, col:6> ‘int’ lvalue ‘=‘
    | |-DeclRefExpr 0xc75b8e8 <col:2> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int’
    | `-ImplicitCastExpr 0xc75b918 <col:6> ‘int’ <LValueToRValue>
    |   `-DeclRefExpr 0xc75b900 <col:6> ‘int’ lvalue Var 0xc75b890 ‘b’ ‘int’
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

    `-ReturnStmt 0xc75b968 <line:6:2, col:9>
      `-ImplicitCastExpr 0xc75b958 <col:9> ‘int’ <LValueToRValue>
        `-DeclRefExpr 0xc75b940 <col:9> ‘int’ lvalue Var 0xc75b840 ‘a’ ‘int

Clang提供了什么能力?

Clang为一些需要分析代码语法、语义信息的工具提供了基础设施。这些基础设施就是LibClang、ClangPlugin、LibTooling。

LibClang

LibClang提供了一个稳定的高级C接口,XCode使用的就是LibClang。LibClang可以访问Clang的上层高级抽象的能力,比如获取所有Token、遍历语法树、代码补全等。由于API稳定,Clang版本更新对其影响不大。但是LibClang并不能完全访问到ClangAST信息。

使用LibClang可以直接用它的C API,或者官方脚本Python binding。还有开源的node-js/ruby binding,OC写的ClangKit库

Clang Plugins

Clang Plugins可以在AST上做些操作,这些操作能够集成到编译中,成为编译的一部分。插件是在运行时由编译器加载的动态库,方便集成到构建系统中。

使用Clang Plugins 一般希望完全控制Clang AST,同时能够集成在编译流程中,可以影响编译的过程,进行中断或者提示。

LibTooling

LibTooling是一个C++接口,通过LibTooling能够编写独立运行的语法检查和代码重构工具。

LibTooling优势如下:

与Clang Plugins相比,LibTooling无法影响编译过程;
与LibClang相比,LibTooling的接口没有那么稳定,也没法开箱即用,当AST的API升级后需要更新接口的调用。

但是,LibTooling基于能够完全控制Clang AST 和可独立运行的特点,可以做到很多事情。

基于LibTooling有个开发人员工具合集:ClangTools。工具主要有:

LibTooling的基本使用方法:LibASTMatchersTutorial

iOS开发课笔记。
上一篇 下一篇

猜你喜欢

热点阅读