Refine the bundling step for `webgpu_dawn`

- Build `webgpu_dawn` only when `DAWN_BUILD_MONOLITHIC_LIBRARY`
is enabled
- Turns off `DAWN_BUILD_MONOLITHIC_LIBRARY` because
tools/android already builds a different bundle.
- Link dawn_native with "-framework Foundation". This is needed for iOS.
- Export symbols from `dawn_native` and `dawn/webgpu.h` when
building monolithic shared library.
- Remove install rules for unexported static libraries.
- Provide a single `webgpu_dawn` library, C/C++ headers
and cmake config file for consumers to use `wgpu` methods.
- The exported symbols also permit instantiation of public
classes from `dawn::native` namespaces.

Change-Id: Ie8575d49366f3c333b860ce2617960067edfc404
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/195996
Commit-Queue: Jaswant Panchumarti <jaswant.panchumarti@kitware.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f99e0f9..42ecb77 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,13 +32,14 @@
 #   in case any of the generator files changes. We should also remove the CACHE "" FORCE stuff to
 #   override options in third_party dependencies.
 # - When upgrading to CMake 3.20 we can take advantage of the GENERATED property being global in
-#   DawnGenerator. We should also use the path utilities in install_if_enabled.
+#   DawnGenerator. We should also use the path utilities in dawn_install_target.
 
 project(
     Dawn
     DESCRIPTION "Dawn, a WebGPU implementation"
     LANGUAGES C CXX
     HOMEPAGE_URL "https://dawn.googlesource.com/dawn"
+    VERSION 0.0.0
 )
 enable_testing()
 
@@ -59,44 +60,6 @@
 set(DAWN_INCLUDE_DIR "${Dawn_SOURCE_DIR}/include" CACHE PATH "Directory that contains public headers for dawn")
 set(DAWN_TEMPLATE_DIR "${DAWN_GENERATOR_DIR}/templates" CACHE PATH "Directory that contains templates for generators")
 
-function (install_if_enabled target)
-    if(NOT DAWN_ENABLE_INSTALL)
-        return()
-    endif()
-
-    install(TARGETS ${target}
-        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
-        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
-        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
-    )
-
-    get_target_property(targetHeaders ${target} INTERFACE_SOURCES)
-    if (NOT targetHeaders)
-        return()
-    endif()
-
-    foreach(headerFile ${targetHeaders})
-        # Starting from CMake 3.20 there is the cmake_path command that could simplify this code.
-        # Compute the install subdirectory for the header by stripping out the path to
-        # the include / gen/include directory...
-        string(FIND "${headerFile}" "${DAWN_INCLUDE_DIR}" foundIndex)
-        if (foundIndex EQUAL 0)
-            string(LENGTH "${DAWN_INCLUDE_DIR}/" lengthToRemove)
-        endif()
-        string(FIND "${headerFile}" "${DAWN_BUILD_GEN_DIR}/include/" foundIndex)
-        if (foundIndex EQUAL 0)
-            string(LENGTH "${DAWN_BUILD_GEN_DIR}/include/" lengthToRemove)
-        endif()
-        string(SUBSTRING "${headerFile}" "${lengthToRemove}" -1 headerRelDir)
-
-        # ... then remove everything after the last /
-        string(FIND "${headerRelDir}" "/" foundIndex REVERSE)
-        string(SUBSTRING "${headerRelDir}" 0 ${foundIndex} headerRelDir)
-
-        install(FILES "${headerFile}" DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${headerRelDir})
-    endforeach()
-endfunction()
-
 ################################################################################
 # Configuration options
 ################################################################################
@@ -260,6 +223,8 @@
 
 option(DAWN_FETCH_DEPENDENCIES "Use fetch_dawn_dependencies.py as an alternative to using depot_tools" OFF)
 
+option(DAWN_BUILD_MONOLITHIC_LIBRARY "Bundle all dawn components into a single shared library." ON)
+
 # Much of the backend code is shared among desktop OpenGL and OpenGL ES
 if (${DAWN_ENABLE_DESKTOP_GL} OR ${DAWN_ENABLE_OPENGLES})
     set(DAWN_ENABLE_OPENGL ON)
@@ -269,11 +234,14 @@
     set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 endif()
 
