# SPDX-FileCopyrightText: 2023 The Qt Company Ltd. # SPDX-FileCopyrightText: 2024 Manuel Alcaraz Zambrano # SPDX-License-Identifier: BSD-3-Clause # Based on https://code.qt.io/cgit/pyside/pyside-setup.git/tree/examples/widgetbinding/CMakeLists.txt #[=======================================================================[.rst: ECMGeneratePythonBindings ------------------------- This module is experimental and internal. The interface will likely change in the coming releases. Generate Python bindings using Shiboken. :: ecm_generate_python_bindings(PACKAGE_NAME VERSION WRAPPED_HEADER TYPESYSTEM GENERATED_SOURCES [ [...]] DEPENDENCIES [ [...]] QT_VERSION HOMEPAGE_URL ISSUES_URL AUTHOR README ) ```` is the name of the Python library that will be created. ``VERSION`` is the version of the library. ``WRAPPED_HEADER`` is a C++ header that contains all the required includes for the library. ``TYPESYSTEM`` is the XML file where the bindings are defined. ``GENERATED_SOURCES`` is the list of generated C++ source files by Shiboken that will be used to build the shared library. ``QT_VERSION`` is the minimum required Qt version of the library. ``DEPENDENCIES`` is the list of dependencies that the bindings uses. ``HOMEPAGE_URL`` is a URL to the proyect homepage. ``ISSUES_URL` is a URL where users can report bugs and feature requests. ``AUTHOR`` is a string with the author of the library. ``README`` is a Markdown file that will be used as the project's description on the Python Package Index. #]=======================================================================] set(MODULES_DIR ${CMAKE_CURRENT_LIST_DIR}) function(ecm_generate_python_bindings) set(options ) set(oneValueArgs PACKAGE_NAME WRAPPED_HEADER TYPESYSTEM VERSION QT_VERSION HOMEPAGE_URL ISSUES_URL AUTHOR README) set(multiValueArgs GENERATED_SOURCES DEPENDENCIES) cmake_parse_arguments(PB "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) # Ugly hacks because PySide6::pyside6 only includes /usr/includes/PySide6 and none of the sub directory # Qt bugreport: PYSIDE-2882 get_property(PYSIDE_INCLUDE_DIRS TARGET "PySide6::pyside6" PROPERTY INTERFACE_INCLUDE_DIRECTORIES) foreach(PYSIDE_INCLUDE_DIR ${PYSIDE_INCLUDE_DIRS}) file(GLOB PYSIDE_SUBDIRS LIST_DIRECTORIES true "${PYSIDE_INCLUDE_DIR}/*") foreach (PYSIDE_SUBDIR ${PYSIDE_SUBDIRS}) if (IS_DIRECTORY ${PYSIDE_SUBDIR}) set_property(TARGET PySide6::pyside6 APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${PYSIDE_SUBDIR} ) endif() endforeach() endforeach() list(APPEND PB_DEPENDENCIES PySide6::pyside6) list(APPEND PB_DEPENDENCIES Shiboken6::libshiboken) # Enable rpaths so that the built shared libraries find their dependencies. set(CMAKE_SKIP_BUILD_RPATH FALSE) set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) set(CMAKE_INSTALL_RPATH ${SHIBOKEN_PYTHON_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # Get the relevant include dirs, to pass them on to shiboken. set(INCLUDES "") if(WIN32) set(PATH_SEP "\;") else() set(PATH_SEP ":") endif() macro(make_path varname) # accepts any number of path variables string(REPLACE ";" "${PATH_SEP}" ${varname} "${ARGN}") endmacro() foreach(_dependency ${PB_DEPENDENCIES}) get_property(DEPENDENCY_INCLUDE_DIRS TARGET "${_dependency}" PROPERTY INTERFACE_INCLUDE_DIRECTORIES) make_path(_include_dirs $,${PATH_SEP}>) list(APPEND INCLUDES "--include-paths=${_include_dirs}") endforeach() # Set up the options to pass to shiboken. set(shiboken_options --enable-pyside-extensions ${INCLUDES} --include-paths=${CMAKE_SOURCE_DIR} --typesystem-paths=${CMAKE_SOURCE_DIR} --typesystem-paths=${PYSIDE_TYPESYSTEMS} --output-directory=${CMAKE_CURRENT_BINARY_DIR}) set(generated_sources_dependencies ${PB_WRAPPED_HEADER} ${PB_TYPESYSTEM}) # Add custom target to run shiboken to generate the binding cpp files. add_custom_command( OUTPUT ${PB_GENERATED_SOURCES} COMMAND shiboken6 ${shiboken_options} ${PB_WRAPPED_HEADER} ${PB_TYPESYSTEM} DEPENDS ${generated_sources_dependencies} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running generator for ${PB_TYPESYSTEM}" ) # Set the cpp files which will be used for the bindings library. set(${PB_PACKAGE_NAME}_sources ${PB_GENERATED_SOURCES}) # PySide6 uses deprecated code. get_property(_defs DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) list(FILTER _defs EXCLUDE REGEX [[^QT_DISABLE_DEPRECATED_BEFORE=]]) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS ${_defs}) get_property(_defs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS) list(FILTER _defs EXCLUDE REGEX [[^QT_DISABLE_DEPRECATED_BEFORE=]]) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY COMPILE_DEFINITIONS ${_defs}) # Define and build the bindings library. add_library(${PB_PACKAGE_NAME} SHARED ${${PB_PACKAGE_NAME}_sources}) target_link_libraries(${PB_PACKAGE_NAME} PRIVATE PySide6::pyside6 Shiboken6::libshiboken ${Python3_LIBRARIES} ) # Apply relevant include and link flags. target_include_directories(${PB_PACKAGE_NAME} PRIVATE ${PYSIDE_PYTHONPATH}/include ${SHIBOKEN_PYTHON_INCLUDE_DIRS} $ $ ) # Hide noisy warnings target_compile_options(${PB_PACKAGE_NAME} PRIVATE -Wno-cast-function-type -Wno-missing-include-dirs) # Adjust the name of generated module. set_property(TARGET ${PB_PACKAGE_NAME} PROPERTY PREFIX "") set_property(TARGET ${PB_PACKAGE_NAME} PROPERTY LIBRARY_OUTPUT_NAME "${PB_PACKAGE_NAME}.${Python3_SOABI}") set_property(TARGET ${PB_PACKAGE_NAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${PB_PACKAGE_NAME}/build/lib) # Build Python Wheel file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PB_PACKAGE_NAME}/${PB_PACKAGE_NAME}") configure_file("${MODULES_DIR}/ECMGeneratePythonBindings.toml.in" "${CMAKE_CURRENT_BINARY_DIR}/${PB_PACKAGE_NAME}/pyproject.toml") configure_file(${PB_README} "${CMAKE_CURRENT_BINARY_DIR}/${PB_PACKAGE_NAME}/README.md" COPYONLY) add_custom_command( TARGET ${PB_PACKAGE_NAME} POST_BUILD COMMAND Python3::Interpreter -m build --wheel WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${PB_PACKAGE_NAME}" COMMENT "Building Python Wheel" ) endfunction()