Make [TARGET_BACKENDS|HAL_DRIVERS]_TO_BUILD functional in CMake. (v2) (#2837)

This reverts commit dfb7633a2d79be6e3bf849148a44b9238afb4bbc.

Clean roll-forward following https://github.com/google/iree/pull/2826 to fix the failing post-submit test.
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b761338..76fa35d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -48,9 +48,9 @@
 
 #TODO: Make this functional!
 set(IREE_HAL_DRIVERS_TO_BUILD "all"
-  CACHE STRING "Semicolon-separated list of HAL drivers to build, or \"all\"." FORCE)
+  CACHE STRING "Semicolon-separated list of HAL drivers to build, or \"all\".")
 set(IREE_TARGET_BACKENDS_TO_BUILD "all"
-  CACHE STRING "Semicolon-separated list of target backends to build, or \"all\"." FORCE)
+  CACHE STRING "Semicolon-separated list of target backends to build, or \"all\".")
 # LINT.ThenChange(
 #   https://github.com/google/iree/tree/main/build_tools/cmake/iree_cross_compile.cmake:iree_cross_compile_options,
 #   https://github.com/google/iree/tree/main/build_tools/cmake/iree_cross_compile.cmake:iree_cross_compile_invoke
@@ -87,8 +87,8 @@
 set(IREE_ALL_HAL_DRIVERS
   DyLib
   LLVM
-  Vulkan
   VMLA
+  Vulkan
 )
 
 if( IREE_HAL_DRIVERS_TO_BUILD STREQUAL "all" )
@@ -99,7 +99,7 @@
     list(REMOVE_ITEM IREE_HAL_DRIVERS_TO_BUILD LLVM DyLib)
   endif()
 endif()
-message(STATUS "Building HAL drivers ${IREE_HAL_DRIVERS_TO_BUILD}")
+message(STATUS "Building HAL drivers: ${IREE_HAL_DRIVERS_TO_BUILD}")
 
 # Default every IREE_HAL_DRIVER_* to OFF
 foreach(_backend ${IREE_ALL_HAL_DRIVERS})
@@ -113,6 +113,20 @@
   set(IREE_HAL_DRIVER_${uppercase_backend} ON CACHE BOOL "" FORCE)
 endforeach()
 
+# Enable HAL driver modules based on options.
+set (IREE_HAL_DRIVER_MODULES "")
+if(${IREE_HAL_DRIVER_DYLIB})
+  list(APPEND IREE_HAL_DRIVER_MODULES iree::hal::dylib::dylib_driver_module)
+endif()
+if(${IREE_HAL_DRIVER_LLVM})
+  list(APPEND IREE_HAL_DRIVER_MODULES iree::hal::llvmjit::llvmjit_driver_module)
+endif()
+if(${IREE_HAL_DRIVER_VMLA})
+  list(APPEND IREE_HAL_DRIVER_MODULES iree::hal::vmla::vmla_driver_module)
+endif()
+if(${IREE_HAL_DRIVER_VULKAN})
+  list(APPEND IREE_HAL_DRIVER_MODULES iree::hal::vulkan::vulkan_driver_module)
+endif()
 
 # List of all target backends to be built by default:
 set(IREE_ALL_TARGET_BACKENDS
@@ -125,7 +139,7 @@
 if( IREE_TARGET_BACKENDS_TO_BUILD STREQUAL "all" )
   set( IREE_TARGET_BACKENDS_TO_BUILD ${IREE_ALL_TARGET_BACKENDS} )
 endif()
-message(STATUS "Building target backends ${IREE_TARGET_BACKENDS_TO_BUILD}")
+message(STATUS "Building target backends: ${IREE_TARGET_BACKENDS_TO_BUILD}")
 
 # Default every IREE_TARGET_BACKEND_* to OFF
 foreach(_backend ${IREE_ALL_TARGET_BACKENDS})
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py
index bc40c97..d63b168 100644
--- a/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py
+++ b/build_tools/bazel_to_cmake/bazel_to_cmake_converter.py
@@ -630,17 +630,27 @@
                             f"{labels_block}"
                             f")\n\n")
 
+  def iree_cmake_extra_content(self, content, inline=False):
+    if inline:
+      self.converter.body += (f"\n{content}\n")
+    else:
+      self.converter.header += (f"\n{content}\n")
 
 class Converter(object):
   """Conversion state tracking and full file template substitution."""
 
   def __init__(self):
+    # Header appears after the license block but before `iree_add_all_subdirs`.
+    self.header = ""
+    # Body appears after `iree_add_all_subdirs`.
     self.body = ""
+
     self.first_error = None
 
   def convert(self, copyright_line):
     converted_content = (f"{copyright_line}\n"
                          f"{self.apache_license}\n\n"
+                         f"{self.header}\n\n"
                          f"iree_add_all_subdirs()\n\n"
                          f"{self.body}")
 
diff --git a/build_tools/cmake/iree_cc_test.cmake b/build_tools/cmake/iree_cc_test.cmake
index ccd170a..f5acfdd 100644
--- a/build_tools/cmake/iree_cc_test.cmake
+++ b/build_tools/cmake/iree_cc_test.cmake
@@ -146,6 +146,7 @@
         "${CMAKE_BINARY_DIR}"
       )
     set_property(TEST ${_TEST_NAME} PROPERTY ENVIRONMENT "TEST_TMPDIR=${CMAKE_BINARY_DIR}/${_NAME}_test_tmpdir")
