Make GN builds produce an ICD JSON in the build dir

ANGLE already has this logic, but with Dawn looking to use Swiftshader
as well, there would have been a conflict when both ANGLE and Dawn tried
to generate the same ICD JSON file.

Having this logic in Swiftshader's GN files means that any number of
component of projects using GN (aka Chromium) can use swiftshader
without issues.

Bug: dawn:283
Change-Id: I8531c98c370db01563dc102f259164e0393242ca
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38491
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Corentin Wallez <cwallez@google.com>
diff --git a/src/Vulkan/BUILD.gn b/src/Vulkan/BUILD.gn
index 8340717..701ed4d 100644
--- a/src/Vulkan/BUILD.gn
+++ b/src/Vulkan/BUILD.gn
@@ -14,6 +14,7 @@
 
 import("//build_overrides/build.gni")
 import("../swiftshader.gni")
+import("vulkan.gni")
 
 # Need a separate config to ensure the warnings are added to the end.
 config("swiftshader_libvulkan_private_config") {
@@ -96,13 +97,9 @@
       "VkSemaphoreExternalLinux.hpp",
     ]
   } else if (is_fuchsia) {
-    sources += [
-      "VkSemaphoreExternalFuchsia.hpp",
-    ]
+    sources += [ "VkSemaphoreExternalFuchsia.hpp" ]
   } else {
-    sources += [
-      "VkSemaphoreExternalNone.hpp",
-    ]
+    sources += [ "VkSemaphoreExternalNone.hpp" ]
   }
 }
 
@@ -168,8 +165,8 @@
   }
 
   deps = [
-    "../../third_party/marl:Marl",
     "${swiftshader_spirv_tools_dir}:SPIRV-Tools",
+    "../../third_party/marl:Marl",
     "../Device",
     "../Pipeline",
     "../Reactor:swiftshader_llvm_reactor",
@@ -188,3 +185,39 @@
     ":swiftshader_libvulkan_headers",
   ]
 }
+
+# Generates an ICD JSON file that can be used by all targets in this GN build
+# (ANGLE, Dawn, Chromium).
+action("icd_file") {
+  output_icd_file = "${root_build_dir}/${swiftshader_icd_file_name}"
+  input_file = swiftshader_icd_file_name
+
+  if (is_win) {
+    library_path = ".\\vk_swiftshader.dll"
+  } else if (is_mac) {
+    library_path = "./libvk_swiftshader.dylib"
+  } else {
+    library_path = "./libvk_swiftshader.so"
+  }
+
+  script = "write_icd_json.py"
+  args = [
+    "--input",
+    rebase_path(input_file, root_build_dir),
+    "--output",
+    rebase_path(output_icd_file, root_build_dir),
+    "--library_path",
+    library_path,
+  ]
+
+  inputs = [
+    input_file,
+  ]
+  outputs = [
+    output_icd_file,
+  ]
+
+  deps = [
+    ":swiftshader_libvulkan",
+  ]
+}
diff --git a/src/Vulkan/vulkan.gni b/src/Vulkan/vulkan.gni
new file mode 100644
index 0000000..15854e9
--- /dev/null
+++ b/src/Vulkan/vulkan.gni
@@ -0,0 +1,20 @@
+# Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# File containing GN "constants" for Swiftshader Vulkan so that GN-based
+# projects depending on Swiftshader don't need to hardcode them.
+
+# The name of the Swiftshader Vulkan ICD file in the $root_build_dir that's
+# produced by ${swiftshader_dir}/src/Vulkan:icd_file
+swiftshader_icd_file_name = "vk_swiftshader_icd.json"
diff --git a/src/Vulkan/write_icd_json.py b/src/Vulkan/write_icd_json.py
new file mode 100644
index 0000000..8c7c9f0
--- /dev/null
+++ b/src/Vulkan/write_icd_json.py
@@ -0,0 +1,35 @@
+# Copyright 2019 The SwiftShader Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import argparse, json, sys
+
+def run():
+    parser = argparse.ArgumentParser(
+        description = "Generates the correct ICD JSON file for swiftshader in GN builds"
+    )
+    parser.add_argument('--input', type=str, help='The template ICD JSON')
+    parser.add_argument('--output', type=str, help='The output ICD JSON in the GN build dir')
+    parser.add_argument('--library_path', type=str, help='The file containing a list of directories to check for stale files')
+    args = parser.parse_args()
+
+    with open(args.input) as infile:
+        with open(args.output, 'wb') as outfile:
+            data = json.load(infile)
+            data['ICD']['library_path'] = args.library_path
+            json.dump(data, outfile)
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(run())