Add and use CMake modules to generate SPIR-V kernels

Closes #213

Closes https://github.com/google/iree/pull/450

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/iree/pull/450 from marbre:cmake-modules 45c0768b788f2aba8a08c3883cd44f667d0737f0
PiperOrigin-RevId: 289152807
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bd22e94..1017273 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -60,6 +60,9 @@
 include(iree_tablegen_library)
 include(iree_cc_embed_data)
 include(iree_bytecode_module)
+include(iree_glslang)
+include(iree_glsl_vulkan)
+include(iree_spirv_kernel_cc_library)
 
 string(JOIN " " CMAKE_CXX_FLAGS ${IREE_DEFAULT_COPTS})
 
diff --git a/build_tools/cmake/iree_glsl_vulkan.cmake b/build_tools/cmake/iree_glsl_vulkan.cmake
new file mode 100644
index 0000000..1854b79
--- /dev/null
+++ b/build_tools/cmake/iree_glsl_vulkan.cmake
@@ -0,0 +1,45 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#      https://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.
+
+include(CMakeParseArguments)
+
+# iree_glsl_vulkan()
+#
+# CMake function to imitate Bazel's iree_glsl_vulkan rule and glsl_vulkan rule
+#
+# Parameters:
+# NAME: Name of spv file to create (without file name extension).
+# SRC: GLSL source file to translate into a SPIR-V binary.
+
+function(iree_glsl_vulkan)
+  cmake_parse_arguments(
+    _RULE
+    ""
+    "NAME;SRC"
+    ""
+    ${ARGN}
+  )
+
+  iree_glslang(
+    NAME
+      ${_RULE_NAME}
+    SRC
+      ${_RULE_SRC}
+    MODE
+      "glsl"
+    TARGET
+      "vulkan"
+  )
+
+endfunction()
diff --git a/build_tools/cmake/iree_glslang.cmake b/build_tools/cmake/iree_glslang.cmake
new file mode 100644
index 0000000..13c4859
--- /dev/null
+++ b/build_tools/cmake/iree_glslang.cmake
@@ -0,0 +1,64 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#      https://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.
+
+include(CMakeParseArguments)
+
+# iree_glslang()
+#
+# CMake function to imitate Bazel's _glslang rule.
+#
+# Parameters:
+# NAME: Name of spv file to create (without file name extension).
+# SRC: Source file.
+# MODE: Defines the type of input: either "hlsl" or "glsl".
+# TARGET: Target to create the SPIR-V binary for: either "vulkan" or "opengl".
+
+function(iree_glslang)
+  cmake_parse_arguments(
+    _RULE
+    ""
+    "NAME;SRC;MODE;TARGET"
+    ""
+    ${ARGN}
+  )
+
+  if(_RULE_MODE STREQUAL "glsl")
+    set(_MODE "")
+  elseif(_RULE_MODE STREQUAL "hlsl")
+    set(_MODE "-D")
+  else()
+    message(FATAL_ERROR "Illegal mode ${_RULE_MODE}")
+  endif()
+
+  if(_RULE_TARGET STREQUAL "opengl")
+    set(_TARGET "-G")
+  elseif(_RULE_TARGET STREQUAL "vulkan")
+    set(_TARGET "-V")
+  else()
+    message(FATAL_ERROR "Illegal target ${_RULE_TARGET}")
+  endif()
+
+  set(_ARGS "${_MODE}")
+  list(APPEND _ARGS "${_TARGET}")
+  list(APPEND _ARGS "${CMAKE_CURRENT_SOURCE_DIR}/${_RULE_SRC}")
+  list(APPEND _ARGS "-o")
+  list(APPEND _ARGS "${_RULE_NAME}.spv")
+
+  add_custom_command(
+    OUTPUT "${_RULE_NAME}.spv"
+    COMMAND glslangValidator ${_ARGS}
+    DEPENDS glslangValidator
+  )
+
+endfunction()
diff --git a/build_tools/cmake/iree_hlsl_vulkan.cmake b/build_tools/cmake/iree_hlsl_vulkan.cmake
new file mode 100644
index 0000000..76c0c72
--- /dev/null
+++ b/build_tools/cmake/iree_hlsl_vulkan.cmake
@@ -0,0 +1,45 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#      https://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.
+
+include(CMakeParseArguments)
+
+# iree_hlsl_vulkan()
+#
+# CMake function to imitate Bazel's iree_hlsl_vulkan rule and hlsl_vulkan rule
+#
+# Parameters:
+# NAME: Name of spv file to create (without file name extension).
+# SRC: GLSL source file to translate into a SPIR-V binary.
+
+function(iree_hlsl_vulkan)
+  cmake_parse_arguments(
+    _RULE
+    ""
+    "NAME;SRC"
+    ""
+    ${ARGN}
+  )
+
+  iree_glslang(
+    NAME
+      ${_RULE_NAME}
+    SRC
+      ${_RULE_SRC}
+    MODE
+      "hlsl"
+    TARGET
+      "vulkan"
+  )
+
+endfunction()
diff --git a/build_tools/cmake/iree_spirv_kernel_cc_library.cmake b/build_tools/cmake/iree_spirv_kernel_cc_library.cmake
new file mode 100644
index 0000000..85a829f
--- /dev/null
+++ b/build_tools/cmake/iree_spirv_kernel_cc_library.cmake
@@ -0,0 +1,74 @@
+# Copyright 2020 Google LLC
+#
+# 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
+#
+#      https://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.
+
+include(CMakeParseArguments)
+
+# iree_spirv_kernel_cc_library()
+#
+# CMake function to imitate Bazel's spirv_kernel_cc_library rule.
+#
+# Parameters:
+# NAME: Name of target (see Note).
+# SRCS: List of compute shader source files.
+# PUBLIC: Add this so that this library will be exported under ${PACKAGE}::
+# TESTONLY: When added, this target will only be built if user passes
+#    -DIREE_BUILD_TESTS=ON to CMake.
+#
+# Note:
+# By default, iree_spirv_kernel_cc_library will always create a library named ${NAME},
+# and alias target iree::${NAME}. The iree:: form should always be used.
+# This is to reduce namespace pollution.
+
+function(iree_spirv_kernel_cc_library)
+  cmake_parse_arguments(
+    _RULE
+    "PUBLIC;TESTONLY"
+    "NAME"
+    "SRCS"
+    ${ARGN}
+  )
+
+  if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS)
+    set(_SPV_FILES)
+    foreach(_SRC ${_RULE_SRCS})
+      get_filename_component(_SPV_NAME ${_SRC} NAME_WE)
+      list(APPEND _SPV_FILES "${_SPV_NAME}.spv")
+
+      iree_glsl_vulkan(
+        NAME
+          "${_SPV_NAME}"
+        SRC
+          "${_SRC}"
+      )
+    endforeach(_SRC)
+
+    iree_cc_embed_data(
+      NAME
+        "${_RULE_NAME}"
+      PUBLIC
+        "${_RULE_PUBLIC}"
+      TESTONLY
+        "${_RULE_TESTONLY}"
+      GENERATED_SRCS
+        "${_SPV_FILES}"
+      CC_FILE_OUTPUT
+        "${_RULE_NAME}.cc"
+      H_FILE_OUTPUT
+        "${_RULE_NAME}.h"
+      CPP_NAMESPACE
+        "mlir::iree_compiler::spirv_kernels"
+      FLATTEN
+    )
+  endif()
+endfunction()
diff --git a/iree/compiler/Translation/SPIRV/EmbeddedKernels/Kernels/CMakeLists.txt b/iree/compiler/Translation/SPIRV/EmbeddedKernels/Kernels/CMakeLists.txt
index 73cdbf1..94c2d6f 100644
--- a/iree/compiler/Translation/SPIRV/EmbeddedKernels/Kernels/CMakeLists.txt
+++ b/iree/compiler/Translation/SPIRV/EmbeddedKernels/Kernels/CMakeLists.txt
@@ -12,48 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# TODO(benvanik): iree_glsl_cc_library.
-# iree_glsl_cc_library(
-#   NAME
-#     Kernels
-#  TARGET
-#    spirv
-#  SRCS
-#    "matmul.comp"
-#    "reduce_untiled.comp"
-#   PUBLIC
-# )
-
-add_custom_command(
-  OUTPUT conv2d_nhwc.spv
-  COMMAND glslangValidator -V "${CMAKE_CURRENT_SOURCE_DIR}/conv2d_nhwc.comp" -o conv2d_nhwc.spv
-  DEPENDS glslangValidator
-)
-
-add_custom_command(
-  OUTPUT matmul.spv
-  COMMAND glslangValidator -V "${CMAKE_CURRENT_SOURCE_DIR}/matmul.comp" -o matmul.spv
-  DEPENDS glslangValidator
-)
-
-add_custom_command(
-  OUTPUT reduce_untiled.spv
-  COMMAND glslangValidator -V "${CMAKE_CURRENT_SOURCE_DIR}/reduce_untiled.comp" -o reduce_untiled.spv
-  DEPENDS glslangValidator
-)
-
-iree_cc_embed_data(
+iree_spirv_kernel_cc_library(
   NAME
     Kernels
-  GENERATED_SRCS
-    "conv2d_nhwc.spv"
-    "matmul.spv"
-    "reduce_untiled.spv"
-  CC_FILE_OUTPUT
-    "Kernels.cc"
-  H_FILE_OUTPUT
-    "Kernels.h"
-  CPP_NAMESPACE
-    "mlir::iree_compiler::spirv_kernels"
-  FLATTEN
+  SRCS
+    "conv2d_nhwc.comp"
+    "matmul.comp"
+    "reduce_untiled.comp"
 )