CMake: Fix workaround for CMake < 3.20 generated files.

CMake < 3.20 needs a workaround to be happy with generated files being
put in INTERFACE of targeets. However the previous workaround relied on
making empty files and changing the access time of the generator script.

Filesystem timestamp precision may be as low as a second, causing both
the generated files and generator to have the same access time, leading
to build systems not realizing that files needed to be rebuilt.

Instead use a heavier-handed approach to run the source code generation
at build time if the files aren't present. If the files are already
present, then they are integrated in the build graph correctly and don't
need special handling.

Fixed: 339061162
Change-Id: Idef6034a5aadb73988d3e556a8ab482a71951d0c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/187143
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/generator/CMakeLists.txt b/generator/CMakeLists.txt
index 9e643ad..75d37bd 100644
--- a/generator/CMakeLists.txt
+++ b/generator/CMakeLists.txt
@@ -100,26 +100,28 @@
         COMMENT "Dawn: Generating files for ${G_PRINT_NAME}."
     )
 
+    # Return the list of outputs.
+    set(${G_RESULT_VARIABLE} ${OUTPUTS} PARENT_SCOPE)
+
     # Prior to CMake 3.20 the GENERATED property is local to a directory which means that putting
     # generated headers in INTERFACE properties causes dependent targets to complain that they
     # cannot find the file. (because they don't see it as generated and want to check is is
     # actually on the filesystem).
-    # Work around this by creating empty files placeholder generated files so that the build
-    # configuration process can success.
+    # Work around this by generating the files once if they aren't present at configuration time.
+    set(needToGenerate OFF)
     foreach(path ${OUTPUTS})
         if (NOT EXISTS ${path})
-            string(FIND "${path}" "/" foundIndex REVERSE)
-            string(SUBSTRING "${path}" 0 ${foundIndex} dir)
-            file(MAKE_DIRECTORY ${dir})
-            file(TOUCH ${path})
-            # Also touch the generator script to make a dependency of the generated file dirty,
-            # ensuring that it gets generated and not used while it is an empty file.
-            file(TOUCH ${G_SCRIPT})
+            set(needToGenerate ON)
         endif()
     endforeach()
 
-    # Return the list of outputs.
-    set(${G_RESULT_VARIABLE} ${OUTPUTS} PARENT_SCOPE)
+    if (${needToGenerate})
+        message(STATUS "Dawn: Generating initial versions of files for ${G_PRINT_NAME}.")
+        execute_process(COMMAND ${BASE_ARGS} RESULT_VARIABLE RET)
+        if (NOT RET EQUAL 0)
+            message(FATAL_ERROR "Dawn: Failed to generate the initial version of files for ${G_PRINT_NAME}. Base args are '${BASE_ARGS}'.")
+        endif()
+    endif()
 endfunction()
 
 # Helper function to call dawn_generator.py: