File size: 4,439 Bytes
739258a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# 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()