+    iree_add_test_environment_properties(${_TEST_NAME})
   endif(ANDROID)
 
   list(APPEND _RULE_LABELS "${_PACKAGE_PATH}")
diff --git a/build_tools/cmake/iree_check_test.cmake b/build_tools/cmake/iree_check_test.cmake
index 93fd934..d4f695b 100644
--- a/build_tools/cmake/iree_check_test.cmake
+++ b/build_tools/cmake/iree_check_test.cmake
@@ -121,6 +121,7 @@
         TEST_EXECUTABLE=$<TARGET_FILE:iree_modules_check_iree-check-module>
     )
     set_property(TEST ${_TEST_NAME} PROPERTY ENVIRONMENT ${_ENVIRONMENT_VARS})
+    iree_add_test_environment_properties(${_TEST_NAME})
   else(ANDROID)
     add_test(
       NAME
@@ -133,6 +134,7 @@
         ${_RULE_RUNNER_ARGS}
     )
     set_property(TEST "${_TEST_NAME}" PROPERTY ENVIRONMENT "TEST_TMPDIR=${_NAME}_test_tmpdir")
+    iree_add_test_environment_properties(${_TEST_NAME})
   endif(ANDROID)
 
   list(APPEND _RULE_LABELS "${_PACKAGE_PATH}" "driver=${_RULE_DRIVER}")
@@ -173,12 +175,12 @@
     ${ARGN}
   )
 
-
+  # Omit tests for which the specified driver or target backend is not enabled.
+  # This overlaps with directory exclusions and other filtering mechanisms.
   string(TOUPPER ${_RULE_DRIVER} _UPPERCASE_DRIVER)
   if(NOT IREE_HAL_DRIVER_${_UPPERCASE_DRIVER})
     return()
   endif()
-
   string(TOUPPER ${_RULE_TARGET_BACKEND} _UPPERCASE_TARGET_BACKEND)
   if(NOT IREE_TARGET_BACKEND_${_UPPERCASE_TARGET_BACKEND})
     return()
diff --git a/build_tools/cmake/iree_lit_test.cmake b/build_tools/cmake/iree_lit_test.cmake
index b841566..609e242 100644
--- a/build_tools/cmake/iree_lit_test.cmake
+++ b/build_tools/cmake/iree_lit_test.cmake
@@ -82,9 +82,10 @@
   )
 
   list(APPEND _RULE_LABELS "${_PACKAGE_PATH}")
-  set_property(TEST ${_NAME_PATH} PROPERTY ENVIRONMENT "TEST_TMPDIR=${_NAME}_test_tmpdir")
   set_property(TEST ${_NAME_PATH} PROPERTY LABELS "${_RULE_LABELS}")
   set_property(TEST ${_NAME_PATH} PROPERTY REQUIRED_FILES "${_TEST_FILE_PATH}")
+  set_property(TEST ${_NAME_PATH} PROPERTY ENVIRONMENT "TEST_TMPDIR=${_NAME}_test_tmpdir")
+  iree_add_test_environment_properties(${_NAME_PATH})
 
   # TODO(gcmn): Figure out how to indicate a dependency on _RULE_DATA being built
 endfunction()
diff --git a/build_tools/cmake/iree_macros.cmake b/build_tools/cmake/iree_macros.cmake
index 36bd5be..b1e70d4 100644
--- a/build_tools/cmake/iree_macros.cmake
+++ b/build_tools/cmake/iree_macros.cmake
@@ -252,3 +252,31 @@
     add_dependencies(${EXECUTABLE} ${DEPENDENCY})
   endif()
 endfunction()
+
+#-------------------------------------------------------------------------------
+# Tests
+#-------------------------------------------------------------------------------
+
+# iree_add_test_environment_properties
+#
+# Adds test environment variable properties based on the current build options.
+#
+# Parameters:
+# TEST_NAME: the test name, e.g. iree/base:ref_ptr_test
+function(iree_add_test_environment_properties TEST_NAME)
+  # IREE_*_DISABLE environment variables may used to skip test cases which
+  # require both a compiler target backend and compatible runtime HAL driver.
+  #
+  # These variables may be set by the test environment, typically as a property
+  # of some continuous execution test runner or by an individual developer, or
+  # here by the build system.
+  #
+  # Tests which only depend on a compiler target backend or a runtime HAL
+  # driver, but not both, should generally use a different method of filtering.
+  if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV} OR NOT ${IREE_HAL_DRIVER_VULKAN})
+    set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "IREE_VULKAN_DISABLE=1")
+  endif()
+  if(NOT ${IREE_TARGET_BACKEND_LLVM-IR} OR NOT ${IREE_HAL_DRIVER_LLVM})
+    set_property(TEST ${TEST_NAME} APPEND PROPERTY ENVIRONMENT "IREE_LLVMJIT_DISABLE=1")
+  endif()
+endfunction()
diff --git a/docs/get_started/cmake_options_and_variables.md b/docs/get_started/cmake_options_and_variables.md
index 3f3dbdd..77dfa1d 100644
--- a/docs/get_started/cmake_options_and_variables.md
+++ b/docs/get_started/cmake_options_and_variables.md
@@ -63,21 +63,16 @@
 
 #### `IREE_HAL_DRIVERS_TO_BUILD`:STRING
 
