Add iree_cc_embed_data and iree_bytecode_module CMake functions.

Tested on Linux and Windows. Both are able to build the relevant targets, though Windows with MSVC isn't able to build `iree/vm/sequencer_dispatch.cc` on my machine so I can't yet run the samples with CMake there.

Fixes #211
Fixes #212

Closes #215

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/iree/pull/215 from ScottTodd:cmake-functions 8dd2beb4ba64c7f6b0f177fa9b158afc95399fb8
PiperOrigin-RevId: 286262579
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6981b51..798890c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,6 +53,8 @@
 include(iree_cc_library)
 include(iree_cc_test)
 include(iree_tablegen_library)
+include(iree_cc_embed_data)
+include(iree_bytecode_module)
 
 string(JOIN " " CMAKE_CXX_FLAGS ${IREE_DEFAULT_COPTS})
 
diff --git a/build_tools/cmake/iree_bytecode_module.cmake b/build_tools/cmake/iree_bytecode_module.cmake
new file mode 100644
index 0000000..77476e9
--- /dev/null
+++ b/build_tools/cmake/iree_bytecode_module.cmake
@@ -0,0 +1,95 @@
+# Copyright 2019 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_bytecode_module()
+#
+# CMake function to imitate Bazel's iree_bytecode_module rule.
+#
+# Parameters:
+# NAME: Name of target (see Note).
+# SRC: Source file to compile into a bytecode module.
+# TRANSLATION: Translation option to pass to the translation tool (string).
+# TRANSLATION_TOOL: Translation tool to invoke (CMake target).
+# CC_NAMESPACE: Wraps everything in a C++ namespace.
+# PUBLIC: Add this so that this library will be exported under ${PACKAGE}::
+# Also in IDE, target will appear in ${PACKAGE} folder while non PUBLIC will be
+# in ${PACKAGE}/internal.
+# TESTONLY: When added, this target will only be built if user passes
+#    -DIREE_BUILD_TESTS=ON to CMake.
+#
+# Note:
+# By default, iree_bytecode_module will create a library named ${NAME}_cc,
+# and alias target iree::${NAME}_cc. The iree:: form should always be used.
+# This is to reduce namespace pollution.
+function(iree_bytecode_module)
+  cmake_parse_arguments(
+    _RULE
+    "PUBLIC;TESTONLY"
+    "NAME;SRC;TRANSLATION;TRANSLATION_TOOL;CC_NAMESPACE"
+    ""
+    ${ARGN}
+  )
+
+  if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS)
+    # Set defaults for TRANSLATION and TRANSLATION_TOOL
+    if(DEFINED _RULE_TRANSLATION)
+      set(_TRANSLATION ${_RULE_TRANSLATION})
+    else()
+      set(_TRANSLATION "-mlir-to-iree-module")
+    endif()
+    if(DEFINED _RULE_TRANSLATION_TOOL)
+      set(_TRANSLATION_TOOL ${_RULE_TRANSLATION_TOOL})
+    else()
+      set(_TRANSLATION_TOOL "iree_tools_iree_translate")
+    endif()
+
+    # Resolve the executable binary path from the target name.
+    set(_TRANSLATION_TOOL_EXECUTABLE $<TARGET_FILE:${_TRANSLATION_TOOL}>)
+
+    set(_ARGS "${_TRANSLATION}")
+    list(APPEND _ARGS "${CMAKE_CURRENT_SOURCE_DIR}/${_RULE_SRC}")
+    list(APPEND _ARGS "-o")
+    list(APPEND _ARGS "${_RULE_NAME}.emod")
+
+    add_custom_command(
+      OUTPUT "${_RULE_NAME}.emod"
+      COMMAND ${_TRANSLATION_TOOL_EXECUTABLE} ${_ARGS}
+      DEPENDS ${_TRANSLATION_TOOL}
+    )
+
+    if(DEFINED _RULE_CC_NAMESPACE)
+      iree_cc_embed_data(
+        NAME
+          "${_RULE_NAME}_cc"
+        PUBLIC
+          "${_RULE_PUBLIC}"
+        TESTONLY
+          "${_RULE_TESTONLY}"
+        IDENTIFIER
+          "${_RULE_NAME}"
+        GENERATED_SRCS
+          "${_RULE_NAME}.emod"
+        CC_FILE_OUTPUT
+          "${_RULE_NAME}.cc"
+        H_FILE_OUTPUT
+          "${_RULE_NAME}.h"
+        CPP_NAMESPACE
+          "${_RULE_CC_NAMESPACE}"
+        FLATTEN
+      )
+    endif()
+  endif()
+endfunction()
diff --git a/build_tools/cmake/iree_cc_embed_data.cmake b/build_tools/cmake/iree_cc_embed_data.cmake
new file mode 100644
index 0000000..a5ceefb
--- /dev/null
+++ b/build_tools/cmake/iree_cc_embed_data.cmake
@@ -0,0 +1,93 @@
+# Copyright 2019 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_cc_embed_data()
+#
+# CMake function to imitate Bazel's cc_embed_data rule.
+#
+# Parameters:
+# NAME: Name of target (see Note).
+# SRCS: List of source files to embed.
+# GENERATED_SRCS: List of generated source files to embed.
+# CC_FILE_OUTPUT: The CC implementation file to output.
+# H_FILE_OUTPUT: The H header file to output.
+# CPP_NAMESPACE: Wraps everything in a C++ namespace.
+# STRIP_PREFIX: Strips this verbatim prefix from filenames (in the TOC).
+# FLATTEN: Removes all directory components from filenames (in the TOC).
+# IDENTIFIER: The identifier to use in generated names (defaults to name).
+# PUBLIC: Add this so that this library will be exported under ${PACKAGE}::
+# Also in IDE, target will appear in ${PACKAGE} folder while non PUBLIC will be
+# in ${PACKAGE}/internal.
+# TESTONLY: When added, this target will only be built if user passes
+#    -DIREE_BUILD_TESTS=ON to CMake.
+# TODO(scotttodd): Support passing KWARGS down into iree_cc_library?
+#
+# Note:
+# By default, iree_cc_embed_data 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_cc_embed_data)
+  cmake_parse_arguments(
+    _RULE
+    "PUBLIC;TESTONLY;FLATTEN"
+    "NAME;IDENTIFIER;STRIP_PREFIX;CC_FILE_OUTPUT;H_FILE_OUTPUT;CPP_NAMESPACE"
+    "SRCS;GENERATED_SRCS"
+    ${ARGN}
+  )
+
+  if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS)
+    if(DEFINED _RULE_IDENTIFIER)
+      set(_IDENTIFIER ${_RULE_IDENTIFIER})
+    else()
+      set(_IDENTIFIER ${_RULE_NAME})
+    endif()
+
+    set(_ARGS)
+    list(APPEND _ARGS "--output_header=${_RULE_H_FILE_OUTPUT}")
+    list(APPEND _ARGS "--output_impl=${_RULE_CC_FILE_OUTPUT}")
+    list(APPEND _ARGS "--identifier=${_IDENTIFIER}")
+    if(DEFINED _RULE_CPP_NAMESPACE)
+      list(APPEND _ARGS "--cpp_namespace=${_RULE_CPP_NAMESPACE}")
+    endif()
+    if(DEFINED _RULE_STRIP_PREFIX})
+      list(APPEND _ARGS "--strip_prefix=${_RULE_STRIP_PREFIX}")
+    endif()
+    if(DEFINED _RULE_FLATTEN})
+      list(APPEND _ARGS "--flatten")
+    endif()
+
+    foreach(SRC ${_RULE_SRCS})
+      list(APPEND _ARGS "${CMAKE_CURRENT_SOURCE_DIR}/${SRC}")
+    endforeach(SRC)
+    foreach(SRC ${_GENERATED_SRCS})
+      list(APPEND _ARGS "${SRC}")
+    endforeach(SRC)
+
+    add_custom_command(
+      OUTPUT "${_RULE_H_FILE_OUTPUT}" "${_RULE_CC_FILE_OUTPUT}"
+      COMMAND generate_cc_embed_data ${_ARGS}
+      DEPENDS generate_cc_embed_data ${_RULE_SRCS}
+    )
+
+    iree_cc_library(
+      NAME ${_RULE_NAME}
+      PUBLIC ${_RULE_PUBLIC}
+      TESTONLY ${_RULE_TESTONLY}
+      HDRS "${_RULE_H_FILE_OUTPUT}"
+      SRCS "${_RULE_CC_FILE_OUTPUT}"
+    )
+  endif()
+endfunction()
diff --git a/iree/compiler/Dialect/HAL/CMakeLists.txt b/iree/compiler/Dialect/HAL/CMakeLists.txt
index 046e91c..b618e38 100644
--- a/iree/compiler/Dialect/HAL/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/CMakeLists.txt
@@ -18,16 +18,16 @@
 add_subdirectory(Transforms)
 add_subdirectory(Utils)
 
