[emscripten] Fix CMake dependencies for generated files

Follow-up to https://dawn-review.googlesource.com/c/dawn/+/227196

The specific issue I had was that modifying dawn.json would rebuild
webgpu_generated_struct_info*.json but not
library_webgpu_generated_struct_info.js. While looking at this I noticed
a lot of other missing dependencies as well:
- Generators on generator scripts
- Generators on their input files (the dependency was on a separate
  target that _also_ depended on the generator, which wouldn't actually
  rerun the generator).
- Link flags on all the other linked files

The comments try to explain my understanding of the setup. I don't fully
understand why it needs to be this way, though. Tested locally:
- rm -rf gen
- touch .../library_webgpu_struct_info_part1.txt
- touch .../library_webgpu_enum_tables.js
- touch .../library_webgpu.js

Additionally, runs the link test during GitHub release.

Bug: 419062310
Fixed: 418173488
Change-Id: I59a20eba9ea3f081a1cb170b2029fc9364aa95ef
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/242954
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
diff --git a/.github/workflows/package-emdawnwebgpu.sh b/.github/workflows/package-emdawnwebgpu.sh
index 40d9a0c..f4869f6 100755
--- a/.github/workflows/package-emdawnwebgpu.sh
+++ b/.github/workflows/package-emdawnwebgpu.sh
@@ -22,10 +22,10 @@
 git submodule update --init --depth=1 third_party/emsdk
 python3 tools/activate-emsdk
 
-# Build
+# Build the package, and also test that the bindings can link.
 mkdir -p out/wasm
 third_party/emsdk/upstream/emscripten/emcmake cmake -S=. -B=out/wasm
-make -j4 -C out/wasm emdawnwebgpu_pkg
+make -j4 -C out/wasm emdawnwebgpu_pkg emdawnwebgpu_link_test
 
 # Create zip
 cat << EOF > out/wasm/emdawnwebgpu_pkg/VERSION.txt
diff --git a/src/emdawnwebgpu/CMakeLists.txt b/src/emdawnwebgpu/CMakeLists.txt
index 4e7380f..0eee3bc 100644
--- a/src/emdawnwebgpu/CMakeLists.txt
+++ b/src/emdawnwebgpu/CMakeLists.txt
@@ -102,6 +102,10 @@
             COMMAND ${ARGS}
             OUTPUT ${OUTPUT}
             COMMENT "Dawn Emscripten: Generating ${PRINT_NAME}."
+            DEPENDS
+                "${EMSCRIPTEN_ROOT_PATH}/tools/gen_struct_info.py"
+                ${EMDAWNWEBGPU_HEADERS_GEN_HEADERS}  # for webgpu.h
+                ${EMDAWNWEBGPU_STRUCT_INFO_JSON_GEN_SOURCES}  # for struct_info_webgpu.json
         )
 
         # Prior to CMake 3.20 the GENERATED property is local to a directory which means that putting
@@ -124,16 +128,10 @@
         OUTPUT_JSON WEBGPU_STRUCT_INFO_GEN32
         WASM64 OFF
     )
-    add_custom_target(webgpu_generated_struct_info32
-        DEPENDS emdawnwebgpu_headers_gen ${EMDAWNWEBGPU_STRUCT_INFO_JSON_GEN_SOURCES} ${WEBGPU_STRUCT_INFO_GEN32}
-    )
     webgpu_gen_struct_info(
         OUTPUT_JSON WEBGPU_STRUCT_INFO_GEN64
         WASM64 ON
     )
-    add_custom_target(webgpu_generated_struct_info64
-        DEPENDS emdawnwebgpu_headers_gen ${EMDAWNWEBGPU_STRUCT_INFO_JSON_GEN_SOURCES} ${WEBGPU_STRUCT_INFO_GEN64}
-    )
 
     # TODO(crbug.com/346806934): Consider using CMake builtin `cat` as per https://stackoverflow.com/a/62362885,
     # especially if we are to remove the GN build where concat.py is needed.
@@ -151,15 +149,18 @@
 
         set(PRINT_NAME library_webgpu_generated_struct_info.js)
         set(OUTPUT "${EM_BUILD_GEN_DIR}/${PRINT_NAME}")
+        set(SRCS
+            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part1.txt"
+            "${WEBGPU_STRUCT_INFO_GEN32}"
+            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part2.txt"
+            "${WEBGPU_STRUCT_INFO_GEN64}"
+            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part3.txt"
+        )
         set(ARGS
             ${Python3_EXECUTABLE}
             "${EM_SRC_DIR}/concat.py"
             "${OUTPUT}"
-            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part1.txt"
-            "${EM_BUILD_GEN_DIR}/webgpu_generated_struct_info32.json"
-            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part2.txt"
-            "${EM_BUILD_GEN_DIR}/webgpu_generated_struct_info64.json"
-            "${EM_SRC_DIR}/snippets/library_webgpu_struct_info_part3.txt"
+            ${SRCS}
         )
         set(${arg_OUTPUT_JS} "${OUTPUT}" PARENT_SCOPE)
 
