您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
业务架构设计
4月18-19日 在线直播
基于UML和EA进行系统分析设计
4月25-26日 北京+在线
AI 智能化软件测试方法与实践
5月23-24日 上海+在线
     
   
 
 订阅
LLVM 1:Clang入门
 
作者: Rogn
   次浏览      
 2025-3-4
 
编辑推荐:
文章介绍了LLVM是什么、LLVM&&Clang安装及clang简介。 希望能为大家提供一些参考或帮助。
文章来自于博客园,由火龙果Linda编辑推荐。

0.LLVM是什么

LLVM项目是可重用(reusable)、模块化(modular)的编译器以及工具链(toolchain)技术的集合,有人将其理解为“底层虚拟机(Low Level Virtual Machine)”的简称,但是官方原话为:

“The name “LLVM” itself is not an acronym; it is the full name of the project.”

意思是:LLVM不是首字母缩写,而是这整个项目的全名。

LLVM项目的发展起源于2000年伊利诺伊大学厄巴纳-香槟分校维克拉姆·艾夫(Vikram Adve)与克里斯·拉特纳(Chris Lattner)的研究,他们想要为所有静态及动态语言创造出动态的编译技术。2005年,苹果计算机雇用了克里斯·拉特纳及他的团队为苹果计算机开发应用程序系统,LLVM为现今Mac OS X及iOS开发工具的一部分。

1.LLVM&&Clang安装

官网安装教程在这里。这里简单介绍一下。

Linux环境

1.1.下载有关库

$ sudo apt-get install cmake
$ sudo apt-get install git
$ sudo apt-get install gcc
$ sudo apt-get install g++

 

注意最新的llvm-project需要>=3.14版本的cmake,apt安装的不是最新的(我的情况),需要手动编译安装

1.2.下载项目源码

$ git clone https://github.com/llvm/llvm-project.git

 

上面这个命令非常慢。通过创建一个shallow clone,可以加快速度。Shallow clone可以节约存储并加速checkout时间,使用这个命令:

$ git clone --depth=1 https://github.com/llvm/llvm-project.git

1.3.构建项目

$ cd llvm-project

创建build目录

$ mkdir build
$ cd build

利用cmake构建

$ cmake -G <generator> [options] ../llvm

常用的generator有:

Unix Makefiles — 生成和 make 兼容的并行的 makefile

Ninja — 生成一个 Ninja 编译文件,大多数 LLVM 开发者使用 Ninja

Visual Studio — 生成一个 Visual Studio 项目

Xcode — 生成一个 Xcode 项目

个人使用Unix Makefiles

常用的options有:

DCMAKE_INSTALL_PREFIX=directory ——为目录指定要在其中安装LLVM工具和库的完整路径名(默认/usr/local)。

DCMAKE_BUILD_TYPE=type ——type选项有Debug,Release,RelWithDebInfo和MinSizeRel。默认值为Debug。

DLLVM_ENABLE_ASSERTIONS=On ——启用断言检查进行编译。

DLLVM_ENABLE_PROJECTS=”…” ——要另外构建的LLVM子项目的列表,以’;’分隔。例如要构建LLVM,Clang,libcxx和libcxxabi,使用:DLLVM_INSTALL_PROJECTS="clang;libcxx;libcxxabi"

DLLVM_TARGETS_TO_BUILD=”…” ——构建针对的平台的部分项目,以’;’分隔。默认面向所有平台编译(all),指定只编译自己需要的CPU架构可以节省时间。

官方文档在这。

由于全部构建真的很耗费资源和时间,我使用的构建clang命令(可供参考):

$ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="
X86" -DLLVM_ENABLE_PROJECTS=clang -DLLVM_USE_LINKER=gold -G "Unix Makefiles" ../llvm

 

当然你如果愿意(而且设备跑得动)也可以:

$ cmake -G "Unix Makefiles" ../llvm

我2G1核的小水管只构建clang都会 "virtual memory exhausted: Cannot allocate memory"

1.4.编译

$ make [-j <core>]
$ sudo make install

 

直接make也可以,但LLVM也支持并行编译,其中core取决于核心数。如:

$ make -j 4

这两步一般会很久……甚至内存不够而终止

1.5.测试

在编译结束后尝试在命令行中使用clang:

$ clang -v

本人测试结果,,,失败,因为编译时内存不够,apt install clang不想吗

apt安装后结果如下:

root@instance-kdpxvah7:~/llvm-project/build# clang -v
clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;@m64
Selected multilib: .;@m64

编写一段C语言代码试试看(C++也可以):

//helloworld.c
#include <stdio.h>
int main() {
    printf("hello world\n");
    return 0;
}

用clang编译:

$ clang helloworld.c -o hello.out
$ ./hello.out

如果是C++代码则:

//helloworld.cpp
#include <iostream>
using namespace std;
int main() {
    cout << "hello world" << endl;
    return 0;
}

 

用clang编译(注意命令是clang++,本人刚开始只写clang提示编译错误…):

$ clang++ helloworld.cpp -o hello.out
$ ./hello.out

大功告成!

2.LLVM简介

用户文档:llvm.org/docs/LangRef.html

LLVM是基于静态单一分配的表示形式,可提供类型安全性、底层操作、灵活性,并且适配几乎所有高级语言,具有通用的代码表示。现在LLVM已经成为多个编译器和代码生成相关子项目的母项目。

The LLVM code representation is designed to be used in three different forms: as an in-memory compiler IR, as an on-disk bitcode representation (suitable for fast loading by a Just-In-Time compiler), and as a human readable assembly language representation.

