diff options
Diffstat (limited to 'cmake/modules/Distutils.cmake')
-rw-r--r-- | cmake/modules/Distutils.cmake | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/cmake/modules/Distutils.cmake b/cmake/modules/Distutils.cmake new file mode 100644 index 000000000..fe3ca410e --- /dev/null +++ b/cmake/modules/Distutils.cmake @@ -0,0 +1,144 @@ +include(CMakeParseArguments) + +# ensure that we are using the exact python version specified by +# 'WITH_PYTHON3', in case some included 3rd party libraries call +# 'find_package(Python3 ...) without specifying the exact version number. if +# the building host happens to have a higher version of python3, that version +# would be picked up instead by find_package(Python3). and that is not want we +# expect. +find_package(Python3 ${WITH_PYTHON3} EXACT + QUIET + REQUIRED + COMPONENTS Interpreter) + +function(distutils_install_module name) + set(py_srcs setup.py README.rst requirements.txt test-requirements.txt bin ${name}) + foreach(src ${py_srcs}) + if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${src}) + list(APPEND py_clone ${CMAKE_CURRENT_BINARY_DIR}/${src}) + add_custom_command( + OUTPUT ${src} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${src} + COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_CURRENT_SOURCE_DIR}/${src} ${src}) + endif() + endforeach() + if(NOT TARGET ${name}-clone) + add_custom_target(${name}-clone ALL + DEPENDS ${py_clone}) + endif() + cmake_parse_arguments(DU "" "INSTALL_SCRIPT" "" ${ARGN}) + install(CODE " + set(options --prefix=${CMAKE_INSTALL_PREFIX}) + if(DEFINED ENV{DESTDIR}) + if(EXISTS /etc/debian_version) + list(APPEND options --install-layout=deb) + endif() + list(APPEND options + --root=\$ENV{DESTDIR} + --single-version-externally-managed) + endif() + if(NOT \"${DU_INSTALL_SCRIPT}\" STREQUAL \"\") + list(APPEND options --install-script=${DU_INSTALL_SCRIPT}) + endif() + execute_process( + COMMAND ${Python3_EXECUTABLE} + setup.py install \${options} + WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")") +endfunction(distutils_install_module) + +function(distutils_add_cython_module target name src) + get_property(compiler_launcher GLOBAL PROPERTY RULE_LAUNCH_COMPILE) + get_property(link_launcher GLOBAL PROPERTY RULE_LAUNCH_LINK) + # When using ccache, CMAKE_C_COMPILER is ccache executable absolute path + # and the actual C compiler is CMAKE_C_COMPILER_ARG1. + # However with a naive + # set(PY_CC ${compiler_launcher} ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}) + # distutils tries to execve something like "/usr/bin/cmake gcc" and fails. + # Removing the leading whitespace from CMAKE_C_COMPILER_ARG1 helps to avoid + # the failure. + string(STRIP "${CMAKE_C_COMPILER_ARG1}" c_compiler_arg1) + string(STRIP "${CMAKE_CXX_COMPILER_ARG1}" cxx_compiler_arg1) + # Note: no quotes, otherwise distutils will execute "/usr/bin/ccache gcc" + # CMake's implicit conversion between strings and lists is wonderful, isn't it? + set(cflags ${COMPILE_OPTIONS}) + list(APPEND cflags -iquote${CMAKE_SOURCE_DIR}/src/include -w) + # This little bit of magic wipes out __Pyx_check_single_interpreter() + # Note: this is reproduced in distutils_install_cython_module + list(APPEND cflags -D'void0=dead_function\(void\)') + list(APPEND cflags -D'__Pyx_check_single_interpreter\(ARG\)=ARG\#\#0') + set(PY_CC ${compiler_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1} ${cflags}) + set(PY_CXX ${compiler_launcher} ${CMAKE_CXX_COMPILER} ${cxx_compiler_arg1}) + set(PY_LDSHARED ${link_launcher} ${CMAKE_C_COMPILER} ${c_compiler_arg1} "-shared") + + execute_process(COMMAND "${Python3_EXECUTABLE}" -c + "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))" + RESULT_VARIABLE result + OUTPUT_VARIABLE ext_suffix + ERROR_VARIABLE error + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT result EQUAL 0) + message(FATAL_ERROR "Unable to tell python extension's suffix: ${error}") + endif() + set(output_dir "${CYTHON_MODULE_DIR}/lib.3") + set(setup_py ${CMAKE_CURRENT_SOURCE_DIR}/setup.py) + add_custom_command( + OUTPUT ${output_dir}/${name}${ext_suffix} + COMMAND + env + CC="${PY_CC}" + CXX="${PY_CXX}" + LDSHARED="${PY_LDSHARED}" + OPT=\"-DNDEBUG -g -fwrapv -O2 -w\" + LDFLAGS=-L${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + CYTHON_BUILD_DIR=${CMAKE_CURRENT_BINARY_DIR} + CEPH_LIBDIR=${CMAKE_LIBRARY_OUTPUT_DIRECTORY} + ${Python3_EXECUTABLE} ${setup_py} + build --verbose --build-base ${CYTHON_MODULE_DIR} + --build-platlib ${output_dir} + MAIN_DEPENDENCY ${src} + DEPENDS ${setup_py} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + add_custom_target(${target} ALL + DEPENDS ${output_dir}/${name}${ext_suffix}) +endfunction(distutils_add_cython_module) + +function(distutils_install_cython_module name) + get_property(compiler_launcher GLOBAL PROPERTY RULE_LAUNCH_COMPILE) + get_property(link_launcher GLOBAL PROPERTY RULE_LAUNCH_LINK) + set(PY_CC "${compiler_launcher} ${CMAKE_C_COMPILER}") + set(PY_LDSHARED "${link_launcher} ${CMAKE_C_COMPILER} -shared") + install(CODE " + set(ENV{CC} \"${PY_CC}\") + set(ENV{LDSHARED} \"${PY_LDSHARED}\") + set(ENV{CPPFLAGS} \"-iquote${CMAKE_SOURCE_DIR}/src/include + -D'void0=dead_function\(void\)' \ + -D'__Pyx_check_single_interpreter\(ARG\)=ARG\#\#0'\") + set(ENV{LDFLAGS} \"-L${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\") + set(ENV{CYTHON_BUILD_DIR} \"${CMAKE_CURRENT_BINARY_DIR}\") + set(ENV{CEPH_LIBDIR} \"${CMAKE_LIBRARY_OUTPUT_DIRECTORY}\") + + set(options --prefix=${CMAKE_INSTALL_PREFIX}) + if(DEFINED ENV{DESTDIR}) + if(EXISTS /etc/debian_version) + list(APPEND options --install-layout=deb) + endif() + list(APPEND options --root=\$ENV{DESTDIR}) + else() + list(APPEND options --root=/) + endif() + execute_process( + COMMAND + ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/setup.py + build --verbose --build-base ${CYTHON_MODULE_DIR} + --build-platlib ${CYTHON_MODULE_DIR}/lib.3 + build_ext --cython-c-in-temp --build-temp ${CMAKE_CURRENT_BINARY_DIR} --cython-include-dirs ${PROJECT_SOURCE_DIR}/src/pybind/rados + install \${options} --single-version-externally-managed --record /dev/null + egg_info --egg-base ${CMAKE_CURRENT_BINARY_DIR} + --verbose + WORKING_DIRECTORY \"${CMAKE_CURRENT_SOURCE_DIR}\" + RESULT_VARIABLE install_res) + if(NOT \"\${install_res}\" STREQUAL 0) + message(FATAL_ERROR \"Failed to build and install ${name} python module\") + endif() + ") +endfunction(distutils_install_cython_module) |