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 dependencies 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: Noa Osherovich <noaos@xxxxxxxxxxxx> Signed-off-by: Jason Gubthorpe <jgg@xxxxxxxxxxxx> Signed-off-by: Alaa Hleihel <alaa@xxxxxxxxxxxx> Signed-off-by: Leon Romanovsky <leonro@xxxxxxxxxxxx> --- .travis.yml | 4 +++ CMakeLists.txt | 58 ++++++++++++++++++++++++++++++-- buildlib/Findcython.cmake | 29 ++++++++++++++++ buildlib/pyverbs_functions.cmake | 36 ++++++++++++++++++++ buildlib/travis-build | 6 ++-- pyverbs/CMakeLists.txt | 14 ++++++++ 6 files changed, 142 insertions(+), 5 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 e093566b..f1c1c0ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,10 @@ addons: - gcc-8-multilib - lib32gcc-8-dev + # pyverbs + - python3-dev + - cython3 + service: - docker diff --git a/CMakeLists.txt b/CMakeLists.txt index 09cf3a12..219762a8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,14 @@ # -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. +# -DNO_PYVERBS=1 (default, build pyverbs) +# Invoke cython to build pyverbs. Usually you will run with this option +# is set, but it will be disabled for travis runs. cmake_minimum_required(VERSION 2.8.11 FATAL_ERROR) project(rdma-core C) @@ -87,6 +95,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") @@ -149,6 +158,7 @@ include(RDMA_BuildType) include(RDMA_DoFixup) include(publish_headers) include(rdma_functions) +include(pyverbs_functions) include(rdma_man) if (NOT DEFINED ENABLE_STATIC) @@ -350,8 +360,45 @@ else() set(HAVE_FULL_SYMBOL_VERSIONS 1) endif() -# Look for Python -FIND_PACKAGE(PythonInterp REQUIRED) +if (${NO_PYVERBS}) + set(CYTHON_EXECUTABLE "") +else () + # 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) +endif() + +# 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() +# 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) @@ -550,6 +597,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) @@ -608,6 +659,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..abf35163 --- /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} -fPIC -fno-strict-aliasing -Wno-unused-function -Wno-redundant-decls -Wno-shadow -Wno-cast-function-type -Wno-implicit-fallthrough -Wno-unknown-warning -Wno-unknown-warning-option" + 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/buildlib/travis-build b/buildlib/travis-build index cb1d72a3..b44f13e9 100755 --- a/buildlib/travis-build +++ b/buildlib/travis-build @@ -17,19 +17,19 @@ ninja cd ../build32 # travis is not configured in a way that enables all 32 bit # packages. We could fix this with some sudo stuff.. For now turn off libnl -CC=gcc-8 CFLAGS="-Werror -m32 -msse3" cmake -GNinja .. -DENABLE_RESOLVE_NEIGH=0 -DIOCTL_MODE=both +CC=gcc-8 CFLAGS="-Werror -m32 -msse3" cmake -GNinja .. -DENABLE_RESOLVE_NEIGH=0 -DIOCTL_MODE=both -DNO_PYVERBS=1 ninja # aarch64 build to check compilation on ARM 64bit platform cd ../build-aarch64 -CC=$HOME/aarch64/bin/aarch64-linux-gnu-gcc CFLAGS="-Werror -Wno-maybe-uninitialized" cmake -GNinja .. -DENABLE_RESOLVE_NEIGH=0 -DIOCTL_MODE=ioctl +CC=$HOME/aarch64/bin/aarch64-linux-gnu-gcc CFLAGS="-Werror -Wno-maybe-uninitialized" cmake -GNinja .. -DENABLE_RESOLVE_NEIGH=0 -DIOCTL_MODE=ioctl -DNO_PYVERBS=1 ninja # Run sparse on the subdirectories which are sparse clean cd ../build-sparse mv ../CMakeLists.txt ../CMakeLists-orig.txt grep -v "# NO SPARSE" ../CMakeLists-orig.txt > ../CMakeLists.txt -CC=cgcc CFLAGS="-Werror" cmake -GNinja .. -DIOCTL_MODE=both +CC=cgcc CFLAGS="-Werror" cmake -GNinja .. -DIOCTL_MODE=both -DNO_PYVERBS=1 ninja | grep -v '^\[' | tee out # sparse does not fail gcc on messages if [ -s out ]; then 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