-*Righ now this only affects whether tests are enabled when compiling for
-Android; it will be fully supported in the future!*
-
 Semicolon-separated list of HAL drivers to build, or `all` for building all HAL
-drivers. Case-insensitive. Defaults to `all`. Example:
-`-DIREE_HAL_DRIVERS_TO_BUILD="Vulkan;VMLA"`.
+drivers. Case-insensitive. If an empty list is provided, will build no HAL
+drivers. Defaults to `all`. Example: `-DIREE_HAL_DRIVERS_TO_BUILD=Vulkan;VMLA`.
 
 #### `IREE_TARGET_BACKENDS_TO_BUILD`:STRING
 
-*Righ now this only affects whether tests are enabled when compiling for
-Android; it will be fully supported in the future!*
-
-Semicolon-separated list of HAL drivers to build, or `all` for building all
-compiler target backends. Case-insensitive. Defaults to `all`. Example:
-`-DIREE_HAL_DRIVERS_TO_BUILD="Vulkan-SPIRV;VMLA"`.
+Semicolon-separated list of target backend to build, or `all` for building all
+compiler target backends. Case-insensitive. If an empty list is provided, will
+build no target backends. Defaults to `all`. Example:
+`-DIREE_TARGET_BACKENDS_TO_BUILD=Vulkan-SPIRV;VMLA`.
 
 #### `IREE_ENABLE_LLD`:BOOL
 
diff --git a/iree/build_defs.oss.bzl b/iree/build_defs.oss.bzl
index a8586b2..65a4d4d 100644
--- a/iree/build_defs.oss.bzl
+++ b/iree/build_defs.oss.bzl
@@ -94,3 +94,16 @@
         ],
         **kwargs
     )
+
+def iree_cmake_extra_content(content = "", inline = False):
+    """Tool for inserting arbitrary content during Bazel->CMake conversion.
+
+    This does nothing in Bazel, while the contents are inserted as-is in
+    converted CMakeLists.txt files.
+
+    Args:
+      content: The text to insert into the converted file.
+      inline: If true, the content will be inserted inline. Otherwise, it will
+        be inserted near the top of the converted file.
+    """
+    pass
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD
index 0f6be4a..e0cbfb9 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/BUILD
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/BUILD
@@ -11,8 +11,8 @@
 # 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.
-#
-load("//iree:build_defs.oss.bzl", "platform_trampoline_deps")
+
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content", "platform_trampoline_deps")
 
 package(
     default_visibility = ["//visibility:public"],
@@ -20,6 +20,16 @@
     licenses = ["notice"],  # Apache 2.0
 )
 
