@@ -37,6 +37,10 @@ addons:
- gcc-multilib
- lib32gcc-7-dev
+ # pyverbs
+ - python3-dev
+ - cython3
+
service:
- docker
@@ -37,6 +37,11 @@
# -DIBACM_ACME_PLUS_KERNEL_ONLY_DEFAULT (default 0)
# If non-zero, limit incoming requests to kernel or the ib_acme utility
# (i.e. do not serve librdmacm requests)
+# -DPYTHON_EXECUTABLE
+# Override automatic detection of python to use a certain
+# exectuable. This can be used to force the build to use python2 on a
+# system that has python3 installed. Otherwise the build automatically
+# prefers python3 if available.
cmake_minimum_required(VERSION 2.8.11 FATAL_ERROR)
project(rdma-core C)
@@ -86,6 +91,7 @@ set(BUILD_LIB ${CMAKE_BINARY_DIR}/lib)
set(BUILD_STATIC_LIB ${CMAKE_BINARY_DIR}/lib/statics)
# Used for IN_PLACE configuration
set(BUILD_ETC ${CMAKE_BINARY_DIR}/etc)
+set(BUILD_PYTHON ${CMAKE_BINARY_DIR}/python)
set(CMAKE_INSTALL_INITDDIR "${CMAKE_INSTALL_SYSCONFDIR}/init.d"
CACHE PATH "Location for init.d files")
@@ -148,6 +154,7 @@ include(RDMA_BuildType)
include(RDMA_DoFixup)
include(publish_headers)
include(rdma_functions)
+include(pyverbs_functions)
include(rdma_man)
if (NOT DEFINED ENABLE_STATIC)
@@ -349,8 +356,35 @@ else()
set(HAVE_FULL_SYMBOL_VERSIONS 1)
endif()
-# Look for Python
-FIND_PACKAGE(PythonInterp REQUIRED)
+# Look for Python. We prefer some variant of python 3 if the system has it.
+FIND_PACKAGE(PythonInterp 3 QUIET)
+if (NOT ${PythonInterp_FOUND})
+ FIND_PACKAGE(PythonInterp REQUIRED)
+endif()
+FIND_PACKAGE(cython)
+# A cython & python-devel installation that matches our selected interpreter.
+if (CYTHON_EXECUTABLE)
+ # cmake has really bad logic here, if PythonIterp has been run it tries to
+ # find a matching -devel installation but will happily return a non-matching
+ # one too. We need them both to match exactly to guarantee cython does the
+ # right thing.
+ FIND_PACKAGE(PythonLibs ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}
+ EXACT REQUIRED)
+
+ # Get a default installation path
+ execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c
+ "from distutils.sysconfig import get_python_lib; print(get_python_lib(True, False, '${CMAKE_INSTALL_PREFIX}'))"
+ OUTPUT_VARIABLE py_path)
+ string(STRIP ${py_path} py_path)
+ set(CMAKE_INSTALL_PYTHON_ARCH_LIB "${py_path}"
+ CACHE PATH "Location for architecture specific python libraries")
+
+ # See PEP3149
+ execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c
+ "import sysconfig; x = sysconfig.get_config_var(\"EXT_SUFFIX\"); print(x if x else '.so')"
+ OUTPUT_VARIABLE py_path)
+ string(STRIP ${py_path} CMAKE_PYTHON_SO_SUFFIX)
+endif()
# Look for pandoc
FIND_PACKAGE(pandoc)
@@ -549,6 +583,10 @@ add_subdirectory(providers/ipathverbs)
add_subdirectory(providers/rxe)
add_subdirectory(providers/rxe/man)
+if (CYTHON_EXECUTABLE)
+ add_subdirectory(pyverbs)
+endif()
+
# Binaries
add_subdirectory(ibacm) # NO SPARSE
if (NOT NL_KIND EQUAL 0)
@@ -607,6 +645,9 @@ if (NOT PANDOC_FOUND)
message(STATUS " pandoc NOT found (using prebuilt man pages)")
endif()
endif()
+if (NOT CYTHON_EXECUTABLE)
+ message(STATUS " cython NOT found (disabling pyverbs)")
+endif()
if (NOT SYSTEMD_FOUND)
message(STATUS " libsystemd NOT found (disabling features)")
endif()
new file mode 100644
@@ -0,0 +1,29 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
+
+execute_process(COMMAND "${PYTHON_EXECUTABLE}" -c
+ "from Cython.Compiler.Main import main; import Cython; print(Cython.__version__);"
+ OUTPUT_VARIABLE _VERSION
+ RESULT_VARIABLE _VERSION_RESULT
+ ERROR_QUIET)
+
+if(NOT _VERSION_RESULT)
+ # We make our own cython script because it is very hard to figure out which
+ # cython exectuable wrapper is appropriately matched to the python
+ # interpreter we want to use. Cython must use the matching version of python
+ # or things will go wrong.
+ string(STRIP "${_VERSION}" CYTHON_VERSION_STRING)
+ set(CYTHON_EXECUTABLE "${BUILD_PYTHON}/cython")
+ file(WRITE "${CYTHON_EXECUTABLE}" "#!${PYTHON_EXECUTABLE}
+from Cython.Compiler.Main import main
+main(command_line = 1)")
+ execute_process(COMMAND "chmod" "a+x" "${CYTHON_EXECUTABLE}")
+endif()
+unset(_VERSION_RESULT)
+unset(_VERSION)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(cython
+ REQUIRED_VARS CYTHON_EXECUTABLE CYTHON_VERSION_STRING
+ VERSION_VAR CYTHON_VERSION_STRING)
+mark_as_advanced(CYTHON_EXECUTABLE)
new file mode 100644
@@ -0,0 +1,36 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
+
+function(rdma_cython_module PY_MODULE)
+ foreach(PYX_FILE ${ARGN})
+ get_filename_component(FILENAME ${PYX_FILE} NAME_WE)
+ set(PYX "${CMAKE_CURRENT_SOURCE_DIR}/${FILENAME}.pyx")
+ set(CFILE "${CMAKE_CURRENT_BINARY_DIR}/${FILENAME}.c")
+ include_directories(${PYTHON_INCLUDE_DIRS})
+ add_custom_command(
+ OUTPUT "${CFILE}"
+ COMMAND ${CYTHON_EXECUTABLE} "${PYX}" -o "${CFILE}"
+ "-I${PYTHON_INCLUDE_DIRS}"
+ COMMENT "Cythonizing ${PYX}"
+ )
+
+ string(REGEX REPLACE "\\.so$" "" SONAME "${FILENAME}${CMAKE_PYTHON_SO_SUFFIX}")
+ add_library(${SONAME} SHARED ${CFILE})
+ set_target_properties(${SONAME} PROPERTIES
+ COMPILE_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -Wno-redundant-decls -Wno-shadow"
+ LIBRARY_OUTPUT_DIRECTORY "${BUILD_PYTHON}/${PY_MODULE}"
+ PREFIX "")
+ target_link_libraries(${SONAME} LINK_PRIVATE ${PYTHON_LIBRARIES} ibverbs)
+ install(TARGETS ${SONAME}
+ DESTINATION ${CMAKE_INSTALL_PYTHON_ARCH_LIB}/${PY_MODULE})
+ endforeach()
+endfunction()
+
+function(rdma_python_module PY_MODULE)
+ foreach(PY_FILE ${ARGN})
+ get_filename_component(LINK "${CMAKE_CURRENT_SOURCE_DIR}/${PY_FILE}" ABSOLUTE)
+ rdma_create_symlink("${LINK}" "${BUILD_PYTHON}/${PY_MODULE}/${PY_FILE}")
+ install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${PY_FILE}
+ DESTINATION ${CMAKE_INSTALL_PYTHON_ARCH_LIB}/${PY_MODULE})
+ endforeach()
+endfunction()
new file mode 100644
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: (GPL-2.0 OR Linux-OpenIB)
+# Copyright (c) 2018, Mellanox Technologies. All rights reserved. See COPYING file
+
+rdma_cython_module(pyverbs
+ enums.pyx
+ base.pyx
+ device.pyx
+ addr.pyx
+ )
+
+rdma_python_module(pyverbs
+ pyverbs_error.py
+ __init__.py
+ )