美文网首页
clang操作记录

clang操作记录

作者: 沉江小鱼 | 来源:发表于2020-08-06 15:22 被阅读0次

    1. 介绍

    clang提供了一些命令,让我们可以对编译的过程进行一些配置和查看,下面我们就对一些常用的指令进行一个基本的介绍.

    2. 常用指令

    2.1 查看编译的步骤
    clang -ccc-print-phases main.m
    

    输出结果如下:

    0: input, "main.m", objective-c               / 找到main.m文件
    1: preprocessor, {0}, objective-c-cpp-output  / 预处理器,处理include、import、宏定义
    2: compiler, {1}, ir                          / 编译器编译,编译成ir中间代码
    3: backend, {2}, assembler                    / 后端,生成目标代码
    4: assembler, {3}, object                     / 汇编
    5: linker, {4}, image                         / 链接其他动态库静态库
    6: bind-arch, "x86_64", {5}, image            / 编译成适合某个架构的代码
    
    2.2 将.m文件转换成.cpp文件

    cd 到.m文件在的目录下,然后:

    clang -rewrite-objc main.m
    

    会在目录下生成main.cpp文件,如果有报错,请自行查找解决办法。

    2.3 查看操作内部命令,可以使用 -###命令
    clang -### main.m -o main
    
    2.4 查看预编译的结果
    clang -E main.m
    

    这个命令敲出,终端就会打印许多信息,直接拉到最下面,看到输出的:

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    
            NSLog(@"Hello, World!");
            int index = 10 + 1;
            NSLog(@"%d",index);
        }
        return 0;
    }
    

    源代码:

    #import <Foundation/Foundation.h>
    
    #define aaa 10
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            NSLog(@"Hello, World!");
            int index = aaa + 1;
            NSLog(@"%d",index);
        }
        return 0;
    }
    

    我们可以看到,预编译阶段把宏定义处理了。

    2.5 词法分析

    预处理完成后就会进行词法分析,这里会把代码切成一个个 Token,比如大小括号,等于号还有字符串等:

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

    输出如下:

    annot_module_include '#import <Foundation/Foundation.h>
    
    #define aaa 10
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
      '     Loc=<main.m:9:1>
    int 'int'    [StartOfLine]  Loc=<main.m:13:1>
    identifier 'main'    [LeadingSpace] Loc=<main.m:13:5>
    l_paren '('     Loc=<main.m:13:9>
    int 'int'       Loc=<main.m:13:10>
    identifier 'argc'    [LeadingSpace] Loc=<main.m:13:14>
    comma ','       Loc=<main.m:13:18>
    const 'const'    [LeadingSpace] Loc=<main.m:13:20>
    char 'char'  [LeadingSpace] Loc=<main.m:13:26>
    star '*'     [LeadingSpace] Loc=<main.m:13:31>
    identifier 'argv'    [LeadingSpace] Loc=<main.m:13:33>
    l_square '['        Loc=<main.m:13:37>
    r_square ']'        Loc=<main.m:13:38>
    r_paren ')'     Loc=<main.m:13:39>
    l_brace '{'  [LeadingSpace] Loc=<main.m:13:41>
    at '@'   [StartOfLine] [LeadingSpace]   Loc=<main.m:14:5>
    identifier 'autoreleasepool'        Loc=<main.m:14:6>
    l_brace '{'  [LeadingSpace] Loc=<main.m:14:22>
    identifier 'NSLog'   [StartOfLine] [LeadingSpace]   Loc=<main.m:16:9>
    l_paren '('     Loc=<main.m:16:14>
    at '@'      Loc=<main.m:16:15>
    string_literal '"Hello, World!"'        Loc=<main.m:16:16>
    r_paren ')'     Loc=<main.m:16:31>
    semi ';'        Loc=<main.m:16:32>
    int 'int'    [StartOfLine] [LeadingSpace]   Loc=<main.m:17:9>
    identifier 'index'   [LeadingSpace] Loc=<main.m:17:13>
    equal '='    [LeadingSpace] Loc=<main.m:17:19>
    numeric_constant '10'    [LeadingSpace] Loc=<main.m:17:21 <Spelling=main.m:11:13>>
    plus '+'     [LeadingSpace] Loc=<main.m:17:25>
    numeric_constant '1'     [LeadingSpace] Loc=<main.m:17:27>
    semi ';'        Loc=<main.m:17:28>
    identifier 'NSLog'   [StartOfLine] [LeadingSpace]   Loc=<main.m:18:9>
    l_paren '('     Loc=<main.m:18:14>
    at '@'      Loc=<main.m:18:15>
    string_literal '"%d"'       Loc=<main.m:18:16>
    comma ','       Loc=<main.m:18:20>
    identifier 'index'      Loc=<main.m:18:21>
    r_paren ')'     Loc=<main.m:18:26>
    semi ';'        Loc=<main.m:18:27>
    r_brace '}'  [StartOfLine] [LeadingSpace]   Loc=<main.m:19:5>
    return 'return'  [StartOfLine] [LeadingSpace]   Loc=<main.m:20:5>
    numeric_constant '0'     [LeadingSpace] Loc=<main.m:20:12>
    semi ';'        Loc=<main.m:20:13>
    r_brace '}'  [StartOfLine]  Loc=<main.m:21:1>
    eof ''      Loc=<main.m:21:2>
    

    可以看出,词法分析的时候,将上面的代码拆分一个个token,后面数字表示某一行的第几个字符,例如第一个int,表示第13行第1个字符。

    2.6 语法树-AST

    语法分析,生成语法树(AST,Abstract Syntax Tree):

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

    输出:

    TranslationUnitDecl 0x7fb8a8036608 <<invalid sloc>> <invalid sloc> <undeserialized declarations>
    |-TypedefDecl 0x7fb8a8036ea0 <<invalid sloc>> <invalid sloc> implicit __int128_t '__int128'
    | `-BuiltinType 0x7fb8a8036ba0 '__int128'
    |-TypedefDecl 0x7fb8a8036f10 <<invalid sloc>> <invalid sloc> implicit __uint128_t 'unsigned __int128'
    | `-BuiltinType 0x7fb8a8036bc0 'unsigned __int128'
    |-TypedefDecl 0x7fb8a8036fb0 <<invalid sloc>> <invalid sloc> implicit SEL 'SEL *'
    | `-PointerType 0x7fb8a8036f70 'SEL *' imported
    |   `-BuiltinType 0x7fb8a8036e00 'SEL'
    |-TypedefDecl 0x7fb8a8037098 <<invalid sloc>> <invalid sloc> implicit id 'id'
    | `-ObjCObjectPointerType 0x7fb8a8037040 'id' imported
    |   `-ObjCObjectType 0x7fb8a8037010 'id' imported
    |-TypedefDecl 0x7fb8a8037178 <<invalid sloc>> <invalid sloc> implicit Class 'Class'
    | `-ObjCObjectPointerType 0x7fb8a8037120 'Class' imported
    |   `-ObjCObjectType 0x7fb8a80370f0 'Class' imported
    |-ObjCInterfaceDecl 0x7fb8a80371d0 <<invalid sloc>> <invalid sloc> implicit Protocol
    |-TypedefDecl 0x7fb8a8037548 <<invalid sloc>> <invalid sloc> implicit __NSConstantString 'struct __NSConstantString_tag'
    | `-RecordType 0x7fb8a8037340 'struct __NSConstantString_tag'
    |   `-Record 0x7fb8a80372a0 '__NSConstantString_tag'
    |-TypedefDecl 0x7fb8a880bc00 <<invalid sloc>> <invalid sloc> implicit __builtin_ms_va_list 'char *'
    | `-PointerType 0x7fb8a80375a0 'char *' imported
    |   `-BuiltinType 0x7fb8a80366a0 'char'
    |-TypedefDecl 0x7fb8a880bee8 <<invalid sloc>> <invalid sloc> implicit __builtin_va_list 'struct __va_list_tag [1]'
    | `-ConstantArrayType 0x7fb8a880be90 'struct __va_list_tag [1]' 1 
    |   `-RecordType 0x7fb8a880bcf0 'struct __va_list_tag'
    |     `-Record 0x7fb8a880bc58 '__va_list_tag'
    |-ImportDecl 0x7fb8a88b6178 <main.m:9:1> col:1 implicit Foundation
    `-FunctionDecl 0x7fb8a88b6440 <line:13:1, line:21:1> line:13:5 main 'int (int, const char **)'
      |-ParmVarDecl 0x7fb8a88b61d0 <col:10, col:14> col:14 argc 'int'
      |-ParmVarDecl 0x7fb8a88b62f0 <col:20, col:38> col:33 argv 'const char **':'const char **'
      `-CompoundStmt 0x7fb8a88c3658 <col:41, line:21:1>
        |-ObjCAutoreleasePoolStmt 0x7fb8a88c3610 <line:14:5, line:19:5>
        | `-CompoundStmt 0x7fb8a88c35e8 <line:14:22, line:19:5>
        |   |-CallExpr 0x7fb8a80d62c0 <line:16:9, col:31> 'void'
        |   | |-ImplicitCastExpr 0x7fb8a80d62a8 <col:9> 'void (*)(id, ...)' <FunctionToPointerDecay>
        |   | | `-DeclRefExpr 0x7fb8a80d61b0 <col:9> 'void (id, ...)' Function 0x7fb8a88b6580 'NSLog' 'void (id, ...)'
        |   | `-ImplicitCastExpr 0x7fb8a80d62e8 <col:15, col:16> 'id':'id' <BitCast>
        |   |   `-ObjCStringLiteral 0x7fb8a80d6230 <col:15, col:16> 'NSString *'
        |   |     `-StringLiteral 0x7fb8a80d6208 <col:16> 'char [14]' lvalue "Hello, World!"
        |   |-DeclStmt 0x7fb8a88c3488 <line:17:9, col:28>
        |   | `-VarDecl 0x7fb8a88c33c0 <col:9, col:27> col:13 used index 'int' cinit
        |   |   `-BinaryOperator 0x7fb8a88c3468 <line:11:13, line:17:27> 'int' '+'
        |   |     |-IntegerLiteral 0x7fb8a88c3428 <line:11:13> 'int' 10
        |   |     `-IntegerLiteral 0x7fb8a88c3448 <line:17:27> 'int' 1
        |   `-CallExpr 0x7fb8a88c3588 <line:18:9, col:26> 'void'
        |     |-ImplicitCastExpr 0x7fb8a88c3570 <col:9> 'void (*)(id, ...)' <FunctionToPointerDecay>
        |     | `-DeclRefExpr 0x7fb8a88c34a0 <col:9> 'void (id, ...)' Function 0x7fb8a88b6580 'NSLog' 'void (id, ...)'
        |     |-ImplicitCastExpr 0x7fb8a88c35b8 <col:15, col:16> 'id':'id' <BitCast>
        |     | `-ObjCStringLiteral 0x7fb8a88c3518 <col:15, col:16> 'NSString *'
        |     |   `-StringLiteral 0x7fb8a88c34f8 <col:16> 'char [3]' lvalue "%d"
        |     `-ImplicitCastExpr 0x7fb8a88c35d0 <col:21> 'int' <LValueToRValue>
        |       `-DeclRefExpr 0x7fb8a88c3538 <col:21> 'int' lvalue Var 0x7fb8a88c33c0 'index' 'int'
        `-ReturnStmt 0x7fb8a88c3648 <line:20:5, col:12>
          `-IntegerLiteral 0x7fb8a88c3628 <col:12> 'int' 0
    

    在终端敲出的时候,终端很直观的帮我们用颜色区分。

    2.7 生成中间代码

    完成这些步骤后就可以开始IR(intermediate representation)中间代码的生成了,CodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IR,IR 是编译过程的前端的输出后端的输入。

    clang -S -fobjc-arc -emit-llvm main.m -o main.ll
    
    2.8 生成汇编
    clang -S -fobjc-arc main.m -o main.s
    
    2.9 生成目标文件
    clang -fmodules -c main.m -o main.o
    

    相关文章

      网友评论

          本文标题:clang操作记录

          本文链接:https://www.haomeiwen.com/subject/rerwrktx.html