owned this note
owned this note
Published
Linked with GitHub
# Add Emscripten to Bazel toolchain
:::info
The expected outcome is to run
```
$ bazel build --config=asmjs //target
````
:::
1. 在 workspace directory 建立 `.bazelrc` 檔案以使用 `--config` flag,`.bazelrc` 內容如下:
```
# Use custom-configured c++ toolchain.
build:asmjs --crosstool_top=//toolchain:emscripten
# Use --cpu as a differentiator.
build:asmjs --cpu=asmjs
# Use the default Bazel C++ toolchain to build the tools used during the
# build.
build:asmjs --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
```
2. 在 workspace directory 創建 `toolchain` 資料夾,並在 `toolchain` 資料夾中建立 3 個檔案:
- `BUILD` ,內容如下:
```
package(default_visibility = ["//visibility:public"])
load(":cc_toolchain_config.bzl", "cc_toolchain_config")
cc_toolchain_config(name = "asmjs_toolchain_config")
cc_toolchain_suite(
name = "emscripten",
toolchains = {
"asmjs": ":asmjs_toolchain",
},
)
filegroup(
name = "all",
srcs = [
"emcc.sh",
":emscripten_cache_content",
"@emscripten_clang//:all",
"@emscripten_toolchain//:all",
],
)
filegroup(
name = "emscripten_cache_content",
srcs = glob(["emscripten_cache/**/*"]),
)
cc_toolchain(
name = "asmjs_toolchain",
all_files = ":all",
compiler_files = ":all",
#cpu = "asmjs",
dwp_files = ":empty",
linker_files = ":all",
objcopy_files = ":empty",
strip_files = ":empty",
supports_param_files = 0,
toolchain_config = ":asmjs_toolchain_config",
toolchain_identifier = "asmjs-toolchain",
)
```
- `cc_toolchain_config.bzl` ,內容如下:
```
load(
"@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
"feature",
"flag_group",
"flag_set",
"tool_path",
)
load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
def _impl(ctx):
tool_paths = [
tool_path(
name = "gcc",
path = "emcc.sh",
),
tool_path(
name = "ld",
path = "emcc.sh",
),
tool_path(
name = "ar",
path = "/bin/false",
),
tool_path(
name = "cpp",
path = "/bin/false",
),
tool_path(
name = "gcov",
path = "/bin/false",
),
tool_path(
name = "nm",
path = "/bin/false",
),
tool_path(
name = "objdump",
path = "/bin/false",
),
tool_path(
name = "strip",
path = "/bin/false",
),
]
toolchain_include_directories_feature = feature(
name = "toolchain_include_directories",
# requires = [with_feature_set(features = ["dbg"])],
enabled = True,
flag_sets = [
flag_set(
actions = [
ACTION_NAMES.assemble,
ACTION_NAMES.preprocess_assemble,
ACTION_NAMES.linkstamp_compile,
ACTION_NAMES.c_compile,
ACTION_NAMES.cpp_compile,
ACTION_NAMES.cpp_header_parsing,
ACTION_NAMES.cpp_module_compile,
ACTION_NAMES.cpp_module_codegen,
ACTION_NAMES.lto_backend,
ACTION_NAMES.clif_match,
],
flag_groups = [
flag_group(
flags = [
"-isystem",
"external/emscripten_toolchain/system/include/libcxx",
"-isystem",
"external/emscripten_toolchain/system/include/libc",
"-ONLY_MY_CODE=1",
],
),
],
),
],
)
return cc_common.create_cc_toolchain_config_info(
ctx = ctx,
toolchain_identifier = "asmjs-toolchain",
host_system_name = "i686-unknown-linux-gnu",
target_system_name = "asmjs-unknown-emscripten",
target_cpu = "asmjs",
target_libc = "unknown",
compiler = "emscripten",
abi_version = "unknown",
abi_libc_version = "unknown",
tool_paths = tool_paths,
features = [toolchain_include_directories_feature],
)
cc_toolchain_config = rule(
attrs = {},
provides = [CcToolchainConfigInfo],
implementation = _impl,
)
```
- `emcc.sh` ,內容如下:
```
#!/bin/bash
set -euo pipefail
export LLVM_ROOT='external/emscripten_clang'
export EMSCRIPTEN_NATIVE_OPTIMIZER='external/emscripten_clang/optimizer'
export BINARYEN_ROOT='external/emscripten_clang/'
export NODE_JS=''
export EMSCRIPTEN_ROOT='external/emscripten_toolchain'
export SPIDERMONKEY_ENGINE=''
export EM_EXCLUSIVE_CACHE_ACCESS=1
export EMCC_SKIP_SANITY_CHECK=1
export EMCC_WASM_BACKEND=0
export EMCC_DEBUG=1
mkdir -p "tmp/emscripten_cache"
export EM_CACHE="tmp/emscripten_cache"
export TEMP_DIR="tmp"
# Prepare the cache content so emscripten doesn't keep rebuilding it
cp -r toolchain/emscripten_cache/* tmp/emscripten_cache
# Run emscripten to compile and link
python external/emscripten_toolchain/emcc.py "$@"
# Remove the first line of .d file
find . -name "*.d" -exec sed -i '2d' {} \;
```
3. 回到 workspace directory ,將下方內容增添至 `WORKSPACE`
```
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = 'emscripten_toolchain',
url = 'https://github.com/kripken/emscripten/archive/1.37.22.tar.gz',
build_file = '//:emscripten-toolchain.BUILD',
strip_prefix = "emscripten-1.37.22",
)
http_archive(
name = 'emscripten_clang',
url = 'https://s3.amazonaws.com/mozilla-games/emscripten/packages/llvm/tag/linux_64bit/emscripten-llvm-e1.37.22.tar.g
build_file = '//:emscripten-clang.BUILD',
strip_prefix = "emscripten-llvm-e1.37.22",
)
```
4. 確保在 workspace directory 有 `BUILD`,假如沒有的話,建立一個空的 `BUILD`
```
$ touch BUILD
```
5. 在 workspace directory 建立 `emscripten-toolchain.BUILD` , 內容如下:
```
package(default_visibility = ["//visibility:public"])
filegroup(
name = "all",
srcs = glob(["**/*"]),
)
py_binary(
name = "generate_emscripten_cache",
srcs = ["generate_emscripten_cache.py"],
data = [":transform"], # a cc_binary which we invoke at run time
deps = [],
)
```
6. 在 workspace directory 建立 `emscripten-clang.BUILD` , 內容如下:
```
package(default_visibility = ['//visibility:public'])
filegroup(
name = "all",
srcs = glob(["**/*"]),
)
```
7. 在 `toolchain` 資料夾裡創建 `emscripten_cache` 資料夾,
###### tags: `DLTcollab`