如何使用LLVM将C语言编译为WASM

Posted 跨链技术践行者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用LLVM将C语言编译为WASM相关的知识,希望对你有一定的参考价值。

LLVM 在10之后都支持了wasm,但是这是一个实验性的功能,默认是不打开的,另外,在windows上,llvm是不带LLVM静态编译器的,也就是llc,但是Linux倒是自带了llvm的llc,但是编译成wasm也是不会默认开启的。这需要我们自己去手动开启。何谓手动开启,那当然是你自己编译一遍了.

编译完成后,才能尝鲜.

推荐在电脑查看此文章

(本文假设你的机子上装好了msys64 或者是MINGW,python或者Anaconda)

第一步:下载LLVM源码
LLVM的源码你可以在github的LLVM镜像仓库找到,又或者你可以在国内的码云上下载,对于国内用户来说gitee是比较快的。还有一种方式,那就是到官网上下载。

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

gitee mirror: https://gitee.com/mirrors/LLVM

我们需要编译的是llvm源码下的llvm文件夹中的源码,所以需要把llvm的源码下下来。

图中所指的文件夹下的源码就是我们需要的
或者你可以在LLVM的官网去下载打包好的源码

箭头指向的链接就是我们需要的源码
https://clang.llvm.org/get_started.html,这里也有相关项目编译的教程

然后就可以开始编译了。

第二步,编译LLVM
LLVM使用的构建工具是cmake,所以只需要一些简单的构建命令就行了

比如cmake常用的

mkdir build && cd build && cmake ../

但是,这次我们构建有点不一样,我们需要给cmake一些参数,其中关键的就是


--DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly

编译的命令如下


实际的编译命令
@set "SOURCE_DIR=%~dp0..\\llvm"

@set "CLANG=clang"

@set "gcC_C_COMPILER=gcc.exe"

@set "gcC_CXX_COMPILER=g++.exe"

@set "C_COMPILER=E:\\Programming\\msys64\\mingw64\\bin\\%CLANG%.exe"

@set "CXX_COMPILER=E:\\Programming\\msys64\\mingw64\\bin\\%CLANG%++.exe"

@set "BUILD_TYPE=Release"

@set "BUILD_EXPORT_COMMANDS=TRUE"

@set "GENERATER_STYLE=Unix Makefiles"

@set "TARGETS_TO_BUILD=WebAssembly"

@cmake -S=%SOURCE_DIR% -DCMAKE_EXPORT_COMPILE_COMMANDS=%BUILD_EXPORT_COMMANDS% --DCMAKE_C_COMPILER=%C_COMPILER% -DCMAKE_CXX_COMPILER=%CXX_COMPILER% --DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=%TARGETS_TO_BUILD% ../llvm

这个是bat(批处理文件)用来编译的命令 两个百分号之间的是定义好的变量,set 命令是在申明变量 @是表示当前的这个命令不在控制台显示

@set "BUILD_TYPE=Release" 此条命令就是定义了一个名叫BUILD_TYPE的变量,它的值是Release

我比较推荐使用vscode进行编译,界面化,而且门槛比较低

使用VSCODE编译
如果你的电脑装好了vscode,并且安装了cmake插件的话,你可以直接在配置里面添加这个参数


打开配置项

选择配置过程中传递给cmake的参数
参数也就是我上面说过的 --DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly

把颜色标出的这段参数拷贝后选择添加项,复制到那个输入框中,确认就行了。

然后就是等待编译完成了。

在编译完成后把llc添加到环境变量当中,完成后在终端(cmd或是其他命令行工具)输入llc --version 将会出现以下信息

LLVM (http://llvm.org/):
  LLVM version 11.0.0
  Optimized build with assertions.
  Default target: x86_64-w64-windows-gnu
  Host CPU: skylake

  Registered Targets:
    aarch64    - AArch64 (little endian)
    aarch64_32 - AArch64 (little endian ILP32)
    aarch64_be - AArch64 (big endian)
    amdgcn     - AMD gcN GPUs
    arm        - ARM
    arm64      - ARM64 (little endian)
    arm64_32   - ARM64 (little endian ILP32)
    armeb      - ARM (big endian)
    avr        - Atmel AVR Microcontroller
    bpf        - BPF (host endian)
    bpfeb      - BPF (big endian)
    bpfel      - BPF (little endian)
    hexagon    - Hexagon
    lanai      - Lanai
    mips       - MIPS (32-bit big endian)
    mips64     - MIPS (64-bit big endian)
    mips64el   - MIPS (64-bit little endian)
    mipsel     - MIPS (32-bit little endian)
    msp430     - MSP430 [experimental]
    nvptx      - NVIDIA PTX 32-bit
    nvptx64    - NVIDIA PTX 64-bit
    ppc32      - PowerPC 32
    ppc64      - PowerPC 64
    ppc64le    - PowerPC 64 LE
    r600       - AMD GPUs HD2XXX-HD6XXX
    risCV32    - 32-bit RISC-V
    risCV64    - 64-bit RISC-V
    sparc      - Sparc
    sparcel    - Sparc LE
    sparCV9    - Sparc V9
    systemz    - SystemZ
    thumb      - Thumb
    thumbeb    - Thumb (big endian)
    wasm32     - WebAssembly 32-bit
    wasm64     - WebAssembly 64-bit
    x86        - 32-bit X86: Pentium-Pro and above
    x86-64     - 64-bit X86: EM64T and AMD64
    xcore      - XCore

这当中的wasm32和wasm64就是我们需要的了

测试部分
然后创建一个测试的项目看看是否工作正常

这个是我创建的一个wasm测试的项目
创建build文件夹,如果没有的话,进入build文件夹后执行命令如下

clang -c -O3 --target=wasm32 ..\\src\\hello_wasm.c

wasm-ld --no-entry --strip-all --allow-undefined --export-all hello_wasm.o -o hello_wasm.wasm

然后就会在控制台看到WebAssemblyScript,你可以把这些代码拷贝下来复制到一个文件里保存起来。

很多Up主有时候根本察觉不到的一个视频投稿功能就使用了这个技术。用于将视频进行解码的一个有名的开源库FFmpeg,就有wasm版本的,使得我们在浏览器里面也能快速对视频音频进行解码。而B站使用正是这个库。

想要验证B站是否是真的使用wasm,可以把浏览器用F12或者Ctrl+Shift+I打开调式工具,然后点击调试器(火狐里的) 或者Source(谷歌浏览器里的),你会看到一个wasm的东西,那就是能够确认这个网站或者说这个网页使用了wasm这个技术。 

以上是关于如何使用LLVM将C语言编译为WASM的主要内容,如果未能解决你的问题,请参考以下文章

如何使 clang 编译为 llvm IR

使用 emcc 将 C++ 代码编译为 WASM 的问题

哪些语言可以编译成 WebAssembly (Wasm)? [关闭]

利用Golang玩转WebAssembly

如何在 Django 中提供 WASM 文件

如何将 C++ 文件编译为 WebAssembly?