기본 콘텐츠로 건너뛰기

Rust를 Webassembly로 컴파일 하기

Rust를 Webassembly로 컴파일 하는 방법과 방법을 정리 해 둔다.

환경 구축이라 순차적으로 따라하면 될것 같지만, 막상 해 보면 시간도 오래 걸리고 잘 안된다. 컴파일 환경 구축 부터 Cargo 로 빌드하는 방법 까지 정리 해 둔다.

OS 선택

Rust와 Emscripten이 설치 되는 OS면 된다. Rust는 Windows, Mac, Ubuntu OS에서 실행 되는 것을 확인 했지만 Emscripten은 우분투 최신 버전과 14.04에서만 테스트를 해 보았기 때문에 최신 Ubuntu 기준으로 정리를 해둔다.

Docker Image 만들어 두면 편할 것 같았는데, 막상 컴파일 환경을 이미지로 빌드하고 보니 이미지 크기가 25GB를 넘는 문제가 있다.

Rust 설치

안정된 Rust 버전과 wasm32 타겟 설치

rustup install stable
rustup default stable
rustup target add wasm32-unknown-emscripten

Emscripten 설치

참고: 

우분투 14.04에서는 설치 중에 cmake 버전 때문에 문제가 생긴다. cmake 최신 버전을 설치 해주면 문제 없다.

최신 우분투에서는 아래 순으로 진행하면 된다. docker에서 실행 한 순서 이기 때문에 sudo로 실행하지 않는다.
apt-get update
apt-get install build-essential
apt-get install cmake
apt-get install python2.7
apt-get install nodejs
apt-get install default-jre
ln -s /usr/bin/python2.7 /usr/bin/python #링크를 생성해 주자
apt-get install curl
curl -o emsdk-portable.tar.gz https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz
tar -xvzf emsdk-portable.tar.gz
cd emsdk-portable
./emsdk update

아래에서 시간이 엄청 많이 걸린다. 

그리고 nodejsnode 문제 인것 같은데 pre-built 환경을 구성 하면서 node를 설치 했지만 중간에 node 4.1.1 버전이 설치된다. node 설치는 오래 걸리지 않으므로 무시하자.
여기 까지 진행하면 아래 메시지를 확인 가능
./emsdk install latest
Done installing tool 'emscripten-tag-1.37.9-64bit'.
Done installing SDK 'sdk-tag-1.37.9-64bit'.
...

Emscripten 최신 버전 활성화

./emsdk activate latest
source ./emsdk_env.sh

emcc 버전 체크

emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 1.37.9
clang version 4.0.0  (emscripten 1.37.9 : 1.37.9)
Target: x86_64-unknown-linux-gnu
...

1.37.0 이하라면 update

apt-get install git-core
./emsdk update
./emsdk install sdk-incoming-64bit
./emsdk activate sdk-incoming-64bit

Rust 코드 컴파일

cat hello.rs
fn main() {
  println!("hello");
}

rustc --target==wasm32-unknown-emscripten hello.rs -o hello.html

ls -al
-rw-r--r--  1 root root 816159 Apr  3 12:16 hello.asm.js
-rw-r--r--  1 root root 102727 Apr  3 12:16 hello.html
-rw-r--r--  1 root root 247359 Apr  3 12:16 hello.js
-rw-r--r--  1 root root     35 Apr  3 12:10 hello.rs
-rw-r--r--  1 root root 155653 Apr  3 12:16 hello.wasm

Cargo 로 빌드하기

프로젝트 생성

cargo new hello

Cargo.toml에 rustc 옵션 추가

[package]
name = "rust-wasm"
version = "0.1.0"
authors = ["freestrings <freestrings@gmail.com>"]

[dependencies]

[target.wasm32-unknown-emscripten]
rustflags=["-o rust-wasm.html"]
테스트 코드
cat src/main.rs
fn main() {
  println!("hello");
}

컴파일

cargo rustc --target=wasm32-unknown-emscripten
ls -al target/wasm32-unknown-emscripten/debug/deps/
...

-rw-r--r-- 1 root root 6769048 Apr  2 12:08 rust_wasm-5d7a20a47b6ec337.asm.js
-rw-r--r-- 2 root root  310906 Apr  2 12:08 rust_wasm-5d7a20a47b6ec337.js
-rw-r--r-- 1 root root 1667847 Apr  2 12:08 rust_wasm-5d7a20a47b6ec337.wasm
...

실행

아직 html 생성은 지원하지 않는다. 그래서 target/wasm32-unknown-emscripten/debug/deps/ 아래 hello.html 파일(html 파일 이름은 편한대로 해도 된다) 을 생성해야 한다. 당연히 .wasm 파일을 호출 하는 코드가 있어야 할텐데, 아래는 실행에 필요한 최소 내용이다. html에 붙여 넣어 주자.

target/wasm32-unknown-emscripten/debug/deps/ 디렉토리에 html 파일을 넣는 이유는 .js 파일에 .wasm 파일 경로가 동일 디렉토리로 되어 있기 때문.

파이어폭스 52 버전 부터는 Webassembly를 기본 지원하고 있기 때문에 최신 파이어폭스에서 결과를 확인하면 편하다.

<!doctype html>
<html lang="en-us">
  <body>
    <textarea class="emscripten" id="output" rows="20" style="width:100%"></textarea>
    <script async type="text/javascript" src="JS 파일"></script>
    <script>
    var Module = {
        print: (function() {
          var element = document.getElementById('output');
          return function(text) {
            element.innerHTML += text;
          };
        })()
      };
    </script>
  </body>
</html>

컴파일2 

프로젝트 루트 ./cargo (없으면 생성) 아래 config 파일을 생성하고 링커 속성을 지정해 준다. 링커 속성은 target에 플랫폼이 컴파일 될 때 rustc에 전달된다. 

echo "emcc \"-o\" \"test.html\" \"-02\" \$@" > ./emcc_conf

cat ./cargo/config
[target.wasm32-unknown-emscripten]
linker = "/work/emcc_conf"

참고

설치 관련해서는 https://hackernoon.com/compiling-rust-to-webassembly-guide-411066a69fde 가 정리가 가장 잘 되어 있다.

그리고 Emscripten이나 LLVM 기본 이해는  https://www.slideshare.net/Hybrid0/llvm-28276305 가 읽을 만하고, WebAssembly는 https://www.slideshare.net/gyeongseokseo/web-assembly-70493156 가 읽을 만하다. 

댓글

댓글 쓰기