+# Defines `CMAKE_INSTALL_*DIR` variables
+include(GNUInstallDirs)
 # The public config contains only the include paths for the Dawn headers.
 add_library(dawn_public_config INTERFACE)
 target_include_directories(dawn_public_config INTERFACE
-    "${DAWN_INCLUDE_DIR}"
-    "${DAWN_BUILD_GEN_DIR}/include"
+    "$<BUILD_INTERFACE:${DAWN_INCLUDE_DIR}>"
+    "$<BUILD_INTERFACE:${DAWN_BUILD_GEN_DIR}/include>"
+    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
 )
 
 # The internal config contains additional path but includes the dawn_public_config include paths
@@ -466,3 +434,32 @@
     COMMENT "Generating tint coverage data"
     VERBATIM)
 endif()
+
+if (DAWN_BUILD_MONOLITHIC_LIBRARY AND DAWN_ENABLE_INSTALL)
+  # This series of functions add the necessary information so that other CMake projects
+  # can use Dawn, be it from a build directory, a local install or when packaged.
+  install(EXPORT DawnTargets
+    FILE DawnTargets.cmake
+    NAMESPACE dawn::
+    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dawn")
+  export(EXPORT DawnTargets
+    FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/DawnTargets.cmake"
+      NAMESPACE dawn::
+  )
+  # Create a ConfigVersion.cmake file:
+  include(CMakePackageConfigHelpers)
+  write_basic_package_version_file(
+    "${CMAKE_CURRENT_BINARY_DIR}/DawnConfigVersion.cmake"
+    COMPATIBILITY AnyNewerVersion)
+  # Configure config file
+  configure_package_config_file("${CMAKE_CURRENT_LIST_DIR}/src/cmake/DawnConfig.cmake.in"
+    "${CMAKE_CURRENT_BINARY_DIR}/DawnConfig.cmake"
+    INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dawn"
+  )
+  # Install the fully generated config and configVersion files
+  install(FILES
+    "${CMAKE_CURRENT_BINARY_DIR}/DawnConfig.cmake"
+    "${CMAKE_CURRENT_BINARY_DIR}/DawnConfigVersion.cmake"
+    DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/Dawn"
+  )
+endif ()
diff --git a/src/cmake/DawnConfig.cmake.in b/src/cmake/DawnConfig.cmake.in
new file mode 100644
index 0000000..8bfeda5
--- /dev/null
+++ b/src/cmake/DawnConfig.cmake.in
@@ -0,0 +1,34 @@
+# Copyright 2024 The Dawn & Tint Authors
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this
+#    list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+#    this list of conditions and the following disclaimer in the documentation
+#    and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+#    contributors may be used to endorse or promote products derived from
+#    this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# This allows CMake find_package() to find all the dawn targets that were exported.
+# For a helpful explanation on this subject, please walk through the steps in the CMake tutorial.
+# 1. https://cmake.org/cmake/help/latest/guide/tutorial/Installing%20and%20Testing.html
+# 2. https://cmake.org/cmake/help/latest/guide/tutorial/Adding%20Export%20Configuration.html
+
+@PACKAGE_INIT@
+include ("${CMAKE_CURRENT_LIST_DIR}/DawnTargets.cmake")
diff --git a/src/cmake/DawnLibrary.cmake b/src/cmake/DawnLibrary.cmake
index d0df135..db93886 100644
--- a/src/cmake/DawnLibrary.cmake
+++ b/src/cmake/DawnLibrary.cmake
@@ -141,3 +141,53 @@
   endif ()
   add_library("dawn::${name}" ALIAS "${name}")
 endfunction()
+
+#[==[.rst:
+.. cmake:command:: dawn_install_target
+
+  Install a target and associated header files.
+
+  .. code-block:: cmake
+
+  dawn_install_target(<name>
+    [HEADERS                  <header>...]
+  )
+
+  * ``HEADERS``: A list of header files to install.
+#]==]
+function(dawn_install_target name)
+  cmake_parse_arguments(PARSE_ARGV 1 arg
+    ""
+    ""
+    "HEADERS")
+  if (arg_UNPARSED_ARGUMENTS)
+    message(FATAL_ERROR
+      "Unparsed arguments for dawn_install_target: "
+      "${arg_UNPARSED_ARGUMENTS}")
+  endif ()
+  install(TARGETS "${name}"
+    EXPORT DawnTargets
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+  )
+  foreach(header IN LISTS arg_HEADERS)
+    # Starting from CMake 3.20 there is the cmake_path command that could simplify this code.
+    # Compute the install subdirectory for the header by stripping out the path to
+    # the 'include' (or) 'gen/include' directory...
+    string(FIND "${header}" "${DAWN_INCLUDE_DIR}" found)
+    if (found EQUAL 0)
+      string(LENGTH "${DAWN_INCLUDE_DIR}/" deduction)
+    endif()
+    string(FIND "${header}" "${DAWN_BUILD_GEN_DIR}/include/" found)
+    if (found EQUAL 0)
+      string(LENGTH "${DAWN_BUILD_GEN_DIR}/include/" deduction)
+    endif()
+    string(SUBSTRING "${header}" "${deduction}" -1 subdir)
+
+    # ... then remove everything after the last /
+    string(FIND "${subdir}" "/" found REVERSE)
+    string(SUBSTRING "${subdir}" 0 ${found} subdir)
+    install(FILES "${header}" DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${subdir}")
+  endforeach()
+endfunction()
diff --git a/src/dawn/CMakeLists.txt b/src/dawn/CMakeLists.txt
index 51560ad..0056327 100644
--- a/src/dawn/CMakeLists.txt
+++ b/src/dawn/CMakeLists.txt
@@ -26,30 +26,6 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ###############################################################################
-# Dawn projects
-###############################################################################
-
-add_subdirectory(partition_alloc)
-add_subdirectory(common)
-add_subdirectory(platform)
-add_subdirectory(native)
-add_subdirectory(wire)
-add_subdirectory(utils)
-
-if (DAWN_BUILD_BENCHMARKS)
-    add_subdirectory(tests/benchmarks)
-endif()
-if(DAWN_USE_GLFW)
-    add_subdirectory(glfw)
-endif()
-if (DAWN_BUILD_SAMPLES)
-    add_subdirectory(samples)
-endif()
-if (DAWN_BUILD_NODE_BINDINGS)
-    add_subdirectory(node)
-endif()
-
-###############################################################################
 # Dawn headers
 ###############################################################################
 
@@ -69,8 +45,6 @@
     DEPENDS
         dawn_public_config
 )
-install_if_enabled(dawn_headers)
-
 ###############################################################################
 # Dawn C++ headers
 ###############################################################################
@@ -91,12 +65,34 @@
     DEPENDS
         dawn::dawn_headers
 )
