From: Noa Osherovich <noaos@xxxxxxxxxxxx> Add CMakeLists in Pyverbs to define build process and add a Findcython file to retrieve cython executable. Build currently uses python3 if possible, while pyverbs fully supports python2 too. However packaging policies of all modern distributions prohibits addition of new packages with depedencies on python2. It means that anyone who is interested to run pyverbs with python2 is expected to adapt it locally to build Python2-pyverbs package. Signed-off-by: Jason Gubthorpe <jgg@xxxxxxxxxxxx> Signed-off-by: Noa Osherovich <noaos@xxxxxxxxxxxx> Signed-off-by: Alaa Hleihel <alaa@xxxxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> --- .travis.yml | 4 +++ CMakeLists.txt | 45 ++++++++++++++++++++++++++++++-- buildlib/Findcython.cmake | 29 ++++++++++++++++++++ buildlib/pyverbs_functions.cmake | 36 +++++++++++++++++++++++++ pyverbs/CMakeLists.txt | 14 ++++++++++ 5 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 buildlib/Findcython.cmake create mode 100644 buildlib/pyverbs_functions.cmake create mode 100644 pyverbs/CMakeLists.txt diff --git a/.travis.yml b/.travis.yml index 9794c1c7..82a6c276 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,10 @@ addons: - gcc-multilib - lib32gcc-7-dev + # pyverbs + - python3-dev + - cython3 + service: - docker diff --git a/CMakeLists.txt b/CMakeLists.txt index 90ee3fcb..c5eb10cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 varient 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 guarentee 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 specifc 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() diff --git a/buildlib/Findcython.cmake b/buildlib/Findcython.cmake new file mode 100644 index 00000000..0bcc862b --- /dev/null +++ b/buildlib/Findcython.cmake @@ -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) diff --git a/buildlib/pyverbs_functions.cmake b/buildlib/pyverbs_functions.cmake new file mode 100644 index 00000000..b0cf16f5 --- /dev/null +++ b/buildlib/pyverbs_functions.cmake @@ -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() diff --git a/pyverbs/CMakeLists.txt b/pyverbs/CMakeLists.txt new file mode 100644 index 00000000..f7bc3eca --- /dev/null +++ b/pyverbs/CMakeLists.txt @@ -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 + ) -- 2.19.1