forked from OSchip/llvm-project
156 lines
5.7 KiB
CMake
156 lines
5.7 KiB
CMake
################################################################################
|
|
# Build python extension
|
|
################################################################################
|
|
function(add_mlir_python_extension libname extname)
|
|
cmake_parse_arguments(ARG
|
|
""
|
|
"INSTALL_DIR"
|
|
"SOURCES;LINK_LIBS"
|
|
${ARGN})
|
|
if (ARG_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR " Unhandled arguments to add_mlir_python_extension(${libname}, ... : ${ARG_UNPARSED_ARGUMENTS}")
|
|
endif()
|
|
if ("${ARG_SOURCES}" STREQUAL "")
|
|
message(FATAL_ERROR " Missing SOURCES argument to add_mlir_python_extension(${libname}, ...")
|
|
endif()
|
|
|
|
# Normally on unix-like platforms, extensions are built as "MODULE" libraries
|
|
# and do not explicitly link to the python shared object. This allows for
|
|
# some greater deployment flexibility since the extension will bind to
|
|
# symbols in the python interpreter on load. However, it also keeps the
|
|
# linker from erroring on undefined symbols, leaving this to (usually obtuse)
|
|
# runtime errors. Building in "SHARED" mode with an explicit link to the
|
|
# python libraries allows us to build with the expectation of no undefined
|
|
# symbols, which is better for development. Note that not all python
|
|
# configurations provide build-time libraries to link against, in which
|
|
# case, we fall back to MODULE linking.
|
|
if(Python3_LIBRARIES STREQUAL "" OR NOT MLIR_PYTHON_BINDINGS_VERSION_LOCKED)
|
|
set(PYEXT_LINK_MODE MODULE)
|
|
set(PYEXT_LIBADD)
|
|
else()
|
|
set(PYEXT_LINK_MODE SHARED)
|
|
set(PYEXT_LIBADD ${Python3_LIBRARIES})
|
|
endif()
|
|
|
|
# The actual extension library produces a shared-object or DLL and has
|
|
# sources that must be compiled in accordance with pybind11 needs (RTTI and
|
|
# exceptions).
|
|
add_library(${libname} ${PYEXT_LINK_MODE}
|
|
${ARG_SOURCES}
|
|
)
|
|
|
|
target_include_directories(${libname} PRIVATE
|
|
"${Python3_INCLUDE_DIRS}"
|
|
"${pybind11_INCLUDE_DIR}"
|
|
)
|
|
|
|
# The extension itself must be compiled with RTTI and exceptions enabled.
|
|
# Also, some warning classes triggered by pybind11 are disabled.
|
|
target_compile_options(${libname} PRIVATE
|
|
$<$<OR:$<CXX_COMPILER_ID:Clang>,$<CXX_COMPILER_ID:AppleClang>,$<CXX_COMPILER_ID:GNU>>:
|
|
# Enable RTTI and exceptions.
|
|
-frtti -fexceptions
|
|
# Noisy pybind warnings
|
|
-Wno-unused-value
|
|
-Wno-covered-switch-default
|
|
>
|
|
$<$<CXX_COMPILER_ID:MSVC>:
|
|
# Enable RTTI and exceptions.
|
|
/EHsc /GR>
|
|
)
|
|
|
|
# Configure the output to match python expectations.
|
|
set_target_properties(
|
|
${libname} PROPERTIES
|
|
# Build-time RPath layouts require to be a directory one up from the
|
|
# binary root.
|
|
# TODO: Don't reference the LLVM_BINARY_DIR here: the invariant is that
|
|
# the output directory must be at the same level of the lib directory
|
|
# where libMLIR.so is installed. This is presently not optimal from a
|
|
# project separation perspective and a discussion on how to better
|
|
# segment MLIR libraries needs to happen.
|
|
LIBRARY_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/python
|
|
OUTPUT_NAME "${extname}"
|
|
PREFIX "${PYTHON_MODULE_PREFIX}"
|
|
SUFFIX "${PYTHON_MODULE_SUFFIX}${PYTHON_MODULE_EXTENSION}"
|
|
)
|
|
|
|
if(WIN32)
|
|
# Need to also set the RUNTIME_OUTPUT_DIRECTORY on Windows in order to
|
|
# control where the .dll gets written.
|
|
set_target_properties(
|
|
${libname} PROPERTIES
|
|
RUNTIME_OUTPUT_DIRECTORY ${LLVM_BINARY_DIR}/python
|
|
)
|
|
endif()
|
|
|
|
# pybind11 requires binding code to be compiled with -fvisibility=hidden
|
|
# For static linkage, better code can be generated if the entire project
|
|
# compiles that way, but that is not enforced here. Instead, include a linker
|
|
# script that explicitly hides anything but the PyInit_* symbols, allowing gc
|
|
# to take place.
|
|
set_target_properties(${libname} PROPERTIES CXX_VISIBILITY_PRESET "hidden")
|
|
|
|
# Python extensions depends *only* on the public API and LLVMSupport unless
|
|
# if further dependencies are added explicitly.
|
|
target_link_libraries(${libname}
|
|
PRIVATE
|
|
MLIRPublicAPI
|
|
LLVMSupport
|
|
${ARG_LINK_LIBS}
|
|
${PYEXT_LIBADD}
|
|
)
|
|
|
|
target_link_options(${libname}
|
|
PRIVATE
|
|
# On Linux, disable re-export of any static linked libraries that
|
|
# came through.
|
|
$<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,ALL>
|
|
)
|
|
|
|
llvm_setup_rpath(${libname})
|
|
|
|
################################################################################
|
|
# Install
|
|
################################################################################
|
|
if (ARG_INSTALL_DIR)
|
|
install(TARGETS ${libname}
|
|
COMPONENT ${libname}
|
|
LIBRARY DESTINATION ${ARG_INSTALL_DIR}
|
|
ARCHIVE DESTINATION ${ARG_INSTALL_DIR}
|
|
# NOTE: Even on DLL-platforms, extensions go in the lib directory tree.
|
|
RUNTIME DESTINATION ${ARG_INSTALL_DIR}
|
|
)
|
|
endif()
|
|
|
|
if (NOT LLVM_ENABLE_IDE)
|
|
add_llvm_install_targets(
|
|
install-${libname}
|
|
DEPENDS ${libname}
|
|
COMPONENT ${libname})
|
|
endif()
|
|
|
|
endfunction()
|
|
|
|
function(add_mlir_dialect_python_bindings filename dialectname)
|
|
set(LLVM_TARGET_DEFINITIONS ${filename})
|
|
mlir_tablegen("${dialectname}.py" -gen-python-op-bindings
|
|
-bind-dialect=${dialectname})
|
|
if (${ARGC} GREATER 2)
|
|
set(suffix ${ARGV2})
|
|
else()
|
|
get_filename_component(suffix ${filename} NAME_WE)
|
|
endif()
|
|
set(tblgen_target "MLIRBindingsPython${suffix}")
|
|
add_public_tablegen_target(${tblgen_target})
|
|
|
|
add_custom_command(
|
|
TARGET ${tblgen_target} POST_BUILD
|
|
COMMENT "Copying generated python source \"dialects/${dialectname}.py\""
|
|
COMMAND "${CMAKE_COMMAND}" -E copy_if_different
|
|
"${CMAKE_CURRENT_BINARY_DIR}/${dialectname}.py"
|
|
"${PROJECT_BINARY_DIR}/python/mlir/dialects/${dialectname}.py")
|
|
add_dependencies(MLIRBindingsPythonIncGen ${tblgen_target})
|
|
endfunction()
|
|
|