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()