Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 20 additions & 15 deletions backends/webgpu/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,27 @@ target_include_directories(

target_link_libraries(webgpu_backend PRIVATE vulkan_schema executorch_core)

# Native WebGPU backend: Dawn (Tint) + SwiftShader; deps script sets Dawn_DIR.
# Native-only: browser/Emscripten builds use the system webgpu.h and never reach
# this find_package (root CMake gates it via EXECUTORCH_BUILD_WEBGPU).
# dawn::webgpu_dawn's link interface references Threads::Threads.
find_package(Threads REQUIRED)
find_package(Dawn REQUIRED)
set(WEBGPU_GPU_LIB dawn::webgpu_dawn)
target_link_libraries(webgpu_backend PUBLIC ${WEBGPU_GPU_LIB})

if(APPLE)
target_link_libraries(
webgpu_backend PRIVATE "-framework Metal" "-framework QuartzCore"
"-framework CoreGraphics" "-framework Foundation"
)
# WASM gets its WebGPU implementation from emdawnwebgpu at executable link time.
# Native builds link Dawn (Tint) and the platform GPU libraries.
if(EMSCRIPTEN)
target_compile_options(webgpu_backend PUBLIC "--use-port=emdawnwebgpu")
# --use-port is also required at link time: the link step pulls in the port's
# headers, JS glue, and libraries for consumers that link webgpu_backend.
target_link_options(webgpu_backend PUBLIC "--use-port=emdawnwebgpu")
else()
target_link_libraries(webgpu_backend PRIVATE dl m pthread)
find_package(Threads REQUIRED)
find_package(Dawn REQUIRED)
set(WEBGPU_GPU_LIB dawn::webgpu_dawn)
target_link_libraries(webgpu_backend PUBLIC ${WEBGPU_GPU_LIB})

if(APPLE)
target_link_libraries(
webgpu_backend PRIVATE "-framework Metal" "-framework QuartzCore"
"-framework CoreGraphics" "-framework Foundation"
)
else()
target_link_libraries(webgpu_backend PRIVATE dl m pthread)
endif()
endif()

target_compile_options(webgpu_backend PRIVATE -fexceptions)
Expand Down
89 changes: 89 additions & 0 deletions backends/webgpu/test/test_cmake_configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright (c) Meta Platforms, Inc. and affiliates.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

import pathlib
import re
import unittest


def _conditional_branches(source: str, condition: str) -> tuple[str, str]:
lines = source.splitlines()
condition_pattern = re.compile(
rf"^\s*if\s*\(\s*{re.escape(condition)}\s*\)\s*$",
re.IGNORECASE,
)
command_pattern = re.compile(r"^\s*([A-Za-z_][A-Za-z0-9_]*)\s*\(")
start = next(
(index for index, line in enumerate(lines) if condition_pattern.match(line)),
None,
)
if start is None:
raise AssertionError(f"if({condition}) branch not found")

depth = 1
else_index = None
for index in range(start + 1, len(lines)):
match = command_pattern.match(lines[index])
if match is None:
continue
command = match.group(1).lower()
if command == "if":
depth += 1
elif command == "endif":
depth -= 1
if depth == 0:
if else_index is None:
raise AssertionError(f"if({condition}) has no else() branch")
return (
"\n".join(lines[start + 1 : else_index]),
"\n".join(lines[else_index + 1 : index]),
)
elif command == "else" and depth == 1:
if else_index is not None:
raise AssertionError(f"if({condition}) has multiple else() branches")
else_index = index
raise AssertionError(f"if({condition}) has no matching endif()")


class TestCMakeConfiguration(unittest.TestCase):
def test_branch_parser_keeps_nested_conditionals_in_native_branch(self) -> None:
source = """
if ( EMSCRIPTEN )
wasm_command()
else()
if(APPLE)
apple_command()
else()
linux_command()
endif()
endif()
"""
wasm_branch, native_branch = _conditional_branches(source, "EMSCRIPTEN")

self.assertIn("wasm_command()", wasm_branch)
self.assertIn("apple_command()", native_branch)
self.assertIn("linux_command()", native_branch)

def test_emscripten_uses_port_instead_of_native_dawn(self) -> None:
cmake = pathlib.Path(__file__).parents[1] / "CMakeLists.txt"
wasm_branch, native_branch = _conditional_branches(
cmake.read_text(), "EMSCRIPTEN"
)
port_flag = r'"--use-port=emdawnwebgpu"'

self.assertRegex(
wasm_branch,
rf"target_compile_options\s*\(\s*webgpu_backend\s+PUBLIC\s+{port_flag}\s*\)",
)
self.assertRegex(
wasm_branch,
rf"target_link_options\s*\(\s*webgpu_backend\s+PUBLIC\s+{port_flag}\s*\)",
)
self.assertNotIn("find_package(Dawn", wasm_branch)
self.assertNotIn("--use-port=emdawnwebgpu", native_branch)
self.assertRegex(
native_branch, r"find_package\s*\(\s*Dawn\s+REQUIRED\s*\)"
)
Loading