Spaces:
Sleeping
Sleeping
# Useful references: | |
# https://thomastrapp.com/blog/building-a-pypi-package-for-a-modern-cpp-project/ for reference | |
# https://www.benjack.io/2017/06/12/python-cpp-tests.html also interesting | |
# https://www.python.org/dev/peps/pep-0427/ the official package format description | |
set(_MAKE_PYTHON_WHEEL_LIST_DIR "${CMAKE_CURRENT_LIST_DIR}") | |
function( MakeWheel python_module) | |
cmake_parse_arguments(MAKEWHEEL "PRINT_HELP" "MODULE;VERSION;SUMMARY;DESCRIPTION;HOMEPAGE;AUTHOR;EMAIL;LICENCE" "REQUIRES" ${ARGN} ) | |
set(version ${MAKEWHEEL_VERSION}) | |
execute_process( | |
COMMAND ${Python_EXECUTABLE} -c " | |
from setuptools.dist import Distribution | |
from setuptools import Extension | |
def wheel_name(**kwargs): | |
# create a fake distribution from arguments | |
dist = Distribution(attrs=kwargs) | |
# finalize bdist_wheel command | |
bdist_wheel_cmd = dist.get_command_obj('bdist_wheel') | |
bdist_wheel_cmd.ensure_finalized() | |
# assemble wheel file name | |
distname = bdist_wheel_cmd.wheel_dist_name | |
tag = '-'.join(bdist_wheel_cmd.get_tag()) | |
return f'{distname};{tag}' | |
print(wheel_name(name='${python_module}', version='${version}', ext_modules=[Extension('dummy', ['summy.c'])])) | |
" | |
OUTPUT_VARIABLE wheel_filename | |
OUTPUT_STRIP_TRAILING_WHITESPACE | |
ERROR_QUIET | |
) | |
if(NOT wheel_filename) | |
message(STATUS "Python module `setuptools` required for correct wheel filename generation. Please install if needed.") | |
set(wheel_filename "unknown;unknown") | |
endif() | |
list(GET wheel_filename 0 distname) | |
list(GET wheel_filename 1 platformtag) | |
set(complete_tag "${distname}-${platformtag}") | |
set(wheel_filename "${CMAKE_BINARY_DIR}/${complete_tag}.whl") | |
set(wheel_distinfo "${CMAKE_BINARY_DIR}/${python_module}-${version}.dist-info") | |
set(wheel_data "${CMAKE_BINARY_DIR}/${python_module}-${version}.data") | |
set(wheel_generator_string "pango_wheelgen_${version}") | |
if( MAKEWHEEL_REQUIRES ) | |
set(MAKEWHEEL_REQUIRES "Requires-Dist: ${MAKEWHEEL_REQUIRES}") | |
string(REPLACE ";" "\nRequires-Dist: " MAKEWHEEL_REQUIRES "${MAKEWHEEL_REQUIRES}") | |
endif() | |
########################################## | |
## Create dist info folder | |
file(GLOB wheel_info_files "${_MAKE_PYTHON_WHEEL_LIST_DIR}/wheel-dist-info/*" ) | |
file(WRITE "${wheel_distinfo}/RECORD" "") | |
foreach(template_path ${wheel_info_files}) | |
get_filename_component(template_name "${template_path}" NAME) | |
configure_file( ${template_path} "${wheel_distinfo}/${template_name}" ) | |
file(SHA256 "${template_path}" file_sha) | |
file (SIZE "${template_path}" file_size) | |
file(APPEND "${wheel_distinfo}/RECORD" "${python_module}-${version}.dist-info/${template_name},sha256=${file_sha},${file_size}\n") | |
endforeach() | |
# TODO: Add line in RECORD for .so module itself (needs to be build time) | |
########################################## | |
## Place module into data folder | |
set_target_properties( ${python_module} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${wheel_data}/purelib") | |
########################################## | |
## Rule for creating file wheel zip | |
add_custom_command( | |
OUTPUT ${wheel_filename} | |
DEPENDS ${python_module} | |
COMMAND ${CMAKE_COMMAND} -E tar cf ${wheel_filename} --format=zip -- ${wheel_distinfo} ${wheel_data} | |
COMMENT "Creating Wheel ${wheel_filename}" | |
VERBATIM | |
) | |
########################################## | |
## Create a friendlier target name we can refer to | |
add_custom_target("${python_module}_wheel" DEPENDS "${wheel_filename}") | |
add_custom_target( | |
"${python_module}_pip_install" | |
DEPENDS "${python_module}_wheel" | |
COMMAND ${Python_EXECUTABLE} -mpip install "${wheel_filename}" --force-reinstall | |
COMMENT "Installing for selected Python '${Python_EXECUTABLE}'" | |
) | |
add_custom_target( | |
"${python_module}_pip_uninstall" | |
COMMAND ${Python_EXECUTABLE} -mpip uninstall -y ${python_module} | |
) | |
########################################## | |
## Help message since this is tricky for people | |
if(MAKEWHEEL_PRINT_HELP) | |
message(STATUS "Selected Python: '${Python_EXECUTABLE}'. cmake --build . -t ${python_module}_pip_install to use ${python_module} module.") | |
endif() | |
endfunction() | |