ceph/cmake/modules/Distutils.cmake
Kefu Chai de9a04027f cmake/modules/Distutils: do not add ${name}-clone if already added
if `distutils_install_module("foo" ...)` is called mutiple times with
different python version, `foo-clone` will be added multiple times as a
custom target. which is not allowed:

add_custom_target cannot create target "foo-clone" because another
target with the same name already exists.

Signed-off-by: Kefu Chai <kchai@redhat.com>
2019-07-26 12:11:25 +02:00

144 lines
6.2 KiB
CMake

include(CMakeParseArguments)
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;PYTHON_VERSION" "" ${ARGN})
if(DU_PYTHON_VERSION)
set(python_version ${DU_PYTHON_VERSION})
else()
set(python_version 3)
endif()
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)
if(NOT \"${DU_INSTALL_SCRIPT}\" STREQUAL \"\")
list(APPEND options --install-script=${DU_INSTALL_SCRIPT})
endif()
endif()
execute_process(
COMMAND ${Python${python_version}_EXECUTABLE}
setup.py install \${options}
WORKING_DIRECTORY \"${CMAKE_CURRENT_BINARY_DIR}\")")
endfunction(distutils_install_module)
function(distutils_add_cython_module target name src python_version)
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?
string(REPLACE " " ";" cflags ${CMAKE_C_FLAGS})
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")
if(${Python${python_version}_VERSION_MAJOR} STREQUAL "2")
set(suffix_var "SO")
else()
set(suffix_var "EXT_SUFFIX")
endif()
execute_process(COMMAND "${Python${python_version}_EXECUTABLE}" -c
"from distutils import sysconfig; print(sysconfig.get_config_var('${suffix_var}'))"
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.${Python${python_version}_VERSION_MAJOR}")
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}
${Python${python_version}_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 python_version)
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
${Python${python_version}_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/setup.py
build --verbose --build-base ${CYTHON_MODULE_DIR}
--build-platlib ${CYTHON_MODULE_DIR}/lib.${Python${python_version}_VERSION_MAJOR}
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)