+# TODO(scotttodd): add 'common', 'JIT', 'AOT' subfolders to filter on
+#     IREE_TARGET_BACKEND_[DYLIB-LLVM-AOT|LLVM-IR]
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_LLVM-IR})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "LLVMIR",
     srcs = [
diff --git a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
index 0ee00e4..8a1d4e5 100644
--- a/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/Target/LLVM/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_LLVM-IR})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/compiler/Dialect/HAL/Target/VMLA/BUILD b/iree/compiler/Dialect/HAL/Target/VMLA/BUILD
index 46ed3e2..99bcc9f 100644
--- a/iree/compiler/Dialect/HAL/Target/VMLA/BUILD
+++ b/iree/compiler/Dialect/HAL/Target/VMLA/BUILD
@@ -12,12 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
+
 package(
     default_visibility = ["//visibility:public"],
     features = ["layering_check"],
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_VMLA})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "VMLA",
     srcs = [
diff --git a/iree/compiler/Dialect/HAL/Target/VMLA/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/VMLA/CMakeLists.txt
index d65b7eb..a58e645 100644
--- a/iree/compiler/Dialect/HAL/Target/VMLA/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/Target/VMLA/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VMLA})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/BUILD b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/BUILD
index db815ab..f4bdf08 100644
--- a/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/BUILD
+++ b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/BUILD
@@ -12,12 +12,22 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
+
 package(
     default_visibility = ["//visibility:public"],
     features = ["layering_check"],
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "VulkanSPIRV",
     srcs = [
diff --git a/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/CMakeLists.txt
index 6e649b0..5764276 100644
--- a/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/CMakeLists.txt
+++ b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/compiler/Dialect/HAL/Target/test/BUILD b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/BUILD
similarity index 96%
rename from iree/compiler/Dialect/HAL/Target/test/BUILD
rename to iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/BUILD
index b780b11..bb9c0e0 100644
--- a/iree/compiler/Dialect/HAL/Target/test/BUILD
+++ b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/BUILD
@@ -1,4 +1,4 @@
-# Copyright 2019 Google LLC
+# 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.
diff --git a/iree/compiler/Dialect/HAL/Target/test/CMakeLists.txt b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/CMakeLists.txt
similarity index 100%
rename from iree/compiler/Dialect/HAL/Target/test/CMakeLists.txt
rename to iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/CMakeLists.txt
diff --git a/iree/compiler/Dialect/HAL/Target/test/smoketest.mlir b/iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/smoketest.mlir
similarity index 100%
rename from iree/compiler/Dialect/HAL/Target/test/smoketest.mlir
rename to iree/compiler/Dialect/HAL/Target/VulkanSPIRV/test/smoketest.mlir
diff --git a/iree/compiler/Dialect/Vulkan/Utils/test/BUILD b/iree/compiler/Dialect/Vulkan/Utils/test/BUILD
index bb9c0e0..e83bb2f 100644
--- a/iree/compiler/Dialect/Vulkan/Utils/test/BUILD
+++ b/iree/compiler/Dialect/Vulkan/Utils/test/BUILD
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
 load("//iree:lit_test.bzl", "iree_lit_test_suite")
 
 package(
@@ -20,6 +21,14 @@
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV})
+  return()
+endif()
+""",
+)
+
 iree_lit_test_suite(
     name = "lit",
     srcs = glob(["*.mlir"]),
diff --git a/iree/compiler/Dialect/Vulkan/Utils/test/CMakeLists.txt b/iree/compiler/Dialect/Vulkan/Utils/test/CMakeLists.txt
index fcc538b..50453b1 100644
--- a/iree/compiler/Dialect/Vulkan/Utils/test/CMakeLists.txt
+++ b/iree/compiler/Dialect/Vulkan/Utils/test/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 file(GLOB _GLOB_X_MLIR LIST_DIRECTORIES false RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} CONFIGURE_DEPENDS *.mlir)
diff --git a/iree/hal/cts/CMakeLists.txt b/iree/hal/cts/CMakeLists.txt
index 08e05a8..3ec336e 100644
--- a/iree/hal/cts/CMakeLists.txt
+++ b/iree/hal/cts/CMakeLists.txt
@@ -14,6 +14,8 @@
 
 iree_add_all_subdirs()
 
+# bazel_to_cmake: DO NOT EDIT, IREE_HAL_DRIVER_MODULES is custom logic
+
 iree_cc_library(
   NAME
     cts_test_base
@@ -25,11 +27,8 @@
     iree::base::status
     iree::base::status_matchers
     iree::hal::driver_registry
-    iree::hal::dylib::dylib_driver_module
-    iree::hal::llvmjit::llvmjit_driver_module
-    iree::hal::vmla::vmla_driver_module
-    iree::hal::vulkan::vulkan_driver_module
     iree::testing::gtest_main
+    ${IREE_HAL_DRIVER_MODULES}
   TESTONLY
   PUBLIC
 )
diff --git a/iree/hal/dylib/BUILD b/iree/hal/dylib/BUILD
index fc3ccb9..d31cf97 100644
--- a/iree/hal/dylib/BUILD
+++ b/iree/hal/dylib/BUILD
@@ -14,12 +14,22 @@
 
 # HAL implementation for executing functions provided by dynamic libraries.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
+
 package(
     default_visibility = ["//visibility:public"],
     features = ["layering_check"],
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_HAL_DRIVER_DYLIB})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "dylib_device",
     srcs = ["dylib_device.cc"],
diff --git a/iree/hal/dylib/CMakeLists.txt b/iree/hal/dylib/CMakeLists.txt
index d720435..9308efd 100644
--- a/iree/hal/dylib/CMakeLists.txt
+++ b/iree/hal/dylib/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_HAL_DRIVER_DYLIB})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/hal/llvmjit/BUILD b/iree/hal/llvmjit/BUILD
index 3ebd609..138b561 100644
--- a/iree/hal/llvmjit/BUILD
+++ b/iree/hal/llvmjit/BUILD
@@ -14,12 +14,22 @@
 
 # HAL implementation for jitting CPU code from LLVMIR.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
+
 package(
     default_visibility = ["//visibility:public"],
     features = ["layering_check"],
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_HAL_DRIVER_LLVM})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "llvmjit_device",
     srcs = ["llvmjit_device.cc"],
diff --git a/iree/hal/llvmjit/CMakeLists.txt b/iree/hal/llvmjit/CMakeLists.txt
index ca40941..bfa7a2f 100644
--- a/iree/hal/llvmjit/CMakeLists.txt
+++ b/iree/hal/llvmjit/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_HAL_DRIVER_LLVM})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/hal/vmla/BUILD b/iree/hal/vmla/BUILD
index 35e081a..9832f42 100644
--- a/iree/hal/vmla/BUILD
+++ b/iree/hal/vmla/BUILD
@@ -14,12 +14,22 @@
 
 # A VMLA (VM-based Linear Algebra) runtime HAL backend.
 
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
+
 package(
     default_visibility = ["//visibility:public"],
     features = ["layering_check"],
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_HAL_DRIVER_VMLA})
+  return()
+endif()
+""",
+)
+
 cc_library(
     name = "op_kernels",
     hdrs = ["op_kernels.h"],
diff --git a/iree/hal/vmla/CMakeLists.txt b/iree/hal/vmla/CMakeLists.txt
index cfa8cca..9849689 100644
--- a/iree/hal/vmla/CMakeLists.txt
+++ b/iree/hal/vmla/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_HAL_DRIVER_VMLA})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_cc_library(
diff --git a/iree/hal/vulkan/CMakeLists.txt b/iree/hal/vulkan/CMakeLists.txt
index 78e81f7..5899f79 100644
--- a/iree/hal/vulkan/CMakeLists.txt
+++ b/iree/hal/vulkan/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_HAL_DRIVER_VULKAN})
+  return()
+endif()
+
 set(VMA_SRC_ROOT
   "${IREE_ROOT_DIR}/third_party/vulkan_memory_allocator/src/"
 )
