00-LLVM源码安装
  • 环境:Ubuntu20.04
  • 版本:LLVM 14.0.3

LLVM安装方法有许多,其实主要区别就在于,源码安装可以后续对LLVM进行进一步加工;若只是单纯使用LLVM,则可以直接安装。

本文只是学习并记录笔记,如有错误或不足请谅解指正,谢谢!

直接安装

wget https://apt.llvm.org/llvm.sh
chmod +x llvm.sh
sudo ./llvm.sh

llvm.sh 内包含安装llvm所需要的其他配件工具,主要通过apt-get安装的


源码编译安装(推荐)

这里使用的LLVM 版本是Github上显示的14.0.3

环境条件

  • CMake >= 3.13.4
  • GCC >= 7.1.0
  • python >= 3.6
  • zlib >= 1.2.3.4
  • GNU Make ≥ 3.79

这些工具的安装网上教程很多,这里不再记录,这里我的环境是:

cmake version 3.16.3
gcc version 9.4.0
Python 3.8.10
zlib version 1.2.12
GNU Make 4.2.1

下载LLVM源码

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

我下载的时候是LLVM 14.0.3版本,由于上面的命令较慢,也可以以浅层克隆的形式节约空间及时间(使用这个只能构建最新版本的llvm,对于只想编译的普通用户,此命令可以正常工作。但是如果后来有人成为贡献者,由于他们无法从浅克隆推送代码,因此需要将其转换为完整克隆)

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

构建LLVM及Clang

cd llvm-project
mkdir build
cd build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS="clang" ../llvm #编译配置
ninja -j8 #开始编译
ninja install

其中,第四行cmake指令的官方原型是:

cmake -G <generator> -DCMAKE_BUILD_TYPE=<type> [options] ../llvm

这里的参数含义分别是:

  • **-G **:一些常见的构建系统生成器包括
    • Ninja — 用于生成Ninja 构建文件(官方文档言:大多数 llvm 开发人员使用这个)
    • Unix Makefiles — 用于生成与 make 兼容的并行 makefile
    • Visual Studio — 用于生成 Visual Studio 项目和解决方案
    • Xcode — 用于生成 Xcode 项目
    在没有-G参数时,默认是使用的make命令
  • -DCMAKE_BUILD_TYPE:默认情况下llvm编译的是debug版本,在编译release版本的时候需要明确指定编译的类型
  • 其他一些选项[options]包括:
    • **DLLVM_ENABLE_PROJECTS=’…’**:在编译的时候,会默认只编译llvm的基础库,使用此命令,指定要另外构建的 LLVM 子项目。可以包括以下任何一种:clang、clang-tools-extra、lldb、compiler-rt、lld、polly、cross-project-tests
    • DCMAKE_INSTALL_PREFIX=directory:指定要安装 LLVM 工具和库的位置的完整路径名(默认值是/usr/local
    • DLLVM_ENABLE_ASSERTIONS=On:在启用断言检查的情况下编译(Debug 构建默认为 Yes,所有其他构建类型默认为 No)

执行完最后的ninja install指令,编译安装完后,将build下的bin文件夹添加到环境变量path下

查看版本:(这里不明白为什么显示15.0.0版本,github上却是14.0.3)

$ llvm-as --version
LLVM (http://llvm.org/):
LLVM version 15.0.0git
Optimized build.
Default target: x86_64-unknown-linux-gnu
Host CPU: tigerlake

测试:

#include<stdio.h>
int main(int argc,char** argv)
{
switch(argc){
case 1:
{
printf("case 1 : argc is %d\r\n",argc);
break;
}
case 2:
{
printf("case 2 : argc is %d\r\n",argc);
break;
}
default:
printf("default :argc is %d\r\n",argc);
}
printf("OK");
}
#将llvm_test.c转换为LLVM IR
clang -emit-llvm -S llvm_test.c -o llvm_test_1.ll

查看生成的IR:

; ModuleID = 'llvm_test.c'
source_filename = "llvm_test.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"

@.str = private unnamed_addr constant [23 x i8] c"case 1 : argc is %d\0D\0A\00", align 1
@.str.1 = private unnamed_addr constant [23 x i8] c"case 2 : argc is %d\0D\0A\00", align 1
@.str.2 = private unnamed_addr constant [25 x i8] c"default \EF\BC\9Aargc is %d\0D\0A\00", align 1
@.str.3 = private unnamed_addr constant [3 x i8] c"OK\00", align 1

; Function Attrs: noinline nounwind optnone uwtable
define dso_local i32 @main(i32 noundef %0, ptr noundef %1) #0 {
%3 = alloca i32, align 4
%4 = alloca i32, align 4
%5 = alloca ptr, align 8
store i32 0, ptr %3, align 4
store i32 %0, ptr %4, align 4
store ptr %1, ptr %5, align 8
%6 = load i32, ptr %4, align 4
switch i32 %6, label %13 [
i32 1, label %7
i32 2, label %10
]

7: ; preds = %2
%8 = load i32, ptr %4, align 4
%9 = call i32 (ptr, ...) @printf(ptr noundef @.str, i32 noundef %8)
br label %16

10: ; preds = %2
%11 = load i32, ptr %4, align 4
%12 = call i32 (ptr, ...) @printf(ptr noundef @.str.1, i32 noundef %11)
br label %16

13: ; preds = %2
%14 = load i32, ptr %4, align 4
%15 = call i32 (ptr, ...) @printf(ptr noundef @.str.2, i32 noundef %14)
br label %16

16: ; preds = %13, %10, %7
%17 = call i32 (ptr, ...) @printf(ptr noundef @.str.3)
%18 = load i32, ptr %3, align 4
ret i32 %18
}

declare i32 @printf(ptr noundef, ...) #1

attributes #0 = { noinline nounwind optnone uwtable "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 7, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project.git e300682597470ffc88b59a6187cdd763f1595d3a)"}

运行测试:

$ lli llvm_test_1.ll                               
case 1 : argc is 1
OK#

$ lli llvm_test_1.ll 1
case 2 : argc is 2
OK#

至此LLVM的源码编译安装及测试使用完成。

参考:

https://clang.llvm.org/get_started.html

https://llvm.org/docs/GettingStarted.html#checkout-llvm-from-subversion

文章作者: HotSpurzzZ
文章链接: http://example.com/2022/05/01/00-LLVM源码安装/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 HotSpurzzZ