[emscripten] Add emsdk to DEPS for Wasm builds
This can be used (manually) to build with CMake.
It is also planned to be used (automatically) with gn.
activate-emsdk comes from here, but modifications and new code:
https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/bin/activate-emsdk
Split out from Loko's original CL, with a few updates.
https://dawn-review.googlesource.com/c/dawn/+/227136
Building with .emscripten.emsdk_original works on both Mac and Windows.
Building with the overridden .emscripten has the following caveats:
- CMake on Mac doesn't work because llvm-build is missing llvm-ranlib
(which is supposed to be a symlink to llvm-ar, but it must be invoked
with the correct executable name; adding a symlink makes it work).
- CMake (and probably gn) on Win doesn't work because llvm-build is
missing clang.exe (though this can be fixed by copying clang-cl.exe),
llvm-ar.exe, and presumably others.
- CMake (and possibly gn) on Win only works with a native Ninja install
(ninja.exe), not depot_tools (ninja.bat).
Bug: 371024051
Co-authored-by: Lokbondo Kung <lokokung@google.com>
Change-Id: I901cc814835e182f95ce73927cf151bc1ab7b07f
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/228554
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/.gitmodules b/.gitmodules
index ace6328..09cb170 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,23 +4,27 @@
gclient-condition = dawn_standalone
[submodule "third_party/clang-format/script"]
path = third_party/clang-format/script
- url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format
+ url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/clang/tools/clang-format.git
gclient-condition = dawn_standalone
[submodule "third_party/depot_tools"]
path = third_party/depot_tools
- url = https://chromium.googlesource.com/chromium/tools/depot_tools
+ url = https://chromium.googlesource.com/chromium/tools/depot_tools.git
gclient-condition = dawn_standalone
[submodule "third_party/libc++/src"]
path = third_party/libc++/src
- url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx
+ url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxx.git
gclient-condition = dawn_standalone
[submodule "third_party/libc++abi/src"]
path = third_party/libc++abi/src
- url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi
+ url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libcxxabi.git
+ gclient-condition = dawn_standalone
+[submodule "third_party/llvm-libc/src"]
+ path = third_party/llvm-libc/src
+ url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libc.git
gclient-condition = dawn_standalone
[submodule "third_party/libdrm/src"]
path = third_party/libdrm/src
- url = https://chromium.googlesource.com/chromiumos/third_party/libdrm
+ url = https://chromium.googlesource.com/chromiumos/third_party/libdrm.git
gclient-condition = dawn_standalone and host_os == "linux"
[submodule "build"]
path = build
@@ -40,7 +44,7 @@
gclient-condition = dawn_standalone
[submodule "third_party/libFuzzer/src"]
path = third_party/libFuzzer/src
- url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt/lib/fuzzer
+ url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/compiler-rt/lib/fuzzer.git
gclient-condition = dawn_standalone
[submodule "third_party/googletest"]
path = third_party/googletest
@@ -48,11 +52,11 @@
gclient-condition = dawn_standalone
[submodule "third_party/catapult"]
path = third_party/catapult
- url = https://chromium.googlesource.com/catapult
+ url = https://chromium.googlesource.com/catapult.git
gclient-condition = dawn_standalone
[submodule "third_party/google_benchmark/src"]
path = third_party/google_benchmark/src
- url = https://chromium.googlesource.com/external/github.com/google/benchmark
+ url = https://chromium.googlesource.com/external/github.com/google/benchmark.git
gclient-condition = dawn_standalone
[submodule "third_party/jinja2"]
path = third_party/jinja2
@@ -142,17 +146,21 @@
path = third_party/webgpu-cts
url = https://chromium.googlesource.com/external/github.com/gpuweb/cts
gclient-condition = build_with_chromium
+[submodule "third_party/emsdk"]
+ path = third_party/emsdk
+ url = https://github.com/emscripten-core/emsdk.git
+ gclient-condition = dawn_wasm
[submodule "third_party/node-api-headers"]
path = third_party/node-api-headers
- url = https://github.com/nodejs/node-api-headers
+ url = https://github.com/nodejs/node-api-headers.git
gclient-condition = dawn_node
[submodule "third_party/node-addon-api"]
path = third_party/node-addon-api
- url = https://github.com/nodejs/node-addon-api
+ url = https://github.com/nodejs/node-addon-api.git
gclient-condition = dawn_node
[submodule "third_party/gpuweb"]
path = third_party/gpuweb
- url = https://github.com/gpuweb/gpuweb
+ url = https://github.com/gpuweb/gpuweb.git
gclient-condition = dawn_node
[submodule "third_party/protobuf"]
path = third_party/protobuf
@@ -164,20 +172,17 @@
gclient-condition = dawn_standalone
[submodule "third_party/libprotobuf-mutator/src"]
path = third_party/libprotobuf-mutator/src
- url = https://chromium.googlesource.com/external/github.com/google/libprotobuf-mutator
+ url = https://chromium.googlesource.com/external/github.com/google/libprotobuf-mutator.git
gclient-condition = dawn_standalone
[submodule "third_party/jsoncpp"]
path = third_party/jsoncpp
- url = https://github.com/open-source-parsers/jsoncpp
+ url = https://github.com/open-source-parsers/jsoncpp.git
gclient-condition = dawn_standalone
[submodule "third_party/langsvr"]
path = third_party/langsvr
- url = https://github.com/google/langsvr
+ url = https://github.com/google/langsvr.git
gclient-condition = dawn_standalone
[submodule "third_party/partition_alloc"]
path = third_party/partition_alloc
- url = https://chromium.googlesource.com/chromium/src/base/allocator/partition_allocator
+ url = https://chromium.googlesource.com/chromium/src/base/allocator/partition_allocator.git
gclient-condition = dawn_standalone
-[submodule "third_party/llvm-libc/src"]
- path = third_party/llvm-libc/src
- url = https://chromium.googlesource.com/external/github.com/llvm/llvm-project/libc.git
diff --git a/DEPS b/DEPS
index 137bd37..3a1546f 100644
--- a/DEPS
+++ b/DEPS
@@ -16,6 +16,7 @@
'dawn_standalone': True,
'dawn_node': False, # Also fetches dependencies required for building NodeJS bindings.
+ 'dawn_wasm': False, # Also fetches dependencies required for building WebAssembly.
'dawn_cmake_version': 'version:2@3.23.3',
'dawn_cmake_win32_sha1': 'b106d66bcdc8a71ea2cdf5446091327bfdb1bcd7',
'dawn_gn_version': 'git_revision:182a6eb05d15cc76d2302f7928fdb4f645d52c53',
@@ -367,6 +368,12 @@
'condition': 'build_with_chromium',
},
+ # Dependencies required to build / run WebAssembly bindings
+ 'third_party/emsdk': {
+ 'url': '{github_git}/emscripten-core/emsdk.git@127ce42cd5f0aabe2d9b5d636041ccef7c66d165',
+ 'condition': 'dawn_wasm',
+ },
+
# Dependencies required to build / run Dawn NodeJS bindings
'third_party/node-api-headers': {
'url': '{github_git}/nodejs/node-api-headers.git@d5cfe19da8b974ca35764dd1c73b91d57cd3c4ce',
@@ -619,11 +626,11 @@
'-o', 'build/util/LASTCHANGE'],
},
- # Node binaries, when dawn_node is enabled
+ # Node binaries, when dawn_node or dawn_wasm is enabled
{
- 'name': 'node_linux64',
+ 'name': 'node_linux',
'pattern': '.',
- 'condition': 'dawn_node and host_os == "linux"',
+ 'condition': '(dawn_node or dawn_wasm) and host_os == "linux"',
'action': [ 'python3',
'third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
@@ -635,9 +642,9 @@
],
},
{
- 'name': 'node_mac',
+ 'name': 'node_mac_x64',
'pattern': '.',
- 'condition': 'dawn_node and host_os == "mac"',
+ 'condition': '(dawn_node or dawn_wasm) and host_os == "mac" and host_cpu == "x64"',
'action': [ 'python3',
'third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
@@ -651,7 +658,7 @@
{
'name': 'node_mac_arm64',
'pattern': '.',
- 'condition': 'dawn_node and host_os == "mac"',
+ 'condition': '(dawn_node or dawn_wasm) and host_os == "mac" and host_cpu == "arm64"',
'action': [ 'python3',
'third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
@@ -665,7 +672,7 @@
{
'name': 'node_win',
'pattern': '.',
- 'condition': 'dawn_node and host_os == "win"',
+ 'condition': '(dawn_node or dawn_wasm) and host_os == "win"',
'action': [ 'python3',
'third_party/depot_tools/download_from_google_storage.py',
'--no_resume',
@@ -676,6 +683,48 @@
],
},
+ # Activate emsdk for WebAssembly builds
+ {
+ 'name': 'activate_emsdk_linux',
+ 'pattern': '.',
+ 'condition': 'dawn_wasm and host_os == "linux"',
+ 'action': [ 'python3',
+ 'tools/activate-emsdk',
+ '--node', 'third_party/node/node-linux-x64/bin/node',
+ '--llvm', 'third_party/llvm-build/Release+Asserts/bin'
+ ],
+ },
+ {
+ 'name': 'activate_emsdk_mac_x64',
+ 'pattern': '.',
+ 'condition': 'dawn_wasm and host_os == "mac" and host_cpu == "x64"',
+ 'action': [ 'python3',
+ 'tools/activate-emsdk',
+ '--node', 'third_party/node/node-darwin-x64/bin/node',
+ '--llvm', 'third_party/llvm-build/Release+Asserts/bin'
+ ],
+ },
+ {
+ 'name': 'activate_emsdk_mac_arm64',
+ 'pattern': '.',
+ 'condition': 'dawn_wasm and host_os == "mac" and host_cpu == "arm64"',
+ 'action': [ 'python3',
+ 'tools/activate-emsdk',
+ '--node', 'third_party/node/node-darwin-arm64/bin/node',
+ '--llvm', 'third_party/llvm-build/Release+Asserts/bin'
+ ],
+ },
+ {
+ 'name': 'activate_emsdk_win',
+ 'pattern': '.',
+ 'condition': 'dawn_wasm and host_os == "win"',
+ 'action': [ 'python3',
+ 'tools/activate-emsdk',
+ '--node', 'third_party/node/node.exe',
+ '--llvm', 'third_party/llvm-build/Release+Asserts/bin'
+ ],
+ },
+
# Download remote exec cfg files
{
'name': 'fetch_reclient_cfgs',
diff --git a/OWNERS b/OWNERS
index 1e93f87..892baf4 100644
--- a/OWNERS
+++ b/OWNERS
@@ -27,6 +27,7 @@
per-file third_party/depot_tools=*
per-file third_party/dxc=*
per-file third_party/dxheaders=*
+per-file third_party/emsdk=*
per-file third_party/glfw=*
per-file third_party/glslang/src=*
per-file third_party/google_benchmark/src=*
diff --git a/docs/quickstart-cmake.md b/docs/quickstart-cmake.md
index 1f8f6b7..fc9513d 100644
--- a/docs/quickstart-cmake.md
+++ b/docs/quickstart-cmake.md
@@ -8,7 +8,7 @@
- A compatible platform (e.g. Windows, macOS, Linux, etc.). Most platforms are fully supported.
- A compatible C++ compiler supporting at least C++17. Most major compilers are supported.
- Git for interacting with the Dawn source code repository.
-- CMake for building your project and Dawn. Dawn supports CMake 3.13+.
+- CMake for building your project and Dawn. Dawn supports CMake 3.16+.
## Getting the Dawn Code
diff --git a/scripts/standalone-with-wasm.gclient b/scripts/standalone-with-wasm.gclient
new file mode 100644
index 0000000..47976e1
--- /dev/null
+++ b/scripts/standalone-with-wasm.gclient
@@ -0,0 +1,13 @@
+# Copy this file to <dawn clone dir>/.gclient to bootstrap gclient in a
+# standalone checkout of Dawn for building emdawnwebgpu using emsdk.
+
+solutions = [
+ { "name" : ".",
+ "url" : "https://dawn.googlesource.com/dawn",
+ "deps_file" : "DEPS",
+ "managed" : False,
+ "custom_vars" : {
+ "dawn_wasm" : True,
+ }
+ },
+]
diff --git a/third_party/emsdk b/third_party/emsdk
new file mode 160000
index 0000000..127ce42
--- /dev/null
+++ b/third_party/emsdk
@@ -0,0 +1 @@
+Subproject commit 127ce42cd5f0aabe2d9b5d636041ccef7c66d165
diff --git a/tools/activate-emsdk b/tools/activate-emsdk
new file mode 100644
index 0000000..3d1b927
--- /dev/null
+++ b/tools/activate-emsdk
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+# Copyright 2025 Google LLC
+#
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import argparse
+import os
+import subprocess
+import sys
+import sysconfig
+import textwrap
+
+EMSDK_ROOT = os.path.join('third_party', 'emsdk')
+
+EMSDK_PATH = os.path.join(EMSDK_ROOT, 'emsdk.py')
+EMSDK_CONFIG_PATH = os.path.join(EMSDK_ROOT, '.emscripten')
+
+EMSDK_VERSION = '4.0.3'
+
+def main(args):
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--node', help='Path to nodejs binary.')
+ parser.add_argument('--llvm', help='Path to LLVM binaries.')
+ options = parser.parse_args();
+
+ # Install and activate the default dependencies for emsdk.
+ try:
+ subprocess.check_call([sys.executable, EMSDK_PATH, 'install', EMSDK_VERSION])
+ except subprocess.CalledProcessError:
+ print ('Failed to install emsdk')
+ return 1
+ try:
+ subprocess.check_call([sys.executable, EMSDK_PATH, 'activate', EMSDK_VERSION])
+ except subprocess.CalledProcessError:
+ print ('Failed to activate emsdk')
+ return 1
+
+ # Back up the .emscripten file generated by emsdk.
+ os.replace(EMSDK_CONFIG_PATH, EMSDK_CONFIG_PATH + ".emsdk_original")
+ # Override the default generated .emscripten file for certain binaries.
+ em_config = textwrap.dedent(f"""\
+ import os
+ emsdk_path = os.path.dirname(os.getenv('EM_CONFIG')).replace('\\\\', '/')
+ NODE_JS = emsdk_path + '/../../{options.node}'
+ LLVM_ROOT = emsdk_path + '/../../{options.llvm}'
+ BINARYEN_ROOT = emsdk_path + '/upstream'
+ EMSCRIPTEN_ROOT = emsdk_path + '/upstream/emscripten'
+ """)
+ with open(EMSDK_CONFIG_PATH, 'w') as f:
+ f.write(em_config)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))