@@ -167,6 +168,9 @@
             COMMAND ${ARGS}
             OUTPUT ${OUTPUT}
             COMMENT "Dawn Emscripten: Generating ${PRINT_NAME}."
+            DEPENDS
+                "${EM_SRC_DIR}/concat.py"
+                ${SRCS}
         )
 
         # Prior to CMake 3.20 the GENERATED property is local to a directory which means that putting
@@ -186,37 +190,13 @@
     webgpu_gen_struct_info_js(
         OUTPUT_JS EMDAWNWEBGPU_STRUCT_INFO_JS
     )
-    add_custom_target(webgpu_generated_struct_info_js
-        DEPENDS
-            webgpu_generated_struct_info32
-            webgpu_generated_struct_info64
-            ${EMDAWNWEBGPU_STRUCT_INFO_JS}
-    )
 
-    add_library(emdawnwebgpu_config INTERFACE)
-    target_include_directories(emdawnwebgpu_config BEFORE INTERFACE
+    # Include dir, and dependency on the generated files in the include dir.
+    add_library(emdawnwebgpu_c_include INTERFACE)
+    target_include_directories(emdawnwebgpu_c_include BEFORE INTERFACE
         "${EM_BUILD_GEN_DIR}/include"
     )
-    add_dependencies(emdawnwebgpu_config
-        webgpu_generated_struct_info_js
-        emdawnwebgpu_js_gen
-        emdawnwebgpu_headers_gen
-    )
-    target_link_options(emdawnwebgpu_config INTERFACE
-        # We are using Dawn-generated bindings, not built-in ones
-        "-sUSE_WEBGPU=0"
-        # The JS libraries needed for bindings
-        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_enum_tables.js"
-        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_generated_struct_info.js"
-        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_generated_sig_info.js"
-        "--js-library=${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/library_webgpu.js"
-        # Closure externs to avoid minifying WebGPU API symbols
-        "--closure-args=--externs=${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/webgpu-externs.js"
-    )
-    # Relink when library_webgpu.js file changes.
-    set_target_properties(emdawnwebgpu_config PROPERTIES
-        INTERFACE_LINK_DEPENDS "${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/library_webgpu.js"
-    )
+    add_dependencies(emdawnwebgpu_c_include emdawnwebgpu_headers_gen)
 
     dawn_add_library(
         emdawnwebgpu_c
@@ -226,7 +206,37 @@
         SOURCES
             "${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/webgpu.cpp"
         DEPENDS
-            emdawnwebgpu_config
+            emdawnwebgpu_c_include
+    )
+    target_link_options(emdawnwebgpu_c INTERFACE
+        # IMPORTANT: If changing these dependencies, update EMDAWNWEBGPU_C_ALL_FILE_DEPS too.
+        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_enum_tables.js"
+        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_generated_sig_info.js"
+        "--js-library=${EM_BUILD_GEN_DIR}/library_webgpu_generated_struct_info.js"
+        "--js-library=${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/library_webgpu.js"
+        "--closure-args=--externs=${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/webgpu-externs.js"
+    )
+
+    # Dependencies from emdawnwebgpu_c to the files referenced in the linker flags.
+    # - These are used as both file-level dependencies (defining *when* to rebuild) and
+    #   target-level dependencies (defining *how* to rebuild).
+    set(EMDAWNWEBGPU_C_GENERATED_FILE_DEPS
+        "${EMDAWNWEBGPU_JS_GEN_SOURCES}"
+        "${EMDAWNWEBGPU_STRUCT_INFO_JS}"
+    )
+    # - There are also source files, which are used only as file-level dependencies.
+    set(EMDAWNWEBGPU_C_ALL_FILE_DEPS
+        "${EMDAWNWEBGPU_C_GENERATED_FILE_DEPS}"
+        "${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/library_webgpu.js"
+        "${DAWN_EMDAWNWEBGPU_DIR}/pkg/webgpu/src/webgpu-externs.js"
+    )
+    add_custom_target(emdawnwebgpu_config_generated_deps
+        DEPENDS "${EMDAWNWEBGPU_C_GENERATED_FILE_DEPS}"
+    )
+    add_dependencies(emdawnwebgpu_c emdawnwebgpu_config_generated_deps)
+    set_target_properties(emdawnwebgpu_c PROPERTIES
+        # This defines file-level dependencies of the linker (intended for "linker scripts").
+        INTERFACE_LINK_DEPENDS "${EMDAWNWEBGPU_C_ALL_FILE_DEPS}"
     )
 
     dawn_add_library(
@@ -244,10 +254,9 @@
 
     add_custom_target(emdawnwebgpu_pkg
         DEPENDS
-            # Note emdawnwebgpu_headers_gen generates all the files we need. We don't want
-            # emdawnwebgpu_c because that will actually compile webgpu.cpp. We want to
-            # package webgpu.cpp as a source file, instead.
-            emdawnwebgpu_config
+            # This will compile webgpu.cpp, which is unnecessary because we package webgpu.cpp as a
+            # source file, but it's simpler than specifying all the generator dependencies again.
+            emdawnwebgpu_c
     )
 
     add_custom_command(TARGET emdawnwebgpu_pkg POST_BUILD