diff --git a/iree/modules/check/CMakeLists.txt b/iree/modules/check/CMakeLists.txt
index 0a016be..c8ae4ca 100644
--- a/iree/modules/check/CMakeLists.txt
+++ b/iree/modules/check/CMakeLists.txt
@@ -14,28 +14,31 @@
 
 iree_add_all_subdirs()
 
-iree_cc_test(
-  NAME
-    check_test
-  SRCS
-    "check_test.cc"
-  DEPS
-    ::native_module
-    absl::core_headers
-    absl::strings
-    iree::base::api
-    iree::base::api_util
-    iree::base::logging
-    iree::base::status
-    iree::base::status_matchers
-    iree::hal::api
-    iree::hal::vmla::vmla_driver_module
-    iree::modules::hal
-    iree::testing::gtest_main
-    iree::vm
-    iree::vm::bytecode_module
-    iree::vm::ref_cc
-)
+# bazel_to_cmake: DO NOT EDIT, IREE_HAL_DRIVER_VMLA filtering is custom logic
+if(${IREE_HAL_DRIVER_VMLA})
+  iree_cc_test(
+    NAME
+      check_test
+    SRCS
+      "check_test.cc"
+    DEPS
+      ::native_module
+      absl::core_headers
+      absl::strings
+      iree::base::api
+      iree::base::api_util
+      iree::base::logging
+      iree::base::status
+      iree::base::status_matchers
+      iree::hal::api
+      iree::hal::vmla::vmla_driver_module
+      iree::modules::hal
+      iree::testing::gtest_main
+      iree::vm
+      iree::vm::bytecode_module
+      iree::vm::ref_cc
+  )
+endif()
 
 iree_cc_binary(
   NAME
@@ -57,13 +60,11 @@
     iree::base::status
     iree::base::target_platform
     iree::base::tracing
-    iree::hal::llvmjit::llvmjit_driver_module
-    iree::hal::vmla::vmla_driver_module
-    iree::hal::vulkan::vulkan_driver_module
     iree::modules::hal
     iree::testing::gtest
     iree::tools::vm_util
     iree::vm::bytecode_module
+    ${IREE_HAL_DRIVER_MODULES}
   TESTONLY
 )
 