-install_if_enabled(dawncpp_headers)
-
 add_library(dawncpp ALIAS dawncpp_headers)
 add_library(webgpu_cpp ALIAS dawncpp_headers)
 
 ###############################################################################
+# Dawn projects
+###############################################################################
+
+add_subdirectory(partition_alloc)
+add_subdirectory(common)
+add_subdirectory(platform)
+add_subdirectory(wire)
+add_subdirectory(native)
+add_subdirectory(utils)
+
+if (DAWN_BUILD_BENCHMARKS)
+  add_subdirectory(tests/benchmarks)
+endif()
+if(DAWN_USE_GLFW)
+  add_subdirectory(glfw)
+endif()
+if (DAWN_BUILD_SAMPLES)
+  add_subdirectory(samples)
+endif()
+if (DAWN_BUILD_NODE_BINDINGS)
+  add_subdirectory(node)
+endif()
+
+###############################################################################
 # libdawn_proc
 ###############################################################################
 
@@ -123,7 +119,6 @@
 if(BUILD_SHARED_LIBS)
   target_compile_definitions(dawn_proc PUBLIC "WGPU_SHARED_LIBRARY")
 endif()
-install_if_enabled(dawn_proc)
 
 ###############################################################################
 # Other generated files (upstream header, emscripten header, emscripten bits)
diff --git a/src/dawn/glfw/CMakeLists.txt b/src/dawn/glfw/CMakeLists.txt
index 4f943af..b0036b9 100644
--- a/src/dawn/glfw/CMakeLists.txt
+++ b/src/dawn/glfw/CMakeLists.txt
@@ -34,7 +34,7 @@
 set(conditional_private_depends)
 if (DAWN_ENABLE_METAL)
     list(APPEND sources "utils_metal.mm")
