Add testonly support to iree_cc_binary.cmake

PiperOrigin-RevId: 298896906
diff --git a/build_tools/bazel_to_cmake/bazel_to_cmake.py b/build_tools/bazel_to_cmake/bazel_to_cmake.py
index b27f1be..82687a9 100755
--- a/build_tools/bazel_to_cmake/bazel_to_cmake.py
+++ b/build_tools/bazel_to_cmake/bazel_to_cmake.py
@@ -416,20 +416,28 @@
     "deps_block": deps_block,
     }
 
-  def cc_binary(self, name, srcs=None, deps=None, linkopts=None, **kwargs):
+  def cc_binary(self,
+                name,
+                srcs=None,
+                deps=None,
+                linkopts=None,
+                testonly=False,
+                **kwargs):
     if linkopts:
       self._convert_unimplemented_function("linkopts")
     name_block = self._convert_name_block(name)
     out_block = self._convert_out_block(name)
     srcs_block = self._convert_srcs_block(srcs)
     deps_block = self._convert_deps_block(deps)
+    testonly_block = self._convert_testonly_block(testonly)
 
     self.converter.body += """iree_cc_binary(
-%(name_block)s%(out_block)s%(srcs_block)s%(deps_block)s)\n\n""" % {
+%(name_block)s%(out_block)s%(srcs_block)s%(deps_block)s%(testonly_block)s)\n\n""" % {
     "name_block": name_block,
     "out_block": out_block,
     "srcs_block": srcs_block,
     "deps_block": deps_block,
+    "testonly_block": testonly_block,
     }
 
   def cc_embed_data(self,
diff --git a/build_tools/cmake/iree_cc_binary.cmake b/build_tools/cmake/iree_cc_binary.cmake
index 2089727..1afea94 100644
--- a/build_tools/cmake/iree_cc_binary.cmake
+++ b/build_tools/cmake/iree_cc_binary.cmake
@@ -1,253 +1,255 @@
-# 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)

-

-if (NOT DEFINED _IREE_CC_BINARY_NAMES)

-  set(_IREE_CC_BINARY_NAMES "")

-endif()

-

-# iree_cc_binary()

-#

-# CMake function to imitate Bazel's cc_binary rule.

-#

-# Parameters:

-# NAME: name of target (see Usage below)

-# SRCS: List of source files for the binary

-# DEPS: List of other libraries to be linked in to the binary targets

-# COPTS: List of private compile options

-# DEFINES: List of public defines

-# LINKOPTS: List of link options

-#

-# Note:

-# By default, iree_cc_binary will always create a binary named iree_${NAME}.

-#

-# Usage:

-# iree_cc_library(

-#   NAME

-#     awesome

-#   HDRS

-#     "a.h"

-#   SRCS

-#     "a.cc"

-#   PUBLIC

-# )

-#

-# iree_cc_binary(

-#   NAME

-#     awesome_tool

-#   OUT

-#     awesome-tool

-#   SRCS

-#     "awesome_tool_main.cc"

-#   DEPS

-#     iree::awesome

-# )

-function(iree_cc_binary)

-  cmake_parse_arguments(

-    _RULE

-    ""

-    "NAME;OUT"

-    "SRCS;COPTS;DEFINES;LINKOPTS;DEPS"

-    ${ARGN}

-  )

-

-  # Prefix the library with the package name, so we get: iree_package_name

-  iree_package_name(_PACKAGE_NAME)

-  set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")

-

-  add_executable(${_NAME} "")

-  add_executable(${_RULE_NAME} ALIAS ${_NAME})

-  if(_RULE_SRCS)

-    target_sources(${_NAME}

-      PRIVATE

-        ${_RULE_SRCS}

-    )

-  else()

-    set(_DUMMY_SRC "${CMAKE_CURRENT_BINARY_DIR}/${_NAME}_dummy.cc")

-    file(WRITE ${_DUMMY_SRC} "")

-    target_sources(${_NAME}

-      PRIVATE

-        ${_DUMMY_SRC}

-    )

-  endif()

-  if(_RULE_OUT)

-    set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_OUT}")

-  else()

-    set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_NAME}")

-  endif()

-  target_include_directories(${_NAME}

-    PUBLIC

-      ${IREE_COMMON_INCLUDE_DIRS}

-    PRIVATE

-      ${GTEST_INCLUDE_DIRS}

-  )

-  target_compile_definitions(${_NAME}

-    PUBLIC

-      ${_RULE_DEFINES}

-  )

-  target_compile_options(${_NAME}

-    PRIVATE

-      ${_RULE_COPTS}

-  )

-

-  iree_package_ns(_PACKAGE_NS)

-  # Replace dependencies passed by ::name with ::iree::package::name

-  list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::")

-

-  # Add all IREE targets to a folder in the IDE for organization.

-  set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER}/binaries)

-

-  set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${IREE_CXX_STANDARD})

-  set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)

-

-  # Defer computing transitive dependencies and calling target_link_libraries()

-  # until all libraries have been declared.

-  # Track target and deps, use in iree_complete_binary_link_options() later.

-  set_property(GLOBAL APPEND PROPERTY _IREE_CC_BINARY_NAMES "${_NAME}")

-  set_property(TARGET ${_NAME} PROPERTY DIRECT_DEPS ${_RULE_DEPS})

-endfunction()

-

-# Lists all transitive dependencies of DIRECT_DEPS in TRANSITIVE_DEPS.

-function(_iree_transitive_dependencies DIRECT_DEPS TRANSITIVE_DEPS)

-  set(_TRANSITIVE "")

-

-  foreach(_DEP ${DIRECT_DEPS})

-    _iree_transitive_dependencies_helper(${_DEP} _TRANSITIVE)

-  endforeach(_DEP)

-

-  set(${TRANSITIVE_DEPS} "${_TRANSITIVE}" PARENT_SCOPE)

-endfunction()

-

-# Recursive helper function for _iree_transitive_dependencies.

-# Performs a depth-first search through the dependency graph, appending all

-# dependencies of TARGET to the TRANSITIVE_DEPS list.

-function(_iree_transitive_dependencies_helper TARGET TRANSITIVE_DEPS)

-  if (NOT TARGET "${TARGET}")

-    # Excluded from the project, or invalid name? Just ignore.

-    return()

-  endif()

-

-  # Resolve aliases, canonicalize name formatting.

-  get_target_property(_ALIASED_TARGET ${TARGET} ALIASED_TARGET)

-  if(_ALIASED_TARGET)

-    set(_TARGET_NAME ${_ALIASED_TARGET})

-  else()

-    string(REPLACE "::" "_" _TARGET_NAME ${TARGET})

-  endif()

-

-  set(_RESULT "${${TRANSITIVE_DEPS}}")

-  if (${_TARGET_NAME} IN_LIST _RESULT)

-    # Already visited, ignore.

-    return()

-  endif()

-

-  # Append this target to the list. Dependencies of this target will be added

-  # (if valid and not already visited) in recursive function calls.

-  list(APPEND _RESULT ${_TARGET_NAME})

-

-  # Check for non-target identifiers again after resolving the alias.

-  if (NOT TARGET ${_TARGET_NAME})

-    return()

-  endif()

-

-  # Get the list of direct dependencies for this target.

-  get_target_property(_TARGET_TYPE ${_TARGET_NAME} TYPE)

-  if(NOT ${_TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY")

-    get_target_property(_TARGET_DEPS ${_TARGET_NAME} LINK_LIBRARIES)

-  else()

-    get_target_property(_TARGET_DEPS ${_TARGET_NAME} INTERFACE_LINK_LIBRARIES)

-  endif()

-

-  if(_TARGET_DEPS)

-    # Recurse on each dependency.

-    foreach(_TARGET_DEP ${_TARGET_DEPS})

-      _iree_transitive_dependencies_helper(${_TARGET_DEP} _RESULT)

-    endforeach(_TARGET_DEP)

-  endif()

-

-  # Propagate the augmented list up to the parent scope.

-  set(${TRANSITIVE_DEPS} "${_RESULT}" PARENT_SCOPE)

-endfunction()

-

-# Sets target_link_libraries() on all registered binaries.

-# This must be called after all libraries have been declared.

-function(iree_complete_binary_link_options)

-  get_property(_NAMES GLOBAL PROPERTY _IREE_CC_BINARY_NAMES)

-

-  foreach(_NAME ${_NAMES})

-    get_target_property(_DIRECT_DEPS ${_NAME} DIRECT_DEPS)

-

-    # List all dependencies, including transitive dependencies, then split the

-    # dependency list into one for whole archive (ALWAYSLINK) and one for

-    # standard linking (which only links in symbols that are directly used).

-    _iree_transitive_dependencies("${_DIRECT_DEPS}" _TRANSITIVE_DEPS)

-    set(_ALWAYS_LINK_DEPS "")

-    set(_STANDARD_DEPS "")

-    foreach(_DEP ${_TRANSITIVE_DEPS})

-      # Check if _DEP is a library with the ALWAYSLINK property set.

-      set(_DEP_IS_ALWAYSLINK OFF)

-      if (TARGET ${_DEP})

-        get_target_property(_DEP_TYPE ${_DEP} TYPE)

-        if(${_DEP_TYPE} STREQUAL "INTERFACE_LIBRARY")

-          # Can't be ALWAYSLINK since it's an INTERFACE library.

-          # We also can't even query for the property, since it isn't whitelisted.

-        else()

-          get_target_property(_DEP_IS_ALWAYSLINK ${_DEP} ALWAYSLINK)

-        endif()

-      endif()

-

-      # Append to the corresponding list of deps.

-      if(_DEP_IS_ALWAYSLINK)

-        list(APPEND _ALWAYS_LINK_DEPS ${_DEP})

-

-        # For MSVC, also add a `-WHOLEARCHIVE:` version of the dep.

-        # CMake treats -WHOLEARCHIVE[:lib] as a link flag and will not actually

-        # try to link the library in, so we need the flag *and* the dependency.

-        if(MSVC)

-          get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET)

-          if (_ALIASED_TARGET)

-            list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_ALIASED_TARGET}")

-          else()

-            list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_DEP}")

-          endif()

-        endif()

-      else()

-        list(APPEND _STANDARD_DEPS ${_DEP})

-      endif()

-    endforeach(_DEP)

-

-    # Call into target_link_libraries with the lists of deps.

-    # TODO(scotttodd): `-Wl,-force_load` version

-    if(MSVC)

-      target_link_libraries(${_NAME}

-        PUBLIC

-          ${_ALWAYS_LINK_DEPS}

-          ${_STANDARD_DEPS}

-        PRIVATE

-          ${_RULE_LINKOPTS}

-      )

-    else()

-      target_link_libraries(${_NAME}

-        PUBLIC

-          "-Wl,--whole-archive"

-          ${_ALWAYS_LINK_DEPS}

-          "-Wl,--no-whole-archive"

-          ${_STANDARD_DEPS}

-        PRIVATE

-          ${_RULE_LINKOPTS}

-      )

-    endif()

-  endforeach(_NAME)

-endfunction()

+# 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)
+
+if (NOT DEFINED _IREE_CC_BINARY_NAMES)
+  set(_IREE_CC_BINARY_NAMES "")
+endif()
+
+# iree_cc_binary()
+#
+# CMake function to imitate Bazel's cc_binary rule.
+#
+# Parameters:
+# NAME: name of target (see Usage below)
+# SRCS: List of source files for the binary
+# DEPS: List of other libraries to be linked in to the binary targets
+# COPTS: List of private compile options
+# DEFINES: List of public defines
+# LINKOPTS: List of link options
+#
+# Note:
+# By default, iree_cc_binary will always create a binary named iree_${NAME}.
+#
+# Usage:
+# iree_cc_library(
+#   NAME
+#     awesome
+#   HDRS
+#     "a.h"
+#   SRCS
+#     "a.cc"
+#   PUBLIC
+# )
+#
+# iree_cc_binary(
+#   NAME
+#     awesome_tool
+#   OUT
+#     awesome-tool
+#   SRCS
+#     "awesome_tool_main.cc"
+#   DEPS
+#     iree::awesome
+# )
+function(iree_cc_binary)
+  cmake_parse_arguments(
+    _RULE
+    "TESTONLY"
+    "NAME;OUT"
+    "SRCS;COPTS;DEFINES;LINKOPTS;DEPS"
+    ${ARGN}
+  )
+
+  if(NOT _RULE_TESTONLY OR IREE_BUILD_TESTS)
+    # Prefix the library with the package name, so we get: iree_package_name
+    iree_package_name(_PACKAGE_NAME)
+    set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")
+
+    add_executable(${_NAME} "")
+    add_executable(${_RULE_NAME} ALIAS ${_NAME})
+    if(_RULE_SRCS)
+      target_sources(${_NAME}
+        PRIVATE
+          ${_RULE_SRCS}
+      )
+    else()
+      set(_DUMMY_SRC "${CMAKE_CURRENT_BINARY_DIR}/${_NAME}_dummy.cc")
+      file(WRITE ${_DUMMY_SRC} "")
+      target_sources(${_NAME}
+        PRIVATE
+          ${_DUMMY_SRC}
+      )
+    endif()
+    if(_RULE_OUT)
+      set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_OUT}")
+    else()
+      set_target_properties(${_NAME} PROPERTIES OUTPUT_NAME "${_RULE_NAME}")
+    endif()
+    target_include_directories(${_NAME}
+      PUBLIC
+        ${IREE_COMMON_INCLUDE_DIRS}
+      PRIVATE
+        ${GTEST_INCLUDE_DIRS}
+    )
+    target_compile_definitions(${_NAME}
+      PUBLIC
+        ${_RULE_DEFINES}
+    )
+    target_compile_options(${_NAME}
+      PRIVATE
+        ${_RULE_COPTS}
+    )
+
+    iree_package_ns(_PACKAGE_NS)
+    # Replace dependencies passed by ::name with ::iree::package::name
+    list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
+
+    # Add all IREE targets to a folder in the IDE for organization.
+    set_property(TARGET ${_NAME} PROPERTY FOLDER ${IREE_IDE_FOLDER}/binaries)
+
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD ${IREE_CXX_STANDARD})
+    set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
+
+    # Defer computing transitive dependencies and calling target_link_libraries()
+    # until all libraries have been declared.
+    # Track target and deps, use in iree_complete_binary_link_options() later.
+    set_property(GLOBAL APPEND PROPERTY _IREE_CC_BINARY_NAMES "${_NAME}")
+    set_property(TARGET ${_NAME} PROPERTY DIRECT_DEPS ${_RULE_DEPS})
+  endif()
+endfunction()
+
+# Lists all transitive dependencies of DIRECT_DEPS in TRANSITIVE_DEPS.
+function(_iree_transitive_dependencies DIRECT_DEPS TRANSITIVE_DEPS)
+  set(_TRANSITIVE "")
+
+  foreach(_DEP ${DIRECT_DEPS})
+    _iree_transitive_dependencies_helper(${_DEP} _TRANSITIVE)
+  endforeach(_DEP)
+
+  set(${TRANSITIVE_DEPS} "${_TRANSITIVE}" PARENT_SCOPE)
+endfunction()
+
+# Recursive helper function for _iree_transitive_dependencies.
+# Performs a depth-first search through the dependency graph, appending all
+# dependencies of TARGET to the TRANSITIVE_DEPS list.
+function(_iree_transitive_dependencies_helper TARGET TRANSITIVE_DEPS)
+  if (NOT TARGET "${TARGET}")
+    # Excluded from the project, or invalid name? Just ignore.
+    return()
+  endif()
+
+  # Resolve aliases, canonicalize name formatting.
+  get_target_property(_ALIASED_TARGET ${TARGET} ALIASED_TARGET)
+  if(_ALIASED_TARGET)
+    set(_TARGET_NAME ${_ALIASED_TARGET})
+  else()
+    string(REPLACE "::" "_" _TARGET_NAME ${TARGET})
+  endif()
+
+  set(_RESULT "${${TRANSITIVE_DEPS}}")
+  if (${_TARGET_NAME} IN_LIST _RESULT)
+    # Already visited, ignore.
+    return()
+  endif()
+
+  # Append this target to the list. Dependencies of this target will be added
+  # (if valid and not already visited) in recursive function calls.
+  list(APPEND _RESULT ${_TARGET_NAME})
+
+  # Check for non-target identifiers again after resolving the alias.
+  if (NOT TARGET ${_TARGET_NAME})
+    return()
+  endif()
+
+  # Get the list of direct dependencies for this target.
+  get_target_property(_TARGET_TYPE ${_TARGET_NAME} TYPE)
+  if(NOT ${_TARGET_TYPE} STREQUAL "INTERFACE_LIBRARY")
+    get_target_property(_TARGET_DEPS ${_TARGET_NAME} LINK_LIBRARIES)
+  else()
+    get_target_property(_TARGET_DEPS ${_TARGET_NAME} INTERFACE_LINK_LIBRARIES)
+  endif()
+
+  if(_TARGET_DEPS)
+    # Recurse on each dependency.
+    foreach(_TARGET_DEP ${_TARGET_DEPS})
+      _iree_transitive_dependencies_helper(${_TARGET_DEP} _RESULT)
+    endforeach(_TARGET_DEP)
+  endif()
+
+  # Propagate the augmented list up to the parent scope.
+  set(${TRANSITIVE_DEPS} "${_RESULT}" PARENT_SCOPE)
+endfunction()
+
+# Sets target_link_libraries() on all registered binaries.
+# This must be called after all libraries have been declared.
+function(iree_complete_binary_link_options)
+  get_property(_NAMES GLOBAL PROPERTY _IREE_CC_BINARY_NAMES)
+
+  foreach(_NAME ${_NAMES})
+    get_target_property(_DIRECT_DEPS ${_NAME} DIRECT_DEPS)
+
+    # List all dependencies, including transitive dependencies, then split the
+    # dependency list into one for whole archive (ALWAYSLINK) and one for
+    # standard linking (which only links in symbols that are directly used).
+    _iree_transitive_dependencies("${_DIRECT_DEPS}" _TRANSITIVE_DEPS)
+    set(_ALWAYS_LINK_DEPS "")
+    set(_STANDARD_DEPS "")
+    foreach(_DEP ${_TRANSITIVE_DEPS})
+      # Check if _DEP is a library with the ALWAYSLINK property set.
+      set(_DEP_IS_ALWAYSLINK OFF)
+      if (TARGET ${_DEP})
+        get_target_property(_DEP_TYPE ${_DEP} TYPE)
+        if(${_DEP_TYPE} STREQUAL "INTERFACE_LIBRARY")
+          # Can't be ALWAYSLINK since it's an INTERFACE library.
+          # We also can't even query for the property, since it isn't whitelisted.
+        else()
+          get_target_property(_DEP_IS_ALWAYSLINK ${_DEP} ALWAYSLINK)
+        endif()
+      endif()
+
+      # Append to the corresponding list of deps.
+      if(_DEP_IS_ALWAYSLINK)
+        list(APPEND _ALWAYS_LINK_DEPS ${_DEP})
+
+        # For MSVC, also add a `-WHOLEARCHIVE:` version of the dep.
+        # CMake treats -WHOLEARCHIVE[:lib] as a link flag and will not actually
+        # try to link the library in, so we need the flag *and* the dependency.
+        if(MSVC)
+          get_target_property(_ALIASED_TARGET ${_DEP} ALIASED_TARGET)
+          if (_ALIASED_TARGET)
+            list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_ALIASED_TARGET}")
+          else()
+            list(APPEND _ALWAYS_LINK_DEPS "-WHOLEARCHIVE:${_DEP}")
+          endif()
+        endif()
+      else()
+        list(APPEND _STANDARD_DEPS ${_DEP})
+      endif()
+    endforeach(_DEP)
+
+    # Call into target_link_libraries with the lists of deps.
+    # TODO(scotttodd): `-Wl,-force_load` version
+    if(MSVC)
+      target_link_libraries(${_NAME}
+        PUBLIC
+          ${_ALWAYS_LINK_DEPS}
+          ${_STANDARD_DEPS}
+        PRIVATE
+          ${_RULE_LINKOPTS}
+      )
+    else()
+      target_link_libraries(${_NAME}
+        PUBLIC
+          "-Wl,--whole-archive"
+          ${_ALWAYS_LINK_DEPS}
+          "-Wl,--no-whole-archive"
+          ${_STANDARD_DEPS}
+        PRIVATE
+          ${_RULE_LINKOPTS}
+      )
+    endif()
+  endforeach(_NAME)
+endfunction()