Xcode预编译命令

cd ~/Desktop 

touch main.m

open main.m 

vi main.m 

 #import <Foundation/Foundation.h>

 int main() {

NSLog(@"Hello world");
return 0;

  }

clang main.m -o main  //直接生成一个可执行文件
<!--more-->

错误原因:未识别Foundation框架

Undefined symbols for architecture x86_64:
"_NSLog", referenced from:
  _main in main-276b38.o
"___CFConstantStringClassReference", referenced from:
  CFString in main-276b38.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

clang -fmodules main.m -o main //-fmodules强转成@import形式

./main  //run一下

clear

clang -fmodules -fsyntax-only -Xclang -ast-dump main.m  //查看语法树

# 第一部分为环境

TranslationUnitDecl 0x7fec3180a6d0 <<invalid sloc>> <invalid sloc>
|-TypedefDecl 0x7fec3180abc8 <<invalid sloc>>     <invalid sloc> implicit __int128_t '__int128'
| `-BuiltinType 0x7fec3180a920 '__int128'
|-TypedefDecl 0x7fec3180ac28 <<invalid sloc>>     <invalid sloc> implicit __uint128_t 'unsigned __int128'
| `-BuiltinType 0x7fec3180a940 'unsigned __int128'
|-TypedefDecl 0x7fec3180acb8 <<invalid sloc>> <invalid sloc> implicit SEL 'SEL *'
| `-PointerType 0x7fec3180ac80 'SEL *'
|   `-BuiltinType 0x7fec3180ab30 'SEL'
|-TypedefDecl 0x7fec3180ad98 <<invalid sloc>> <invalid sloc> implicit id 'id'
| `-ObjCObjectPointerType 0x7fec3180ad40 'id' imported
|   `-ObjCObjectType 0x7fec3180ad10 'id' imported
|-TypedefDecl 0x7fec3180ae78 <<invalid sloc>> <invalid sloc> implicit Class 'Class'
| `-ObjCObjectPointerType 0x7fec3180ae20 'Class'
|   `-ObjCObjectType 0x7fec3180adf0 'Class'
|-ObjCInterfaceDecl 0x7fec3180aec8 <<invalid sloc>> <invalid sloc> implicit Protocol
|-TypedefDecl 0x7fec3180b218 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct     __NSConstantString_tag'
| `-RecordType 0x7fec3180b030 'struct     __NSConstantString_tag'
|   `-Record 0x7fec3180af90 '__NSConstantString_tag'
|-TypedefDecl 0x7fec3180b2a8 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
| `-PointerType 0x7fec3180b270 'char *'
|   `-BuiltinType 0x7fec3180a760 'char'
|-TypedefDecl 0x7fec32000178 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
| `-ConstantArrayType 0x7fec32000120 'struct __va_list_tag [1]' 1 
|   `-RecordType 0x7fec3180b3a0 'struct __va_list_tag'
|     `-Record 0x7fec3180b2f8 '__va_list_tag'

# 第二部分为自己的代码部分

|-ImportDecl 0x7fec32000eb0 <main.m:1:1> col:1 implicit Foundation
|-FunctionDecl 0x7fec32000f38 <line:3:1, line:8:1> line:3:5 main 'int ()'
| `-CompoundStmt 0x7fec309f5550 <col:12, line:8:1>
|   |-CallExpr 0x7fec309f54d0 <line:5:5, col:25> 'void'
|   | |-ImplicitCastExpr 0x7fec309f54b8 <col:5> 'void (*)(id, ...)' <FunctionToPointerDecay>
|   | | `-DeclRefExpr 0x7fec309f53a0 <col:5> 'void     (id, ...)' Function 0x7fec309ed460 'NSLog' 'void     (id, ...)'
|   | `-ImplicitCastExpr 0x7fec309f5500 <col:11, col:12> 'id':'id' <BitCast>
|   |   `-ObjCStringLiteral 0x7fec309f5440 <col:11, col:12> 'NSString *'
|   |     `-StringLiteral 0x7fec309f5408 <col:12> 'char [12]' lvalue "Hello world"
|   `-ReturnStmt 0x7fec309f5538 <line:6:5, col:12>
|     `-IntegerLiteral 0x7fec309f5518 <col:12> 'int' 0

`-<undeserialized declarations>

#

生成汇编

clang -S main.m -o main.s

vi main.s
# 输出
retq

.cfi_endproc



.section        __TEXT,__cstring,cstring_literals

L_.str: ## @.str

.asciz  "Hello world"



.section        __DATA,__cfstring

.align  3                       ## @_unnamed_cfstring_

L__unnamed_cfstring_:

.quad   ___CFConstantStringClassReference

.long   1992                    ## 0x7c8

.space  4

.quad   L_.str

.quad   11                      ## 0xb



.section        __DATA,__objc_imageinfo,regular,no_dead_strip

L_OBJC_IMAGE_INFO:

.long   0

.long   64

.subsections_via_symbols

<img
src = “http://chuantu.biz/t5/38/1476935851x981781122.png"
width = “100%”
align = “center”

我们能在Clang上做些什么

LibClang

(1)优缺点

1.C API 来访问Clang的上层能力,如获取Tokens、遍历语法树、代码补全、获取诊断信息

2.API稳定,不受Clang源码更新影响

3.只有上层的语法树访问,不能获取到全部信息

(2)LibClang - 如何使用

1.使用原始C API
2.脚本语言:使用官方提供的python binding 或开源的node-js/rubybinding
3.Object-c:开源库ClangKit

(3)LibClang-Demo

@inteface Sark : NSObject
@property (nonatomic , strong) NSString * backgrond;
@end
代码中一些常用单词的拼写错误
<img
src = “http://chuantu.biz/t5/38/1476940990x981781122.png"
width = “100%”
align = “center”

运行结果
$python property-linter.py main.m

获取正确的提示

typo: backgrond, do you mean: background?

LibTooling

(1)优缺点

1.对语法树有完全的控制权
2.可以作为一个standalore命令单独的使用,如clang-format
3.需要使用C++且对Clang源码熟悉

LibTooling -Demo

@interface Sark : NSObject

@property (nonatomic , copy)NSString *name;

  • (void)becomeGay;

    @end

    实现一个建议的Object-c -> Swift源码转换器
    <img
    src = “http://chuantu.biz/t5/38/1476941655x981781122.png"
    width = “100%”
    align = “center”

    创建RecursiveASTVisitor, 在AST中重写感兴趣节点的Visit方法

    $objc2swift test.m – -fsyntax-only -fmodules

    转换完毕之后

    class Sark: NSObject {<br>
    
        var name: NSString?<br>
    
        func becomeGay() {<br>
    
    }<br>
    

    }

ClangPlugin

优缺点

1.对语法书有完全的控制权

2.作为插件注入到编译流程中,可以影响build和决定编译过程

3.需要使用C++且对Clang源码熟悉

可以定义前缀提示,比如大公司整顿代码风格

<img
src = “http://chuantu.biz/t5/38/1476942114x981781122.png"
width = “100%”
align = “center”

代码Demo

<img
src = “http://chuantu.biz/t5/38/1476942267x981781122.png"
width = “100%”
align = “center”

Clang-LLVM 相关资料

<img
src = “http://chuantu.biz/t5/38/1476943209x981781122.png"
width = “100%”
align = “center”

<img
src = “http://chuantu.biz/t5/38/1476943306x981781122.png"
width = “100%”
align = “center”

@end