blob: b5dcdd3832a59d94c76bcb3d8a46909f348d71a2 [file] [log] [blame]
# Copyright 2020 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
include(CMakeParseArguments)
###############################################################################
# Package detection
###############################################################################
# Checks whether the PyYAML package is available. Sets IREE_PYYAML_FOUND to
# ON if so.
function(iree_detect_pyyaml)
execute_process(
COMMAND ${Python3_EXECUTABLE} -c "import yaml"
RESULT_VARIABLE EXIT_CODE
OUTPUT_QUIET
ERROR_QUIET
)
if(EXIT_CODE)
message(STATUS "Looking for PyYAML - not found (some features may not be available: install with 'python -m pip install PyYAML' or equiv for your system)")
set(IREE_PYYAML_FOUND OFF PARENT_SCOPE)
else()
message(STATUS "Looking for PyYAML - found")
set(IREE_PYYAML_FOUND ON PARENT_SCOPE)
endif()
endfunction()
###############################################################################
# Main user rules
###############################################################################
# iree_pyext_module()
#
# Builds a native python module (.so/.dylib/.pyd).
#
# Parameters:
# NAME: name of target
# MODULE_NAME: Base-name of the module.
# SRCS: List of source files for the library
# DEPS: List of other targets the test python libraries require
# COPTS: List of private compile options
# DEFINES: List of public defines
# INCLUDES: Include directories to add to dependencies
function(iree_pyext_module)
cmake_parse_arguments(ARG
""
"NAME;MODULE_NAME;UNIX_LINKER_SCRIPT"
"SRCS;DEPS;COPTS;DEFINES;INCLUDES"
${ARGN})
iree_package_ns(_PACKAGE_NS)
# Replace dependencies passed by ::name with ::iree::package::name
list(TRANSFORM ARG_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
list(TRANSFORM ARG_PYEXT_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
# Prefix the library with the package name, so we get: iree_package_name.
iree_package_name(_PACKAGE_NAME)
set(_NAME "${_PACKAGE_NAME}_${ARG_NAME}")
pybind11_add_module(
${_NAME}
${ARG_SRCS}
)
# Alias the iree_package_name library to iree::package::name so that we can
# refer to this target with the namespaced format.
add_library(${_PACKAGE_NS}::${ARG_NAME} ALIAS ${_NAME})
target_link_libraries(
${_NAME}
PRIVATE ${ARG_DEPS}
)
set_target_properties(
${_NAME} PROPERTIES
OUTPUT_NAME "${ARG_MODULE_NAME}"
)
target_include_directories(${_NAME}
PUBLIC
"$<BUILD_INTERFACE:${ARG_INCLUDES}>"
)
# pybind11 requires both RTTI and Exceptions, and it does not know that
# we have disabled them globally, so turn them back on. Since this is
# *the only* place in the codebase where we do this, just inline here.
# Note that this is playing with fire and the extension code is structured
# so as not to cause problems with RTTI cross-module issues.
iree_select_compiler_opts(_RTTI_AND_EXCEPTION_COPTS
CLANG_OR_GCC
"-frtti"
"-fexceptions"
MSVC_OR_CLANG_CL
# Configure exception handling for standard C++ behavior.
# - /EHs enables C++ catch-style exceptions
# - /EHc breaks unwinding across extern C boundaries, dramatically reducing
# unwind table size and associated exception handling overhead as the
# compiler can assume no exception will ever be thrown within any function
# annotated with extern "C".
# https://docs.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model
"/EHsc"
# Configure RTTI generation.
# - /GR - Enable generation of RTTI (default)
# - /GR- - Disables generation of RTTI
# https://docs.microsoft.com/en-us/cpp/build/reference/gr-enable-run-time-type-information?view=msvc-160
"/GR"
)
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD 17)
set_property(TARGET ${_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
target_compile_options(
${_NAME} PRIVATE
${ARG_COPTS}
${IREE_DEFAULT_COPTS}
${_RTTI_AND_EXCEPTION_COPTS}
)
target_compile_definitions(
${_NAME} PUBLIC
${ARG_DEFINES}
)
# Link flags.
if(UNIX AND NOT APPLE) # Apple does not support linker scripts.
if(ARG_UNIX_LINKER_SCRIPT)
set_target_properties(${_NAME} PROPERTIES LINK_FLAGS
"-Wl,--version-script=\"${CMAKE_CURRENT_SOURCE_DIR}/${ARG_UNIX_LINKER_SCRIPT}\"")
endif()
endif()
endfunction()
# iree_py_library()
#
# CMake function to imitate Bazel's iree_py_library rule.
#
# Parameters:
# NAME: name of target
# SRCS: List of source files for the library
# DEPS: List of other targets the test python libraries require
# PYEXT_DEPS: List of deps of extensions built with iree_pyext_module
function(iree_py_library)
cmake_parse_arguments(
_RULE
""
"NAME"
"SRCS;DEPS;PYEXT_DEPS"
${ARGN}
)
iree_package_ns(_PACKAGE_NS)
# Replace dependencies passed by ::name with ::iree::package::name
list(TRANSFORM _RULE_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
iree_package_name(_PACKAGE_NAME)
set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")
add_custom_target(${_NAME} ALL
DEPENDS ${_RULE_DEPS}
)
# Symlink each file as its own target.
foreach(_SRC_FILE ${_RULE_SRCS})
# _SRC_FILE could have other path components in it, so we need to make a
# directory for it. Ninja does this automatically, but make doesn't. See
# https://github.com/openxla/iree/issues/6801
set(_SRC_BIN_PATH "${CMAKE_CURRENT_BINARY_DIR}/${_SRC_FILE}")
get_filename_component(_SRC_BIN_DIR "${_SRC_BIN_PATH}" DIRECTORY)
add_custom_command(
TARGET ${_NAME}
COMMAND
${CMAKE_COMMAND} -E make_directory "${_SRC_BIN_DIR}"
COMMAND ${CMAKE_COMMAND} -E create_symlink
"${CMAKE_CURRENT_SOURCE_DIR}/${_SRC_FILE}" "${_SRC_BIN_PATH}"
BYPRODUCTS "${_SRC_BIN_PATH}"
)
endforeach()
# Add PYEXT_DEPS if any.
if(_RULE_PYEXT_DEPS)
list(TRANSFORM _RULE_PYEXT_DEPS REPLACE "^::" "${_PACKAGE_NS}::")
add_dependencies(${_NAME} ${_RULE_PYEXT_DEPS})
endif()
endfunction()
# iree_local_py_test()
#
# CMake function to run python test with provided python package paths.
#
# Parameters:
# NAME: name of test
# SRC: Test source file
# ARGS: Command line arguments to the Python source file.
# LABELS: Additional labels to apply to the test. The package path is added
# automatically.
# GENERATED_IN_BINARY_DIR: If present, indicates that the srcs have been
# in the CMAKE_CURRENT_BINARY_DIR.
# PACKAGE_DIRS: Python package paths to be added to PYTHONPATH.
function(iree_local_py_test)
if(NOT IREE_BUILD_TESTS OR ANDROID OR EMSCRIPTEN)
return()
endif()
cmake_parse_arguments(
_RULE
"GENERATED_IN_BINARY_DIR"
"NAME;SRC"
"ARGS;LABELS;PACKAGE_DIRS;TIMEOUT"
${ARGN}
)
# Switch between source and generated tests.
set(_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
if(_RULE_GENERATED_IN_BINARY_DIR)
set(_SRC_DIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
iree_package_name(_PACKAGE_NAME)
set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")
iree_package_ns(_PACKAGE_NS)
string(REPLACE "::" "/" _PACKAGE_PATH ${_PACKAGE_NS})
set(_NAME_PATH "${_PACKAGE_PATH}/${_RULE_NAME}")
list(APPEND _RULE_LABELS "${_PACKAGE_PATH}")
add_test(
NAME ${_NAME_PATH}
COMMAND
"${Python3_EXECUTABLE}"
"${CMAKE_CURRENT_SOURCE_DIR}/${_RULE_SRC}"
${_RULE_ARGS}
)
set_property(TEST ${_NAME_PATH} PROPERTY LABELS "${_RULE_LABELS}")
set_property(TEST ${_NAME_PATH} PROPERTY TIMEOUT ${_RULE_ARGS})
# Extend the PYTHONPATH environment variable with _RULE_PACKAGE_DIRS.
list(APPEND _RULE_PACKAGE_DIRS "$ENV{PYTHONPATH}")
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
# Windows uses semi-colon delimiters, but so does CMake, so escape them.
list(JOIN _RULE_PACKAGE_DIRS "\\;" _PYTHONPATH)
else()
list(JOIN _RULE_PACKAGE_DIRS ":" _PYTHONPATH)
endif()
set_property(TEST ${_NAME_PATH} PROPERTY ENVIRONMENT
"PYTHONPATH=${_PYTHONPATH}"
)
if (NOT DEFINED _RULE_TIMEOUT)
set(_RULE_TIMEOUT 60)
endif()
iree_configure_test(${_NAME_PATH})
# TODO(marbre): Find out how to add deps to tests.
# Similar to _RULE_DATA in iree_lit_test().
endfunction()
# iree_py_test()
#
# CMake function to imitate Bazel's iree_py_test rule.
#
# Parameters:
# NAME: name of test
# SRCS: Test source file (single file only, despite name)
# ARGS: Command line arguments to the Python source file.
# LABELS: Additional labels to apply to the test. The package path is added
# automatically.
# GENERATED_IN_BINARY_DIR: If present, indicates that the srcs have been
# in the CMAKE_CURRENT_BINARY_DIR.
function(iree_py_test)
cmake_parse_arguments(
_RULE
"GENERATED_IN_BINARY_DIR"
"NAME;SRCS"
"ARGS;LABELS;TIMEOUT"
${ARGN}
)
if(NOT IREE_BUILD_PYTHON_BINDINGS)
return()
endif()
iree_local_py_test(
NAME
"${_RULE_NAME}"
SRC
"${_RULE_SRCS}"
ARGS
${_RULE_ARGS}
LABELS
${_RULE_LABELS}
PACKAGE_DIRS
"${IREE_BINARY_DIR}/compiler/bindings/python"
"${IREE_BINARY_DIR}/runtime/bindings/python"
GENERATED_IN_BINARY_DIR
"${_RULE_GENERATED_IN_BINARY_DIR}"
TIMEOUT
${_RULE_TIMEOUT}
)
endfunction()
# iree_build_tools_py_test()
#
# CMake function to test with build_tools python modules.
#
# Parameters:
# NAME: name of test
# SRC: Test source file
# ARGS: Command line arguments to the Python source file.
# LABELS: Additional labels to apply to the test. The package path is added
# automatically.
# PACKAGE_DIRS: Additional python module paths.
function(iree_build_tools_py_test)
cmake_parse_arguments(
_RULE
""
"NAME;SRC"
"ARGS;LABELS;PACKAGE_DIRS"
${ARGN}
)
iree_local_py_test(
NAME
"${_RULE_NAME}"
SRC
"${_RULE_SRC}"
ARGS
${_RULE_ARGS}
LABELS
${_RULE_LABELS}
PACKAGE_DIRS
${_RULE_PACKAGE_DIRS}
"${IREE_ROOT_DIR}/build_tools/python"
)
endfunction()