其中,LLVM提供了完整编译系统的中间层,并将中间语言(Intermediate Repressentation, IR)从编译器取出并进行最优化,最优化后的IR接着被转换及链接到目标平台的汇编语言。

我们知道,传统编译器主要结构为:

Frontend:前端,词法分析、语法分析、语义分析、生成中间代码

Optimizer:优化器,进行中间代码优化

Backend:后端,生成机器码

就是编译原理课上学的那一套流程

LLVM主要结构:

也就是说,对于LLVM来说,不同的前后端使用统一的中间代码LLVM IR。如果需要支持一种新的编程语言/硬件设备,那么只需要实现一个新的前端/后端就可以了(从这里可以看出LLVM的作用),而优化截断是一个通用的阶段,针对统一的LLVM IR,都不需要对于优化阶段修改。对比GCC,其前端和后端基本耦合在一起,所以GCC支持一门新的语言或者目标平台会变得很困难。

一个更具体的例子:

Objective-C与swift都采用Clang作为编译器前端,编译器前端主要进行语法分析、语义分析、生成中间代码,在这个过程中,会进行类型检查,如果发现错误或者警告会标注出来在哪一行。

编译器后端会进行机器无关的代码优化,生成机器语言,并且进行机器相关的代码优化,根据不同的系统架构生成不同的机器码。C++,Objective-C都是编译语言。编译语言在执行的时候,必须先通过编译器生成机器码。

3.clang简介

Clang是LLVM针对C语言及其家族语言的前端(a C language family frontend for LLVM)。它的主要目标是提供一个GNU编译器套装(GCC)的替代品,支持GNU编译器大多数便已设置以及非官方语言拓展。项目包括Clang前端和Clang静态分析器。

The Clang project provides a language front-end and tooling infrastructure for languages in the C language family (C, C++, Objective C/C++, OpenCL, CUDA, and RenderScript) for the LLVM project. Both a GCC-compatible compiler driver (clang) and an MSVC-compatible compiler driver (clang-cl.exe) are provided. You can get and build the source today.

Clang项目为LLVM项目中的C语言家族提供了一个语言前端和工具基础设施。其提供了兼容GCC和MSVC的编译器驱动程序(clang和clang-cl.exe)。

官方手册:http://clang.llvm.org/docs/UsersManual.html#basicusage

针对于GCC,Clang的优点有:

占用内存小

设计清晰简单,容易理解

编译速度快

设计偏向模块化,易于集成

诊断信息可读性强

3.0.Clang(Clang++)的使用

我们先随便写一段以下代码:

//test.cpp
#include <iostream>
#include <algorithm>

using namespace std;

int a[10] = {4,2,7,5,6,1,8,9,3,0};

int main() {
    for(int i = 0; i < 10; ++i)
        cout << a[i] << (i == 9?"\n":" ");
    sort(a,a+10);
    for(int i = 0; i < 10; ++i)
        cout << a[i] << (i == 9?"\n":" ");
    return 0;
}

3.1.生成预处理文件

$ clang++ -E test.cpp -o test.i

3.2.生成汇编程序

$ clang++ -S test.i

 

3.3.生成目标文件

$ clang++ -c test.s

3.4.生成可执行文件

3.5.查看Clang编译的过程

$ clang -ccc-print-phases A.c

0.获取输入:A.c文件,C语言, A.c

1.预处理器:处理define、include等, A.i

2.编译:生成中间代码(IR), ir

3.后端:生成汇编代码, A.s

4.汇编:生成目标代码, A.o

5.链接器:链接其他动态库, A.out

3.6.词法分析

$ clang -fmodules -E -Xclang -dump-tokens A.c

如图,写一个小函数对其进行词法分析。

3.7.语法分析

$ clang -fmodules -E -Xclang -dump-tokens A.c

 

生成语法树如下:

有颜色区分还是比较美观的。

3.8.语义分析

生成LLVM IR。LLVM IR有3种表示形式(本质是等价的)

(1).text:便于阅读的文本格式,类似于汇编语言,拓展名.ll

(2).memory:内存格式

(3).bitcode:二进制格式,拓展名.bc

生成text格式:

$ clang -S -emit-llvm A.c
 

在生成LLVM IR的时候会进行优化(虽然各阶段都会优化)

clang file.c -S -emit-llvm -o - (print out unoptimized llvm code)
clang file.c -S -emit-llvm -o - -O3

LLVM IR的三种形式是等价的:

a.ll和a.bc之间可以通过llvm-as和llvm-dis命令相互转换。

至于在内存中的那种格式,我们是无法通过文件的形式得到的。

 

   
次浏览       
相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程

最新活动计划
DeepSeek在软件测试应用实践 4-12[在线]
DeepSeek大模型应用开发实践 4-19[在线]
UAF架构体系与实践 4-11[北京]
AI智能化软件测试方法与实践 5-23[上海]
基于 UML 和EA进行分析设计 4-26[北京]
业务架构设计与建模 4-18[北京]
 
 
最新文章
.NET Core 3.0 正式公布:新特性详细解读
.NET Core部署中你不了解的框架依赖与独立部署
C# event线程安全
简析 .NET Core 构成体系
C#技术漫谈之垃圾回收机制(GC)
最新课程
.Net应用开发
C#高级开发技术
.NET 架构设计与调试优化
ASP.NET Core Web 开发
ASP.Net MVC框架原理与应用开发
成功案例
航天科工集团子公司 DotNet企业级应用设计与开发
日照港集 .NET Framewor
神华信 .NET单元测试
台达电子 .NET程序设计与开发
神华信息 .NET单元测试