1. WebAssembly技術介紹
WebAssembly是2015年誕生的一項新的技術,在2015年7月,Wasm首次對外公開,并正式開始設計,同年,W3C成立了Wasm社區(qū)小組(成員包括Chrome、Edge、Firefox和WebKit),致力于推動Wasm技術的早期發(fā)展。
wasm 是一個可移植、體積小、加載快并且兼容 Web 的全新格式。
WebAssembly的中文官網:webassembly.org.cn/
來至官網的介紹:
WebAssembly 是由主流瀏覽器廠商組成的 W3C 社區(qū)團體 制定的一個新的規(guī)范。
高效 WebAssembly 有一套完整的語義,實際上 wasm 是體積小且加載快的二進制格式, 其目標就是充分發(fā)揮硬件能力以達到原生執(zhí)行效率
安全 WebAssembly 運行在一個沙箱化的執(zhí)行環(huán)境中,甚至可以在現(xiàn)有的 JavaScript 虛擬機中實現(xiàn)。在web環(huán)境中,WebAssembly將會嚴格遵守同源策略以及瀏覽器安全策略。
開放 WebAssembly 設計了一個非常規(guī)整的文本格式用來、調試、測試、實驗、優(yōu)化、學習、教學或者編寫程序??梢砸赃@種文本格式在web頁面上查看wasm模塊的源碼。
標準 WebAssembly 在 web 中被設計成無版本、特性可測試、向后兼容的。WebAssembly 可以被 JavaScript 調用,進入 JavaScript 上下文,也可以像 Web API 一樣調用瀏覽器的功能。當然,WebAssembly 不僅可以運行在瀏覽器上,也可以運行在非web環(huán)境下。
由于不同的計算機 CPU 架構不同,機器碼標準有所差別,常見的架構有 x86、AMD 64、ARM,因此高級語言編譯成可執(zhí)行代碼時需要指定目標架構。
WebAssembly 抹平了不同 CPU 架構的機器碼,WebAssembly 的機器碼不能放在任何一個平臺上運行,但由于非常接近機器碼,可以被非??焖俚姆g為對應架構的機器碼。因此,WebAssembly 的運行速度和機器碼非常接近。
通過官網的介紹看出,WebAssembly技術的目的就是提高web端代碼性能,總所周知C/C++語言的運行性能一直是天花板,許多 3D 游戲,大型圖形編輯相關的工具軟件都是用 C/C++ 語言寫的,如果能把C/C++代碼搬到web端運行,那么理論上可以大大提高web端的運行效率。
要使用WebAssembly技術,需要先安裝Emscripten編譯器,這個Emscripten編譯器可以將 C/C++ 代碼編譯成 JS 代碼,但不是普通的 JS,而是一種叫做 asm.js 的 JavaScript 變體。
在WebAssembly官網有介紹如何編譯安裝Emscripten SDK,網站地址: webassembly.org.cn/getting-sta…
Emscripten的官網也有詳細介紹: emscripten.org/docs/gettin…
2. 安裝Emscripten編譯器
官網上有步驟介紹,這里再把安裝的步驟做個總結。
注: 當前是在win10 64 位環(huán)境下操作。
(1)需要先安裝python環(huán)境,推薦安裝python3.X,因為Emscripten編譯器里用到了python命令。
python環(huán)境安裝看這里:
xiaolong.blog.csdn.net/article/det…
xiaolong.blog.csdn.net/article/det…
(2)安裝Git工具,因為需要使用git命令在線從倉庫下載需要的文件。
Git工具安裝看這里:翻到Git工具安裝章節(jié)。
blog.csdn.net/xiaolong112…
(3)從GitHub倉庫下載編譯器項目文件,選擇一個英文目錄,鼠標右鍵,打開git命令行。(安裝完Git工具后會自動關關鍵鼠標右鍵)
運行下面命令進行下載,過程中需要等待一段時間。
git clone https://github.com/emscripten-core/emsdk.git
復制代碼
下載成功后,當前目錄下會出現(xiàn)一個emsdk目錄。
(4)在當前目錄下的文件夾地址欄里輸入cmd,按下回車,快速打開cmd命令終端。
輸入命令進入到emdk目錄下。
cd emsdk
復制代碼
(5)安裝最新的SDK并激活,在當前命令行繼續(xù)輸入命令。 注: 安裝要一點時間,需要耐心等待,具體速度看網絡情況。
emsdk install latest
emsdk activate latest --permanent
復制代碼
完成輸出的過程:
C:\Qt\emsdk>emsdk install latest
Installing SDK 'sdk-releases-upstream-37fc7647c754ac9a28ad588c143b82286de0ef71-64bit'..
Skipped installing node-12.18.1-64bit, already installed.
Skipped installing python-3.7.4-pywin32-64bit, already installed.
Skipped installing java-8.152-64bit, already installed.
Installing tool 'releases-upstream-37fc7647c754ac9a28ad588c143b82286de0ef71-64bit'..
Downloading: C:/Qt/emsdk/zips/37fc7647c754ac9a28ad588c143b82286de0ef71-wasm-binaries.zip from https://storage.googleapis.com/webassembly/emscripten-releases-builds/win/37fc7647c754ac9a28ad588c143b82286de0ef71/wasm-binaries.zip, 476624087 Bytes
Unpacking 'C:/Qt/emsdk/zips/37fc7647c754ac9a28ad588c143b82286de0ef71-wasm-binaries.zip' to 'C:/Qt/emsdk/upstream'
Done installing tool 'releases-upstream-37fc7647c754ac9a28ad588c143b82286de0ef71-64bit'.
Running post-install step: npm ci ...
Running post-install step: npm install google-closure-compiler-windows
Done running: npm ci
Done installing SDK 'sdk-releases-upstream-37fc7647c754ac9a28ad588c143b82286de0ef71-64bit'.
?
C:\Qt\emsdk>emsdk activate latest --permanent
Registering active Emscripten environment permanently
?
Setting the following tools as active:
node-12.18.1-64bit
python-3.7.4-pywin32-64bit
java-8.152-64bit
releases-upstream-37fc7647c754ac9a28ad588c143b82286de0ef71-64bit
?
Setting environment variables:
PATH = C:\Qt\emsdk;C:\Qt\emsdk\node\12.18.1_64bit\bin;C:\Qt\emsdk\python\3.7.4-pywin32_64bit;C:\Qt\emsdk\java\8.152_64bit\bin;C:\Qt\emsdk\upstream\emscripten;C:\Users\11266\AppData\Local\Programs\Python\Python38-32\Scripts;C:\Users\11266\AppData\Local\Programs\Python\Python38-32;%USERPROFILE%\AppData\Local\Microsoft\WindowsApps;C:\Users\11266\AppData\Local\Programs\Microsoft VS Code\bin;C:\MinGW\i686-8.1.0-release-posix-dwarf-rt_v6-rev0\mingw32\bin;C:\OpenCV_3.4.7\OpenCV-MinGW-Build-OpenCV-3.4.7\x86\mingw\bin;%USERPROFILE%.dotnet\tools;C:\FFMPEG\ffmpeg_x86_4.2.2\bin;C:\FFMPEG\ffmpeg_x86_x64_3.3.2\bin;C:\Users\11266\AppData\Roaming\npm
Global environment variables up to date
復制代碼
(6)在命令行輸入em++ -v測試編譯器是否安裝成功。
出現(xiàn)以下提示,表示編譯器已經安裝成功。
C:\Qt\emsdk>emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.10
clang version 12.0.0 (Cswircachegitchromium.googlesource.com-external-github.com-llvm-llvm--project 445289aa63e1b82b9eea6497fb2d0443813a9d4e)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:/Qt/emsdk/upstream/bin
shared:INFO: (Emscripten: Running sanity checks)
?
C:\Qt\emsdk>em++ -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.10
clang version 12.0.0 (Cswircachegitchromium.googlesource.com-external-github.com-llvm-llvm--project 445289aa63e1b82b9eea6497fb2d0443813a9d4e)
Target: x86_64-pc-windows-msvc
Thread model: posix
InstalledDir: C:/Qt/emsdk/upstream/bin
shared:INFO: (Emscripten: Running sanity checks)
?
C:\Qt\emsdk>
復制代碼
(7)這時可以先關閉當前終端,再重新開一個新終端,運行emcc或者em++查看幫助,會出現(xiàn)以下提示。
C:\Users\11266>cd /d D:\linux-share-dir\tmp\WebAssembly_TestCode
?
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc -help
?
==============================================================================
Welcome to Emscripten!
?
This is the first time any of the Emscripten tools has been run.
?
A settings file has been copied to ~/.emscripten, at absolute path: C:\Users\11266.emscripten
?
It contains our best guesses for the important paths, which are:
?
LLVM_ROOT = /usr/bin
NODE_JS = C:\Program Files\nodejs\node.exe
EMSCRIPTEN_ROOT = C:\Qt\emsdk\upstream\emscripten
?
Please edit the file if any of those are incorrect.
?
This command will now exit. When you are done editing those paths, re-run it.
==============================================================================
復制代碼
打開當前系統(tǒng)的用戶目錄,會看到一個.emscripten文件。這個文件里存放了編譯器需要的環(huán)境變量和路徑。
如果后續(xù)運行emcc或者em++命令編譯程序時報錯,例如:
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.cpp -Os -s WASM=1 -s SIDE_MODULE=1 -o hello.wasm
shared:ERROR: BINARYEN_ROOT is set to empty value in C:\Users\11266/.emscripten
?
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.cpp -Os -s WASM=1 -s SIDE_MODULE=1 -o hello.wasm
cache:INFO: generating system asset: is_vanilla.txt... (this will be cached in "C:\Users\11266.emscripten_cache\is_vanilla.txt" for subsequent builds)
shared:ERROR: llc executable not found at `C:\Users\11266/upstream/bin\llc.exe`
復制代碼
解決辦法:將.emscripten文件里的所有路徑改成絕對路徑。
例如:原來的路徑
import os
emsdk_path = os.path.dirname(os.environ.get('EM_CONFIG')).replace('\', '/')
NODE_JS = emsdk_path + '/node/12.18.1_64bit/bin/node.exe'
PYTHON = emsdk_path + '/python/3.7.4-pywin32_64bit/python.exe'
JAVA = emsdk_path + '/java/8.152_64bit/bin/java.exe'
LLVM_ROOT = emsdk_path + '/upstream/bin'
BINARYEN_ROOT = emsdk_path + '/upstream'
EMSCRIPTEN_ROOT = emsdk_path + '/upstream/emscripten'
TEMP_DIR = emsdk_path + '/tmp'
COMPILER_ENGINE = NODE_JS
JS_ENGINES = [NODE_JS]
復制代碼
修改后的配置文件路徑:
import os
NODE_JS = 'C:/Qt/emsdk/node/12.18.1_64bit/bin/node.exe'
PYTHON = 'C:/Qt/emsdk/python/3.7.4-pywin32_64bit/python.exe'
JAVA = 'C:/Qt/emsdk/java/8.152_64bit/bin/java.exe'
LLVM_ROOT = 'C:/Qt/emsdk/upstream/bin'
BINARYEN_ROOT = 'C:/Qt/emsdk/upstream'
EMSCRIPTEN_ROOT = 'C:/Qt/emsdk/upstream/emscripten'
TEMP_DIR = 'C:/Qt/emsdk/tmp'
COMPILER_ENGINE = NODE_JS
JS_ENGINES = [NODE_JS]
復制代碼
再重新運行即可:
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.cpp -Os -s WASM=1 -s SIDE_MODULE=1 -o hello.wasm
cache:INFO: generating system asset: generated_struct_info.json... (this will be cached in "C:\Users\11266.emscripten_cache\wasm-obj-pic\generated_struct_info.json" for subsequent builds)
cache:INFO: - ok
復制代碼
3. 編寫C/C++代碼瀏覽器運行測試
(1)編寫一個簡單的C/C++代碼
#include
int main()
{
printf("Hello World! \n");
printf("WebAssembly 牛逼!\n");
return 0;
}
復制代碼
(2)使用emcc編譯編譯
D:>cd /d D:\linux-share-dir\tmp\WebAssembly_TestCode
?
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.cpp -s WASM=1 -O3 -o hello-emcc.js
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.cpp -s WASM=1 -O3 -o hello-emcc.html
復制代碼
編譯成功之后,在目錄下會生成:js,html,wasm 等3個文件。
(3)開一個HTTP服務器,測試網頁運行效果
在當前編譯目錄,使用python開一個HTTP服務器。
D:\linux-share-dir\tmp\WebAssembly_TestCode>python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
復制代碼
打開Edge瀏覽器(win10自帶的瀏覽器),輸入http://127.0.1:8000。
選擇hello-emcc.html文件打開。下面是運行效果。
也可以使用 emrun 命令來創(chuàng)建一個 http 協(xié)議的 web server 展示編譯后的文件,和前面python命令的功能類似。
$ emrun --no_browser --port 8080
復制代碼
4. 編寫C/C++代碼給前端調用測試
(1)編寫一個函數(shù),用于測試調用
#include
#include
?
int func_square(int x)
{
return x * x;
}
?
int func_sum(int x, int y)
{
return x + y;
}
?
char* func_string(char* str)
{
return str;
}
復制代碼
(2)編譯成wasm文件
D:\linux-share-dir\tmp\WebAssembly_TestCode>emcc hello.c -Os -s WASM=1 -s SIDE_MODULE=1 -o hello.wasm
復制代碼
(3)編寫一個js文件。名稱為: loader.js
function loadWebAssembly(filename, imports = {}) {
return fetch(filename)
.then(response => response.arrayBuffer())
.then(buffer => {
imports.env = imports.env || {}
Object.assign(imports.env, {
memoryBase: 0,
tableBase: 0,
__memory_base: 0,
__table_base: 0,
memory: new WebAssembly.Memory({ initial: 256, maximum: 256 }),
table: new WebAssembly.Table({ initial: 0, maximum: 0, element: 'anyfunc' })
})
return WebAssembly.instantiate(buffer, imports)
})
.then(result => result.instance )
}
?
function loadJS (url, imports = {}) {
return fetch(url)
.then(response => response.text())
.then(code => new Function('imports', `return (${code})()`))
.then(factory => ({ exports: factory(imports) }))
}
復制代碼
(4)編寫一個HTML文件調用函數(shù)接口 : 例如: index.html
?
Compile C to WebAssembly
The test result can be found in console.
?
復制代碼
(5)啟動http服務器,訪問測試。
python -m http.server
復制代碼
打開谷歌瀏覽器輸入地址訪問: http://127.0.0.1:8000/index.html
運行后,按下F12,查看控制臺的輸出。
注意:如果要反復修改HTML文件測試結果,瀏覽器最好打開無痕模式進行測試。
在瀏覽器里可以看到wasm轉成wast文本格式的代碼,從代碼里可以看到導出的函數(shù)。
5. webassembly在線調試工具
地址:wasdk.github.io/WasmFiddle/
6. wasm2wast工具安裝
wasm2wast這個工具是將 WebAssembly 二進制轉換為 S-expressions。他是命令行工具,一個二進制文件作為輸入,輸出一個包含可以讀文本的文件。開發(fā)者可以編輯文本文件,然后再將其轉換為二進制文件,比如優(yōu)化算法、追蹤問題、插入調試語句等等。
地址: github.com/WebAssembly…
用法示例:
wast2wasm demo.wast -o demo.wasm
?
wasm2wast demo.wasm -o demo.wast
復制代碼
7. emsdk常用命令介紹
(1)emcc -v 顯示安裝的版本號
?
(2)em++ -v 顯示安裝的版本號
?
(3)emsdk update 更新emssk庫到最新版
?
(4)emsdk list --old 查看emsdk歷史版本號列表
?
(5)emsdk list --old > sdklist.txt 將歷史版本號寫入到sdklist.txt文件中
?
(6)emsdk install <版本號> 安裝對應版本號的sdk tool
例如: emsdk install 1.39.7
(7)emsdk install latest 安裝最新版本號的std tool
?
(8)emsdk activate <版本號> 激活對應版本號的std tool ,也就是設置當前使用的版本
例如:emsdk activate --embedded 1.39.7 --permanent
?
?
(9)emsdk uninstall <版本號> 卸載對應版本號的sdk tool
?
?
(10)emsdk help 或者 emsdk --help 查看幫助
復制代碼
8. 總結
審核編輯:湯梓紅
-
Web
+關注
關注
2文章
1262瀏覽量
69440 -
編譯器
+關注
關注
1文章
1623瀏覽量
49108 -
Win10
+關注
關注
2文章
710瀏覽量
39980
發(fā)布評論請先 登錄
相關推薦
評論