diff --git a/iree/samples/custom_modules/BUILD b/iree/samples/custom_modules/BUILD
index 036f5b2..6a3a852 100644
--- a/iree/samples/custom_modules/BUILD
+++ b/iree/samples/custom_modules/BUILD
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 load("//iree/tools:compilation.bzl", "iree_bytecode_module")
+load("//iree:build_defs.oss.bzl", "iree_cmake_extra_content")
 
 package(
     default_visibility = ["//visibility:public"],
@@ -20,6 +21,14 @@
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_VMLA} OR NOT ${IREE_HAL_DRIVER_VMLA})
+  return()
+endif()
+""",
+)
+
 iree_bytecode_module(
     name = "custom_modules_test_module",
     src = "custom_modules_test.mlir",
diff --git a/iree/samples/custom_modules/CMakeLists.txt b/iree/samples/custom_modules/CMakeLists.txt
index b98d0f4..895fab3 100644
--- a/iree/samples/custom_modules/CMakeLists.txt
+++ b/iree/samples/custom_modules/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VMLA} OR NOT ${IREE_HAL_DRIVER_VMLA})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_bytecode_module(
diff --git a/iree/samples/simple_embedding/BUILD b/iree/samples/simple_embedding/BUILD
index 5dad5bf..5b0fc4b 100644
--- a/iree/samples/simple_embedding/BUILD
+++ b/iree/samples/simple_embedding/BUILD
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load("//iree:build_defs.oss.bzl", "PLATFORM_VULKAN_TEST_DEPS")
+load("//iree:build_defs.oss.bzl", "PLATFORM_VULKAN_TEST_DEPS", "iree_cmake_extra_content")
 load("//iree/tools:compilation.bzl", "iree_bytecode_module")
 
 package(
@@ -21,6 +21,15 @@
     licenses = ["notice"],  # Apache 2.0
 )
 
+iree_cmake_extra_content(
+    content = """
+if(NOT ${IREE_TARGET_BACKEND_VMLA} OR NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV}
+   OR NOT ${IREE_HAL_DRIVER_VMLA} OR NOT ${IREE_HAL_DRIVER_VULKAN})
+  return()
+endif()
+""",
+)
+
 iree_bytecode_module(
     name = "simple_embedding_test_bytecode_module",
     src = "simple_embedding_test.mlir",
diff --git a/iree/samples/simple_embedding/CMakeLists.txt b/iree/samples/simple_embedding/CMakeLists.txt
index 1001ec8..f60742f 100644
--- a/iree/samples/simple_embedding/CMakeLists.txt
+++ b/iree/samples/simple_embedding/CMakeLists.txt
@@ -12,6 +12,11 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VMLA} OR NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV}
+   OR NOT ${IREE_HAL_DRIVER_VMLA} OR NOT ${IREE_HAL_DRIVER_VULKAN})
+  return()
+endif()
+
 iree_add_all_subdirs()
 
 iree_bytecode_module(
diff --git a/iree/samples/vulkan/CMakeLists.txt b/iree/samples/vulkan/CMakeLists.txt
index 8d83188..9d2ab0a 100644
--- a/iree/samples/vulkan/CMakeLists.txt
+++ b/iree/samples/vulkan/CMakeLists.txt
@@ -12,6 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+if(NOT ${IREE_TARGET_BACKEND_VULKAN-SPIRV} OR NOT ${IREE_HAL_DRIVER_VULKAN})
+  return()
+endif()
+
 iree_bytecode_module(
   NAME
     simple_mul_bytecode_module
diff --git a/iree/test/e2e/regression/dynamic_abs.mlir b/iree/test/e2e/regression/dynamic_abs.mlir
index 8af3dac..c7dad45 100644
--- a/iree/test/e2e/regression/dynamic_abs.mlir
+++ b/iree/test/e2e/regression/dynamic_abs.mlir
@@ -1,5 +1,5 @@
 // RUN: iree-run-mlir -iree-hal-target-backends=vmla %s | IreeFileCheck %s
-// RUN: iree-run-mlir -iree-hal-target-backends=llvm-ir %s | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir -iree-hal-target-backends=llvm-ir %s | IreeFileCheck %s)
 
 // CHECK-LABEL: EXEC @dynamic_tensor
 func @dynamic_tensor() -> tensor<?x?xf32> attributes { iree.module.export } {
diff --git a/iree/test/e2e/regression/dynamic_add.mlir b/iree/test/e2e/regression/dynamic_add.mlir
index 0c97386..d6837a6 100644
--- a/iree/test/e2e/regression/dynamic_add.mlir
+++ b/iree/test/e2e/regression/dynamic_add.mlir
@@ -1,5 +1,6 @@
+// RUN: iree-run-mlir -iree-hal-target-backends=vmla -input-value="2x4xf32=[[1.0, 2.0, 3.0, 4.0], [-1.0, -2.0, -3.0, -4.0]]" -input-value="2x4xf32=[[5.0, 6.0, 7.0, 8.0], [-5.0, -6.0, -7.0, -8.0]]" %s | IreeFileCheck %s
 // RUN: [[ $IREE_VULKAN_DISABLE == 1 ]] || (iree-run-mlir -iree-hal-target-backends=vulkan-spirv -input-value="2x4xf32=[[1.0, 2.0, 3.0, 4.0], [-1.0, -2.0, -3.0, -4.0]]" -input-value="2x4xf32=[[5.0, 6.0, 7.0, 8.0], [-5.0, -6.0, -7.0, -8.0]]" %s | IreeFileCheck %s)
-// RUN: iree-run-mlir -iree-hal-target-backends=llvm-ir -input-value="2x4xf32=[[1.0, 2.0, 3.0, 4.0], [-1.0, -2.0, -3.0, -4.0]]" -input-value="2x4xf32=[[5.0, 6.0, 7.0, 8.0], [-5.0, -6.0, -7.0, -8.0]]" %s | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir -iree-hal-target-backends=llvm-ir -input-value="2x4xf32=[[1.0, 2.0, 3.0, 4.0], [-1.0, -2.0, -3.0, -4.0]]" -input-value="2x4xf32=[[5.0, 6.0, 7.0, 8.0], [-5.0, -6.0, -7.0, -8.0]]" %s | IreeFileCheck %s)
 
 // CHECK: EXEC @main
 // CHECK: 2x4xf32=[6 8 10 12][-6 -8 -10 -12]
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir
index ce42e31..93ea402 100644
--- a/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir
+++ b/iree/test/e2e/regression/dynamic_torch_index_select_high_rank.mlir
@@ -1,4 +1,4 @@
-// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2xi32=[6, 7] [8, 9]" -input-value="2x2x2x2xi32=[[[0, 1] [1, 0]] [[0, 0] [1, 1]]] [[[1, 1] [0, 0]] [[0, 1] [1, 0]]]" | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2xi32=[6, 7] [8, 9]" -input-value="2x2x2x2xi32=[[[0, 1] [1, 0]] [[0, 0] [1, 1]]] [[[1, 1] [0, 0]] [[0, 1] [1, 0]]]" | IreeFileCheck %s)
 
 // CHECK-LABEL: EXEC @torch_index_select1
 func @torch_index_select1(%arg0: tensor<?x?xi32>, %arg1: tensor<?x?x?x?xi32>) -> tensor<?x?x?x?xi32> attributes {iree.module.export} {
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir
index 0755b5c..c7004ee 100644
--- a/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir
+++ b/iree/test/e2e/regression/dynamic_torch_index_select_negative.mlir
@@ -1,4 +1,4 @@
-// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2x2xi32=[[100, 101] [110, 111]] [[200, 201] [210, 211]]" -input-value="2x2x2xi32=[[0, 1] [1, 0]] [[0, 0] [1, 1]]" | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="2x2x2xi32=[[100, 101] [110, 111]] [[200, 201] [210, 211]]" -input-value="2x2x2xi32=[[0, 1] [1, 0]] [[0, 0] [1, 1]]" | IreeFileCheck %s)
 
 // CHECK-LABEL: EXEC @torch_index_select1
 func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<?x?x?xi32>) -> tensor<?x?x?xi32> attributes {iree.module.export} {
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir
index 8ccb4fa..a8e2e6e 100644
--- a/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir
+++ b/iree/test/e2e/regression/dynamic_torch_index_select_scalar.mlir
@@ -1,4 +1,5 @@
-// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="5x1x5xi32=[[1,2,3,4,5]] [[6,7,8,9,10]] [[11,12,13,14,15]] [[16,17,18,19,20]] [[21,22,23,24,25]]" -input-value="i32=0" | IreeFileCheck %s
+// RUN: iree-run-mlir %s -iree-hal-target-backends=vmla -input-value="5x1x5xi32=[[1,2,3,4,5]] [[6,7,8,9,10]] [[11,12,13,14,15]] [[16,17,18,19,20]] [[21,22,23,24,25]]" -input-value="i32=0" | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="5x1x5xi32=[[1,2,3,4,5]] [[6,7,8,9,10]] [[11,12,13,14,15]] [[16,17,18,19,20]] [[21,22,23,24,25]]" -input-value="i32=0" | IreeFileCheck %s)
 
 // CHECK-LABEL: EXEC @torch_index_select1
 func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<i32>) -> tensor<?x?xi32> attributes {iree.module.export} {
diff --git a/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir b/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir
index d22ccc7..534c59a 100644
--- a/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir
+++ b/iree/test/e2e/regression/dynamic_torch_index_select_vector.mlir
@@ -1,4 +1,5 @@
-// RUN: iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="3x2x2xi32=[[1, 2] [3, 4]] [[5, 6] [7, 8]] [[9, 10] [11, 12]]" -input-value="2xi32=[0, 1]" | IreeFileCheck %s
+// RUN: iree-run-mlir %s -iree-hal-target-backends=vmla -input-value="3x2x2xi32=[[1, 2] [3, 4]] [[5, 6] [7, 8]] [[9, 10] [11, 12]]" -input-value="2xi32=[0, 1]" | IreeFileCheck %s
+// RUN: [[ $IREE_LLVMJIT_DISABLE == 1 ]] || (iree-run-mlir %s -iree-hal-target-backends=llvm-ir -input-value="3x2x2xi32=[[1, 2] [3, 4]] [[5, 6] [7, 8]] [[9, 10] [11, 12]]" -input-value="2xi32=[0, 1]" | IreeFileCheck %s)
 
 // CHECK-LABEL: EXEC @torch_index_select1
 func @torch_index_select1(%arg0: tensor<?x?x?xi32>, %arg1: tensor<?xi32>) -> tensor<?x?x?xi32> attributes {iree.module.export} {
diff --git a/iree/tools/BUILD b/iree/tools/BUILD
index a3b5a9f..052ccfc 100644
--- a/iree/tools/BUILD
+++ b/iree/tools/BUILD
@@ -143,7 +143,14 @@
 
 cc_library(
     name = "init_targets",
+    srcs = ["init_targets.cc"],
     hdrs = ["init_targets.h"],
+    copts = [
+        "-DIREE_HAVE_LLVMAOT_TARGET",
+        "-DIREE_HAVE_LLVMIR_TARGET",
+        "-DIREE_HAVE_VMLA_TARGET",
+        "-DIREE_HAVE_VULKANSPIRV_TARGET",
+    ],
     deps = [
         "//iree/compiler/Dialect/HAL/Target/LLVM:LLVMAOT",
         "//iree/compiler/Dialect/HAL/Target/LLVM:LLVMIR",
diff --git a/iree/tools/CMakeLists.txt b/iree/tools/CMakeLists.txt
index b3a4fa9..c9e7bbf 100644
--- a/iree/tools/CMakeLists.txt
+++ b/iree/tools/CMakeLists.txt
@@ -12,17 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+# bazel_to_cmake: DO NOT EDIT (Special logic is used throughout this file)
+
 add_subdirectory(test)
 
-# TODO: iree_select_target_platform macros.
-# TODO: skip targets disabled by options.
-iree_select_compiler_opts(IREE_HAL_DRIVER_MODULES
-  ALL
-    "iree::hal::dylib::dylib_driver_module"
-    "iree::hal::llvmjit::llvmjit_driver_module"
-    "iree::hal::vmla::vmla_driver_module"
-    "iree::hal::vulkan::vulkan_driver_module"
-)
+# Enable compiler targets based on options.
+set(IREE_COMPILER_TARGETS "")
+set(IREE_COMPILER_TARGET_COPTS "")
+# TODO(#2645): Move LLVMAOT target under DYLIB-LLVM-AOT flag
+if(${IREE_TARGET_BACKEND_LLVM-IR})
+  list(APPEND IREE_COMPILER_TARGETS iree::compiler::Dialect::HAL::Target::LLVM::LLVMAOT)
+  list(APPEND IREE_COMPILER_TARGET_COPTS "-DIREE_HAVE_LLVMAOT_TARGET")
+  list(APPEND IREE_COMPILER_TARGETS iree::compiler::Dialect::HAL::Target::LLVM::LLVMIR)
+  list(APPEND IREE_COMPILER_TARGET_COPTS "-DIREE_HAVE_LLVMIR_TARGET")
+endif()
+if(${IREE_TARGET_BACKEND_VMLA})
+  list(APPEND IREE_COMPILER_TARGETS iree::compiler::Dialect::HAL::Target::VMLA)
+  list(APPEND IREE_COMPILER_TARGET_COPTS "-DIREE_HAVE_VMLA_TARGET")
+endif()
+if(${IREE_TARGET_BACKEND_VULKAN-SPIRV})
+  list(APPEND IREE_COMPILER_TARGETS iree::compiler::Dialect::HAL::Target::VulkanSPIRV)
+  list(APPEND IREE_COMPILER_TARGET_COPTS "-DIREE_HAVE_VULKANSPIRV_TARGET")
+endif()
 
 if(IREE_ENABLE_EMITC)
   set(IREE_OPT_CONDITIONAL_DEPS
@@ -195,11 +206,12 @@
       init_targets
     HDRS
       "init_targets.h"
+    SRCS
+      "init_targets.cc"
     DEPS
-      iree::compiler::Dialect::HAL::Target::LLVM::LLVMAOT
-      iree::compiler::Dialect::HAL::Target::LLVM::LLVMIR
-      iree::compiler::Dialect::HAL::Target::VMLA
-      iree::compiler::Dialect::HAL::Target::VulkanSPIRV
+      ${IREE_COMPILER_TARGETS}
+    COPTS
+      ${IREE_COMPILER_TARGET_COPTS}
     PUBLIC
   )
 
diff --git a/iree/tools/init_targets.cc b/iree/tools/init_targets.cc
new file mode 100644
index 0000000..c0b4c4f
--- /dev/null
+++ b/iree/tools/init_targets.cc
@@ -0,0 +1,62 @@
+// 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 "iree/tools/init_targets.h"
+
+#ifdef IREE_HAVE_LLVMAOT_TARGET
+#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.h"
+#endif
+#ifdef IREE_HAVE_LLVMIR_TARGET
+#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.h"
+#endif
+#ifdef IREE_HAVE_VMLA_TARGET
+#include "iree/compiler/Dialect/HAL/Target/VMLA/VMLATarget.h"
+#endif
+#ifdef IREE_HAVE_VULKANSPIRV_TARGET
+#include "iree/compiler/Dialect/HAL/Target/VulkanSPIRV/VulkanSPIRVTarget.h"
+#endif
+
+namespace mlir {
+namespace iree_compiler {
+
+// This function should be called before creating any MLIRContext if one
+// expects all the possible target backends to be available. Custom tools can
+// select which targets they want to support by only registering those they
+// need.
+void registerHALTargetBackends() {
+  static bool init_once = []() {
+
+#ifdef IREE_HAVE_LLVMAOT_TARGET
+    IREE::HAL::registerLLVMAOTTargetBackends(
+        []() { return IREE::HAL::getLLVMTargetOptionsFromFlags(); });
+#endif
+#ifdef IREE_HAVE_LLVMIR_TARGET
+    IREE::HAL::registerLLVMIRTargetBackends(
+        []() { return IREE::HAL::getLLVMTargetOptionsFromFlags(); });
+#endif
+#ifdef IREE_HAVE_VMLA_TARGET
+    IREE::HAL::registerVMLATargetBackends(
+        []() { return IREE::HAL::getVMLATargetOptionsFromFlags(); });
+#endif
+#ifdef IREE_HAVE_VULKANSPIRV_TARGET
+    IREE::HAL::registerVulkanSPIRVTargetBackends(
+        []() { return IREE::HAL::getVulkanSPIRVTargetOptionsFromFlags(); });
+#endif
+    return true;
+  }();
+  (void)init_once;
+}
+
+}  // namespace iree_compiler
+}  // namespace mlir
diff --git a/iree/tools/init_targets.h b/iree/tools/init_targets.h
index 6f1b11f..ed48e0b 100644
--- a/iree/tools/init_targets.h
+++ b/iree/tools/init_targets.h
@@ -15,11 +15,6 @@
 #ifndef IREE_TOOLS_INIT_TARGETS_H_
 #define IREE_TOOLS_INIT_TARGETS_H_
 
-#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMAOTTarget.h"
-#include "iree/compiler/Dialect/HAL/Target/LLVM/LLVMIRTarget.h"
-#include "iree/compiler/Dialect/HAL/Target/VMLA/VMLATarget.h"
-#include "iree/compiler/Dialect/HAL/Target/VulkanSPIRV/VulkanSPIRVTarget.h"
-
 namespace mlir {
 namespace iree_compiler {
 
@@ -27,20 +22,7 @@
 // expects all the possible target backends to be available. Custom tools can
 // select which targets they want to support by only registering those they
 // need.
-inline void registerHALTargetBackends() {
-  static bool init_once = []() {
-    IREE::HAL::registerLLVMAOTTargetBackends(
-        []() { return IREE::HAL::getLLVMTargetOptionsFromFlags(); });
-    IREE::HAL::registerLLVMIRTargetBackends(
-        []() { return IREE::HAL::getLLVMTargetOptionsFromFlags(); });
-    IREE::HAL::registerVMLATargetBackends(
-        []() { return IREE::HAL::getVMLATargetOptionsFromFlags(); });
-    IREE::HAL::registerVulkanSPIRVTargetBackends(
-        []() { return IREE::HAL::getVulkanSPIRVTargetOptionsFromFlags(); });
-    return true;
-  }();
-  (void)init_once;
-}
+void registerHALTargetBackends();
 
 }  // namespace iree_compiler
 }  // namespace mlir