-add_custom_command(
-  PRE_BUILD
-  OUTPUT hal.imports.h hal.imports.cc
-  COMMAND generate_cc_embed_data "${CMAKE_CURRENT_SOURCE_DIR}/hal.imports.mlir"
-          --output_header=hal.imports.h
-          --output_impl=hal.imports.cc
-          --identifier=hal_imports
-          --cpp_namespace=mlir::iree_compiler
-          --flatten
-  DEPENDS generate_cc_embed_data
+iree_cc_embed_data(
+  NAME
+    hal_imports
+  SRCS
+    "hal.imports.mlir"
+  CC_FILE_OUTPUT
+    "hal.imports.cc"
+  H_FILE_OUTPUT
+    "hal.imports.h"
+  CPP_NAMESPACE
+    "mlir::iree_compiler"
+  FLATTEN
 )
-
-add_custom_target(iree_compiler_Dialect_HAL_hal_imports DEPENDS hal.imports.h)
diff --git a/iree/compiler/Dialect/HAL/Conversion/HALToVM/CMakeLists.txt b/iree/compiler/Dialect/HAL/Conversion/HALToVM/CMakeLists.txt
index 9290991..ae9c3ed 100644
--- a/iree/compiler/Dialect/HAL/Conversion/HALToVM/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/Conversion/HALToVM/CMakeLists.txt
@@ -28,7 +28,7 @@
     "ConvertVariableOps.cpp"
   DEPS
     iree::compiler::Dialect::IREE::IR
-    iree_compiler_Dialect_HAL_hal_imports
+    iree::compiler::Dialect::HAL::hal_imports
     iree::compiler::Dialect::HAL::IR::IR
     iree::compiler::Dialect::HAL::IR::HALEnumsGen
     iree::compiler::Dialect::HAL::IR::HALOpInterfaceGen
diff --git a/iree/compiler/Dialect/HAL/IR/CMakeLists.txt b/iree/compiler/Dialect/HAL/IR/CMakeLists.txt
index 99609f8..5e52e7a 100644
--- a/iree/compiler/Dialect/HAL/IR/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/IR/CMakeLists.txt
@@ -52,7 +52,7 @@
   DEPS
     IR
     iree::compiler::Dialect
-    iree_compiler_Dialect_HAL_hal_imports
+    iree::compiler::Dialect::HAL::hal_imports
     iree::compiler::Dialect::HAL::Conversion::HALToVM
     iree::compiler::Dialect::VM::Conversion
     LLVMSupport
diff --git a/iree/samples/hal/CMakeLists.txt b/iree/samples/hal/CMakeLists.txt
index fa543c2..5ddb14f 100644
--- a/iree/samples/hal/CMakeLists.txt
+++ b/iree/samples/hal/CMakeLists.txt
@@ -12,28 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-add_custom_command(
-  OUTPUT simple_compute_test_module.emod
-  COMMAND iree-translate
-          --mlir-to-iree-module "${CMAKE_CURRENT_SOURCE_DIR}/simple_compute_test.mlir"
-          -o simple_compute_test_module.emod
-  DEPENDS iree_tools_iree_translate
-)
-
-add_custom_command(
-  OUTPUT simple_compute_test_module.h simple_compute_test_module.cc
-  COMMAND generate_cc_embed_data simple_compute_test_module.emod
-          --output_header=simple_compute_test_module.h
-          --output_impl=simple_compute_test_module.cc
-          --identifier=simple_compute_test_module
-          --cpp_namespace=iree::hal::samples
-  DEPENDS generate_cc_embed_data
-          simple_compute_test_module.emod
-)
-
-add_library(
-  simple_compute_test_module STATIC
-  simple_compute_test_module.cc
+iree_bytecode_module(
+  NAME
+    simple_compute_test_module
+  SRC
+    "simple_compute_test.mlir"
+  CC_NAMESPACE
+    "iree::hal::samples"
 )
 
 iree_cc_test(
@@ -52,9 +37,9 @@
     iree::hal::command_buffer
     iree::hal::command_queue
     iree::hal::driver_registry
+    iree::samples::hal::simple_compute_test_module_cc
     iree::schemas
     # Enabled drivers:
     iree::hal::interpreter::interpreter_driver_module
     iree::hal::vulkan::vulkan_driver_module
-    simple_compute_test_module
 )
diff --git a/iree/samples/rt/CMakeLists.txt b/iree/samples/rt/CMakeLists.txt
index 9689a5a..272a53a 100644
--- a/iree/samples/rt/CMakeLists.txt
+++ b/iree/samples/rt/CMakeLists.txt
@@ -14,28 +14,13 @@
 
 add_subdirectory(vulkan)
 
-add_custom_command(
-  OUTPUT simple_module_test_bytecode_module.emod
-  COMMAND iree-translate
-          --mlir-to-iree-module "${CMAKE_CURRENT_SOURCE_DIR}/simple_module_test.mlir"
-          -o simple_module_test_bytecode_module.emod
-  DEPENDS iree_tools_iree_translate
-)
-
-add_custom_command(
-  OUTPUT simple_module_test_bytecode_module.h simple_module_test_bytecode_module.cc
-  COMMAND generate_cc_embed_data simple_module_test_bytecode_module.emod
-          --output_header=simple_module_test_bytecode_module.h
-          --output_impl=simple_module_test_bytecode_module.cc
-          --identifier=simple_module_test_bytecode_module
-          --cpp_namespace=iree::rt::samples
-  DEPENDS generate_cc_embed_data
-          simple_module_test_bytecode_module.emod
-)
-
-add_library(
-  simple_module_test_bytecode_module STATIC
-  simple_module_test_bytecode_module.cc
+iree_bytecode_module(
+  NAME
+    simple_module_test_bytecode_module
+  SRC
+    "simple_module_test.mlir"
+  CC_NAMESPACE
+    "iree::rt::samples"
 )
 
 iree_cc_test(
@@ -51,6 +36,7 @@
     iree::base::status_matchers
     iree::hal::buffer_view
     iree::hal::driver_registry
+    iree::samples::rt::simple_module_test_bytecode_module_cc
     iree::schemas
     iree::rt
     iree::vm::bytecode_module
@@ -58,5 +44,4 @@
     # Enabled drivers:
     iree::hal::interpreter::interpreter_driver_module
     iree::hal::vulkan::vulkan_driver_module
-    simple_module_test_bytecode_module
 )
diff --git a/iree/samples/rt/vulkan/CMakeLists.txt b/iree/samples/rt/vulkan/CMakeLists.txt
index 8bacc1c..d27feda 100644
--- a/iree/samples/rt/vulkan/CMakeLists.txt
+++ b/iree/samples/rt/vulkan/CMakeLists.txt
@@ -12,28 +12,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-add_custom_command(
-  OUTPUT simple_mul_bytecode_module.emod
-  COMMAND iree-translate
-          --mlir-to-iree-module "${CMAKE_CURRENT_SOURCE_DIR}/simple_mul.mlir"
-          -o simple_mul_bytecode_module.emod
-  DEPENDS iree_tools_iree_translate
-)
-
-add_custom_command(
-  OUTPUT simple_mul_bytecode_module.h simple_mul_bytecode_module.cc
-  COMMAND generate_cc_embed_data simple_mul_bytecode_module.emod
-          --output_header=simple_mul_bytecode_module.h
-          --output_impl=simple_mul_bytecode_module.cc
-          --identifier=simple_mul_bytecode_module
-          --cpp_namespace=iree::rt::samples
-  DEPENDS generate_cc_embed_data
-          simple_mul_bytecode_module.emod
-)
-
-add_library(
-  simple_mul_bytecode_module STATIC
-  simple_mul_bytecode_module.cc
+iree_bytecode_module(
+  NAME
+    simple_mul_bytecode_module
+  SRC
+    "simple_mul.mlir"
+  CC_NAMESPACE
+    "iree::rt::samples"
 )
 
 # Statically link against Vulkan.
@@ -58,8 +43,8 @@
       iree::hal::api
       iree::hal::vulkan::api
       iree::rt::api
+      iree::samples::rt::vulkan::simple_mul_bytecode_module_cc
       iree::vm::api
       SDL2-static
-      simple_mul_bytecode_module
       Vulkan::Vulkan
 )