美文网首页
Clang 与 GCC 的区别

Clang 与 GCC 的区别

作者: 跃文 | 来源:发表于2018-10-29 16:19 被阅读93次

    1. 介绍

    1.1 GCC

    GCC:GNU(Gnu's Not Unix)编译器套装(GNU Compiler Collection,GCC),指一套编程语言编译器,以GPL及LGPL许可证所发行的自由软件,也是GNU项目的关键部分,也是GNU工具链的主要组成部分之一。GCC(特别是其中的C语言编译器)也常被认为是跨平台编译器的事实标准。1985年由理查德·马修·斯托曼开始发展,现在由自由软件基金会负责维护工作。GCC原本用C开发,后来因为LLVM、Clang的崛起,它更快地将开发语言转换为C++。

    GCC支持的语言:原名为GNU C语言编译器(GNU C Compiler),因为它原本只能处理C语言。GCC在发布后很快地得到扩展,变得可处理C++。之后也变得可处理Fortran、Pascal、Objective-C、Java、Ada,Go与其他语言。
    许多操作系统,包括许多类Unix系统,如Linux及BSD家族都采用GCC作为标准编译器。苹果电脑预装的Mac OS X操作系统也采用这个编译器。
    GCC目前由世界各地不同的数个程序员小组维护。它是移植到最多中央处理器架构以及最多操作系统的编译器。由于GCC已成为GNU系统的官方编译器(包括GNU/Linux家族),它也成为编译与创建其他操作系统的主要编译器,包括BSD家族、Mac OS X、NeXTSTEP与BeOS。

    GCC通常是跨平台软件的编译器首选。有别于一般局限于特定系统与运行环境的编译器,GCC在所有平台上都使用同一个前端处理程序,产生一样的中介码,因此此中介码在各个其他平台上使用GCC编译,有很大的机会可得到正确无误的输出程序。

    GCC支持的主要处理器架构:ARM、x86、x86-64、MIPS、PowerPC等。

    GCC结构:GCC的外部接口长得像一个标准的Unix编译器。用户在命令行下键入gcc之程序名,以及一些命令参数,以便决定每个输入文件使用的个别语言编译器,并为输出代码使用适合此硬件平台的汇编语言编译器,并且选择性地运行连接器以制造可执行的程序。每个语言编译器都是独立程序,此程序可处理输入的源代码,并输出汇编语言码。全部的语言编译器都拥有共通的中介架构:一个前端解析匹配此语言的源代码,并产生一抽象语法树,以及一翻译此语法树成为GCC的寄存器转换语言的后端。编译器最优化与静态代码解析技术在此阶段应用于代码上。最后,适用于此硬件架构的汇编语言代码以杰克·戴维森与克里斯·弗雷泽发明的算法产出。

    几乎全部的GCC都由C/C++写成,除了Ada前端大部分以Ada写成。

    1.2 Clang

    Clang:是一个C、C++、Objective-C和Objective-C++编程语言的编译器前端。它采用了底层虚拟机(LLVM)作为其后端。它的目标是提供一个GNU编译器套装(GCC)的替代品。作者是克里斯·拉特纳(Chris Lattner),在苹果公司的赞助支持下进行开发,而源代码授权是使用类BSD的伊利诺伊大学厄巴纳-香槟分校开源码许可。Clang主要由C++编写。

    Clang项目包括Clang前端和Clang静态分析器等。这个软件项目在2005年由苹果电脑发起,是LLVM(Low Level Virtual Machine)编译器工具集的前端(front-end),目的是输出代码对应的抽象语法树(Abstract Syntax Tree, AST),并将代码编译成LLVM Bitcode。接着在后端(back-end)使用LLVM编译成平台相关的机器语言。

    Clang本身性能优异,其生成的AST所耗用掉的内存仅仅是GCC的20%左右。2014年1月发行的FreeBSD10.0版将Clang/LLVM作为默认编译器。

    Clang性能:测试证明Clang编译Objective-C代码时速度为GCC的3倍,还能针对用户发生的编译错误准确地给出建议。

    GCC与Clang区别:

    GCC特性:除支持C/C++/ Objective-C/Objective-C++语言外,还是支持Java/Ada/Fortran/Go等;当前的Clang的C++支持落后于GCC;支持更多平台;更流行,广泛使用,支持完备。

    Clang特性:编译速度快;内存占用小;兼容GCC;设计清晰简单、容易理解,易于扩展增强;基于库的模块化设计,易于IDE集成;出错提示更友好。

    Clang采用的license是BSD,而GCC是GPLv3。

    它们使用的宏不同:

    (1)GCC定义的宏包括:

    __GNUC__
    __GNUC_MINOR__
    __GNUC_PATCHLEVEL__
    __GNUG__
    

    (2)Clang除了支持GCC定义的宏之外还定义了:

    __clang__
    __clang_major__
    __clang_minor__
    __clang_patchlevel__
    

    2 用法

    终端输入 gcc -helpclang -help 查看
    常用:

    (1) 查看编译源文件需要的几个不同的阶段:clang -ccc-print-phases main.m
    (2) 查看oc的c实现:clang -rewrite-objc main.m
    (3) 查看操作内部命令: clang -### main.m -o main
    (4) 想看清clang的全部过程,可以先通过-E查看clang在预处理处理这步做了什么:(这个过程的处理包括宏的替换,头文件的导入,以及类似#if的处理)clang -E main.m
    (5) 预处理完成后就会进行词法分析,这里会把代码切成一个个 Token,比如大小括号,等于号还有字符串等:clang -fmodules -fsyntax-only -Xclang -dump-tokens main.m
    (6)然后是语法分析,验证语法是否正确,然后将所有节点组成抽象语法树 AST:clang -fmodules -fsyntax-only -Xclang -ast-dump main.m
    (7) 完成这些步骤后就可以开始IR中间代码的生成了,CodeGen 会负责将语法树自顶向下遍历逐步翻译成 LLVM IR,IR 是编译过程的前端的输出后端的输入:clang -S -fobjc-arc -emit-llvm main.m -o main.ll
    (8) 这里 LLVM 会去做些优化工作,在 Xcode 的编译设置里也可以设置优化级别-01,-03,-0s,还可以写些自己的 Pass: clang -O3 -S -fobjc-arc -emit-llvm main.m -o main.ll
    (9) 生成汇编 clang -S -fobjc-arc main.m -o main.s
    (10) 生成目标文件 clang -fmodules -c main.m -o main.o
    (11) 生成可执行文件 clang main.o -o main
    (12) 执行 ./main

    完整步骤:

    1. 编译信息写入辅助文件,创建文件架构 .app 文件
    2. 处理文件打包信息
    3. 执行 CocoaPod 编译前脚本,checkPods Manifest.lock
    4. 编译.m文件,使用 CompileC 和 clang 命令
    5. 链接需要的 Framework
    6. 编译 xib
    7. 拷贝 xib ,资源文件
    8. 编译 ImageAssets
    9. 处理 info.plist
    10. 执行 CocoaPod 脚本
    11. 拷贝标准库
    12. 创建 .app 文件和签名

    参考 http://www.voidcn.com/article/p-vywfvfug-xd.html

    相关文章

      网友评论

          本文标题:Clang 与 GCC 的区别

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