-    list(APPEND conditional_private_depends"-framework Metal")
+    list(APPEND conditional_private_depends "-framework Metal")
 endif ()
 
 dawn_add_library(
diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt
index 6e36756..aec51ef 100644
--- a/src/dawn/native/CMakeLists.txt
+++ b/src/dawn/native/CMakeLists.txt
@@ -189,7 +189,6 @@
     "ComputePipeline.cpp"
     "CopyTextureForBrowserHelper.cpp"
     "CreatePipelineAsyncEvent.cpp"
-    "DawnNative.cpp"
     "Device.cpp"
     "DynamicUploader.cpp"
     "EncodingContext.cpp"
@@ -318,7 +317,6 @@
     list(APPEND sources
         "d3d/BackendD3D.cpp"
         "d3d/BlobD3D.cpp"
-        "d3d/D3DBackend.cpp"
         "d3d/D3DError.cpp"
         "d3d/DeviceD3D.cpp"
         "d3d/KeyedMutex.cpp"
@@ -374,7 +372,6 @@
         "d3d11/CommandBufferD3D11.cpp"
         "d3d11/CommandRecordingContextD3D11.cpp"
         "d3d11/ComputePipelineD3D11.cpp"
-        "d3d11/D3D11Backend.cpp"
         "d3d11/DeviceD3D11.cpp"
         "d3d11/DeviceInfoD3D11.cpp"
         "d3d11/PhysicalDeviceD3D11.cpp"
@@ -447,7 +444,6 @@
         "d3d12/CommandRecordingContext.cpp"
         "d3d12/ComputePipelineD3D12.cpp"
         "d3d12/CPUDescriptorHeapAllocationD3D12.cpp"
-        "d3d12/D3D12Backend.cpp"
         "d3d12/D3D12Info.cpp"
         "d3d12/DeviceD3D12.cpp"
         "d3d12/GPUDescriptorHeapAllocationD3D12.cpp"
@@ -516,7 +512,6 @@
         "metal/CommandRecordingContext.mm"
         "metal/ComputePipelineMTL.mm"
         "metal/DeviceMTL.mm"
-        "metal/MetalBackend.mm"
         "metal/PhysicalDeviceMTL.mm"
         "metal/PipelineLayoutMTL.mm"
         "metal/QuerySetMTL.mm"
@@ -535,6 +530,7 @@
         list(APPEND conditional_private_platform_depends "-framework Cocoa")
     endif()
     list(APPEND conditional_private_platform_depends
+        "-framework Foundation"
         "-framework IOKit"
         "-framework IOSurface"
         "-framework QuartzCore"
@@ -551,7 +547,6 @@
     )
     list(APPEND sources
         "null/DeviceNull.cpp"
-        "null/NullBackend.cpp"
     )
 endif()
 
@@ -627,7 +622,6 @@
         "opengl/DisplayEGL.cpp"
         "opengl/EGLFunctions.cpp"
         "opengl/GLFormat.cpp"
-        "opengl/OpenGLBackend.cpp"
         "opengl/OpenGLFunctions.cpp"
         "opengl/OpenGLVersion.cpp"
         "opengl/PersistentPipelineStateGL.cpp"
@@ -722,7 +716,6 @@
         "vulkan/SwapChainVk.cpp"
         "vulkan/TextureVk.cpp"
         "vulkan/UtilsVulkan.cpp"
-        "vulkan/VulkanBackend.cpp"
         "vulkan/VulkanError.cpp"
         "vulkan/VulkanExtensions.cpp"
         "vulkan/VulkanFunctions.cpp"
@@ -761,22 +754,38 @@
     endif()
 endif()
 
-dawn_add_library(
-  dawn_native
-  UTILITY_TARGET dawn_internal_config
-  HEADERS
-    ${headers}
-  PRIVATE_HEADERS
-    ${private_headers}
-  SOURCES
-    ${sources}
-  DEPENDS
+set(dawn_component_srcs)
+list(APPEND dawn_component_srcs "DawnNative.cpp")
+if (DAWN_ENABLE_D3D11 OR DAWN_ENABLE_D3D12)
+    list(APPEND dawn_component_srcs "d3d/D3DBackend.cpp")
+endif()
+if (DAWN_ENABLE_D3D11)
+    list(APPEND dawn_component_srcs "d3d11/D3D11Backend.cpp")
+endif()
+if (DAWN_ENABLE_D3D12)
+    list(APPEND dawn_component_srcs "d3d12/D3D12Backend.cpp")
+endif()
+if (DAWN_ENABLE_METAL)
+    list(APPEND dawn_component_srcs "metal/MetalBackend.mm")
+endif()
+if (DAWN_ENABLE_NULL)
+    list(APPEND dawn_component_srcs "null/NullBackend.cpp")
+endif()
+if (DAWN_ENABLE_OPENGL)
+    list(APPEND dawn_component_srcs "opengl/OpenGLBackend.cpp")
+endif()
+if (DAWN_ENABLE_VULKAN)
+    list(APPEND dawn_component_srcs "vulkan/VulkanBackend.cpp")
+endif()
+
+set(dawn_native_public_depends
     dawn::dawn_common
     dawn::dawn_platform
     dawn::dawncpp_headers
     dawn::partition_alloc
     ${conditional_public_depends}
-  PRIVATE_DEPENDS
+)
+set(dawn_native_private_depends
     absl::flat_hash_map
     absl::flat_hash_set
     absl::inlined_vector
@@ -784,6 +793,38 @@
     absl::strings
     libtint
     ${conditional_private_depends}
+)
+
+# The same object files are reused to build
+# 1. dawn_native (which gets used by tests, samples, benchmarks)
+# 2. webgpu_dawn bundle (which gets installed via CMake install rules)
+dawn_add_library(
+  dawn_native_objects
+  UTILITY_TARGET dawn_internal_config
+  FORCE_OBJECT
+  HEADERS
+    ${headers}
+  PRIVATE_HEADERS
+    ${private_headers}
+  SOURCES
+    ${sources}
+  DEPENDS
+    ${dawn_native_public_depends}
+  PRIVATE_DEPENDS
+    ${dawn_native_private_depends}
+    ${conditional_private_platform_depends}
+)
+
+dawn_add_library(
+  dawn_native
+  UTILITY_TARGET dawn_internal_config
+  SOURCES
+    ${dawn_component_srcs}
+  DEPENDS
+    dawn::dawn_native_objects
+    ${dawn_native_public_depends}
+  PRIVATE_DEPENDS
+    ${dawn_native_private_depends}
     ${conditional_private_platform_depends}
 )
 
@@ -811,35 +852,59 @@
     target_compile_definitions(dawn_native PRIVATE "DAWN_ENABLE_SWIFTSHADER")
 endif()
 
-###############################################################################
-# Do the 'complete_lib' build.
-# A convenience target that bundles dawn_native and procs calling it directly so that
-# applications link against it and have WebGPU work without jumping through more hoops.
-# Note that this library name is referenced in several places, search for it and things like:
-# "{{.*}}_dawn" when you rename it.
-###############################################################################
-
-if (NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
+if (DAWN_BUILD_MONOLITHIC_LIBRARY)
+    ###############################################################################
+    # Do the 'complete_lib' build.
+    # A convenience target that bundles dawn_native and procs calling it directly so that
+    # applications link against it and have WebGPU work without jumping through more hoops.
+    # Note that this library name is referenced in several places, search for it and things like:
+    # "{{.*}}_dawn" when you rename it.
+    ###############################################################################
     DawnJSONGenerator(
         TARGET "webgpu_dawn_native_proc"
         PRINT_NAME "Dawn native WebGPU procs"
         OUTPUT_SOURCES WEBGPU_DAWN_NATIVE_PROC_GEN_SOURCES
     )
-
+    # Bundle all objects of dawn_native, it's public dependencies and private dependencies.
     include(BundleLibraries)
-    bundle_libraries(webgpu_dawn dawn_native)
-    add_library(dawn::webgpu ALIAS webgpu_dawn)
+    bundle_libraries(webgpu_dawn dawn::dawn_native_objects)
+    add_library(dawn::webgpu_dawn ALIAS webgpu_dawn)
+    # Compile backend specific sources along with webgpu_dawn_native_proc sources for export macros to get applied.
     target_sources(webgpu_dawn
-    PRIVATE
+        PRIVATE
         ${WEBGPU_DAWN_NATIVE_PROC_GEN_SOURCES}
+        ${dawn_component_srcs}
     )
+    target_compile_definitions(webgpu_dawn
+        PRIVATE
+            "WGPU_IMPLEMENTATION"
+            "DAWN_NATIVE_IMPLEMENTATION"
+        PUBLIC
+            "WGPU_SHARED_LIBRARY"
+            "DAWN_NATIVE_SHARED_LIBRARY"
+    )
+    # TODO: Revert https://dawn-review.googlesource.com/c/dawn/+/196361 and remove the next line.
+    set_target_properties(webgpu_dawn PROPERTIES CXX_EXTENSIONS NO)
+    # Apart from dawn_public_config, everything else goes inside PRIVATE, otherwise install rules will complain that they were not exported.
     target_link_libraries(webgpu_dawn
-    PRIVATE
-        dawn_internal_config
-        ${conditional_private_platform_depends}
+        PUBLIC
+            dawn_public_config
+        PRIVATE
+            dawn_internal_config
+            ${dawn_native_public_depends}
+            ${dawn_native_private_depends}
+            ${conditional_private_platform_depends}
     )
-    target_compile_definitions(webgpu_dawn PRIVATE "WGPU_IMPLEMENTATION")
-    target_compile_definitions(webgpu_dawn PUBLIC "WGPU_SHARED_LIBRARY")
+    set(webgpu_dawn_public_headers)
+    foreach(dawn_target_name IN ITEMS dawn_headers dawncpp_headers dawn_native_objects)
+        get_target_property(headers "${dawn_target_name}" INTERFACE_SOURCES)
+        list(INSERT webgpu_dawn_public_headers 0 "${headers}")
+    endforeach()
+    if (DAWN_ENABLE_INSTALL)
+        dawn_install_target(dawn_public_config)
+        dawn_install_target(webgpu_dawn
+            HEADERS ${webgpu_dawn_public_headers})
+    endif ()
 endif ()
 
 # Linking with dxcompiler after bundling so that the bundling process
@@ -850,6 +915,3 @@
     target_link_libraries(dawn_native PRIVATE dxcompiler)
     target_link_libraries(webgpu_dawn PRIVATE dxcompiler)
 endif()
-
-install_if_enabled(dawn_native)
-install_if_enabled(webgpu_dawn)
diff --git a/src/dawn/platform/CMakeLists.txt b/src/dawn/platform/CMakeLists.txt
index 7916e10..34648c9 100644
--- a/src/dawn/platform/CMakeLists.txt
+++ b/src/dawn/platform/CMakeLists.txt
@@ -56,5 +56,3 @@
 if (DAWN_USE_BUILT_DXC)
   target_compile_definitions(dawn_platform PRIVATE "DAWN_USE_BUILT_DXC")
 endif()
-
-install_if_enabled(dawn_platform)
diff --git a/src/dawn/wire/CMakeLists.txt b/src/dawn/wire/CMakeLists.txt
index 35020df..1ac86c8 100644
--- a/src/dawn/wire/CMakeLists.txt
+++ b/src/dawn/wire/CMakeLists.txt
@@ -128,5 +128,3 @@
 if(BUILD_SHARED_LIBS)
     target_compile_definitions(dawn_wire PRIVATE "DAWN_WIRE_SHARED_LIBRARY")
 endif()
-
-install_if_enabled(dawn_wire)
diff --git a/tools/android/webgpu/src/main/cpp/CMakeLists.txt b/tools/android/webgpu/src/main/cpp/CMakeLists.txt
index 44033e0..259af44 100644
--- a/tools/android/webgpu/src/main/cpp/CMakeLists.txt
+++ b/tools/android/webgpu/src/main/cpp/CMakeLists.txt
@@ -31,6 +31,7 @@
 cmake_minimum_required(VERSION 3.22.1)
 
 set(DAWN_BUILD_ANDROID_SAMPLES OFF)
+set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF)
 set(DAWN_BUILD_SAMPLES OFF)
 set(TINT_BUILD_TESTS OFF)
 set(TINT_BUILD_CMD_TOOLS OFF)