• MacOS使用clang


    clang是编译器前端,用来做预处理,词法分析,语法分析,它可以把结果转换为抽象语法树AST,然后交给LLVM编译器后端,最终生成可执行程序。

    代码的编译过程可以分为预处理,词法分析,语法分析,语义分析,目标代码,链接,生成可执行程序,本文在MacOS平台结合clang命令完成一段C++代码的编译。

    新建一个文件main.cpp,写入C++代码。

    #include 
    
    #define STR "Hello world"
    
    int main(int argc, const char * argv[]) {
        std::string a = STR;
        std::cout << a << std::endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们先使用clang命令查看这个段代码的编译过程,由于代码是C++,需要使用clang++

    clang++ -ccc-print-phases main.cpp
    
    • 1

    终端输出了信息

                   +- 0: input, "main.cpp", c++
                +- 1: preprocessor, {0}, c++-cpp-output
             +- 2: compiler, {1}, ir
          +- 3: backend, {2}, assembler
       +- 4: assembler, {3}, object
    +- 5: linker, {4}, image
    6: bind-arch, "x86_64", {5}, image
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    input指的是输入源码文件,preprocessor是预处理,compiler是编译器前端,compiler做词法分析,语法分析,语义分析。随后backend生成汇编,生成目标文件。linker是链接,生成image。最后bind-arch处理架构信息,生成架构相关的image文件。

    1.查看preprocessor预处理过程

    clang++ -E main.cpp -o main.i
    
    • 1

    生成的main.i文件很长,滑动到底部可以看到源码部分

    int main(int argc, const char * argv[]) {
        std::string a = "Hello world";
        std::cout << a << std::endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    可以看到预处理阶段,宏定义被展开,代码部分还未处理。

    2.查看词法分析

    clang++ -fmodules -E -Xclang -dump-tokens main.cpp
    
    • 1

    生成的词法分析结果很长,这里仅截取一小段

    identifier 'std'	 [StartOfLine] [LeadingSpace]	Loc=<main.cpp:14:5>
    coloncolon '::'		Loc=<main.cpp:14:8>
    identifier 'cout'		Loc=<main.cpp:14:10>
    lessless '<<'	 [LeadingSpace]	Loc=<main.cpp:14:15>
    identifier 'a'	 [LeadingSpace]	Loc=<main.cpp:14:18>
    lessless '<<'	 [LeadingSpace]	Loc=<main.cpp:14:20>
    identifier 'std'	 [LeadingSpace]	Loc=<main.cpp:14:23>
    coloncolon '::'		Loc=<main.cpp:14:26>
    identifier 'endl'		Loc=<main.cpp:14:28>
    semi ';'		Loc=<main.cpp:14:32>
    return 'return'	 [StartOfLine] [LeadingSpace]	Loc=<main.cpp:15:5>
    numeric_constant '0'	 [LeadingSpace]	Loc=<main.cpp:15:12>
    semi ';'		Loc=<main.cpp:15:13>
    r_brace '}'	 [StartOfLine]	Loc=<main.cpp:16:1>
    eof ''		Loc=<main.cpp:16:2>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    词法分析就是对源码进行解析,生成一个个token,从结果看std,::,cout,a等符号都被识别出来。左侧是token的类型,比如identifier标识符,semi分号,eof是文件末尾。右侧记录了每个符号在源码的中行号列号。

    3.语法分析

    clang++ -fmodules -fsyntax-only -Xclang -ast-dump main.cpp
    
    • 1

    4.语义分析

    clang++ -S -emit-llvm main.cpp
    
    • 1

    当前目录会生成main.ll语法分析文件

    5.汇编文件

    clang++ -S main.cpp
    
    • 1

    当前目录会生成main.s的汇编文件

    6.生成目标文件

    clang++ -c main.s
    
    • 1

    当前目录会生成main.o目标文件,这个文件是二进制形式的。

    7.生成可执行文件

     clang++  main.cpp -o main
    
    • 1

    当前目录生成main文件,在命令行中执行./main 即可运行程序,输出Hello world

  • 相关阅读:
    全局变量和静态变量的初始化
    Linux PAGE_ALIGN 宏定义的理解
    特定深度节点链表
    [C语言]对一段连续内存,多个结构体赋值的一种手段
    ArrayList和LinkedList的区别,以及应用场景
    FreeRTOS简单内核实现5 阻塞延时
    SQL实用功能手册
    深入浅出 MyBatis 的一级、二级缓存机制
    认识ArrayList
    系统及其存储相关
  • 原文地址:https://blog.csdn.net/u011608357/article/details/127707335