Warning, /frameworks/extra-cmake-modules/find-modules/FindPythonModuleGeneration.cmake is written in an unsupported language. File is not indexed.

0001 # SPDX-FileCopyrightText: 2016 Stephen Kelly <steveire@gmail.com>
0002 #
0003 # SPDX-License-Identifier: BSD-3-Clause
0004 
0005 #[=======================================================================[.rst:
0006 FindPythonModuleGeneration
0007 --------------------------
0008 
0009 This module is experimental and internal.  The interface will likely
0010 change in the coming releases.
0011 
0012 Tools and macros for generating python bindings
0013 
0014 This will define the following public function:
0015 
0016   ecm_generate_python_binding(TARGET <target>
0017                               PYTHONNAMESPACE <namespace>
0018                               MODULENAME <modulename>
0019                               RULES_FILE <rulesfile>
0020                               SIP_DEPENDS <dependencies>
0021                               SIP_INCLUDES <includes>
0022                               HEADERS <headers>)
0023 
0024 Invoking the function will create bindings for the <target> for python 2 and 3,
0025 if available.  The bindings will be put in the namespace <namespace> in python,
0026 and will be available from the module <modulename>.
0027 
0028 The optional rules file specifies the rules for creating the bindings
0029 
0030 A simple invocation would be:
0031 
0032   ecm_generate_python_binding(TARGET KMyTarget
0033     PYTHONNAMESPACE PyKF5
0034     MODULENAME MyTarget
0035     SIP_DEPENDS QtCore/QtCoremod.sip
0036     HEADERS ${myTargetHeaders}
0037   )
0038 
0039 which can then be used from python as
0040 
0041   import PyKF5.MyTarget
0042 
0043 Inclusion of this module defines the following variables:
0044 
0045 ``KDE_INSTALL_PYTHON2DIR``, ``KDE_INSTALL_PYTHON3DIR``
0046     destination for generated bindings
0047 ``KDE_INSTALL_FULL_PYTHON2DIR``, ``KDE_INSTALL_FULL_PYTHON3DIR``
0048     corresponding absolute path
0049 
0050 If ``KDE_INSTALL_USE_PYTHON2_SYS_PATHS`` is set to TRUE before including this
0051 module, the default value for ``KDE_INSTALL_PYTHON2DIR`` is instead queried from
0052 pythons distutil.sysconfig.get_python_lib().
0053 If not set, it will default to TRUE if pythons ``sysconfig.PREFIX`` is the same
0054 as ``CMAKE_INSTALL_PREFIX``, otherwise it defaults to FALSE.
0055 This variable should NOT be set from within CMakeLists.txt files, instead it
0056 is intended to be set manually when configuring a project which uses this
0057 module (e.g. by packagers).
0058 
0059 Likewise for ``KDE_INSTALL_USE_PYTHON3_SYS_PATHS`` and ``KDE_INSTALL_PYTHON3DIR``.
0060 #]=======================================================================]
0061 
0062 macro(_find_python version minor_version)
0063   set(_CURRENT_VERSION ${version}.${minor_version})
0064   find_library(GPB_PYTHON${version}_LIBRARY
0065     NAMES
0066       python${_CURRENT_VERSION}mu
0067       python${_CURRENT_VERSION}m
0068       python${_CURRENT_VERSION}u
0069       python${_CURRENT_VERSION}
0070     PATHS
0071       [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
0072       [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/libs
0073     # Avoid finding the .dll in the PATH.  We want the .lib.
0074     NO_SYSTEM_ENVIRONMENT_PATH
0075   )
0076 
0077   if(GPB_PYTHON${version}_LIBRARY)
0078     # Use the library's install prefix as a hint
0079     set(_Python_INCLUDE_PATH_HINT)
0080     get_filename_component(_Python_PREFIX ${GPB_PYTHON${version}_LIBRARY} PATH)
0081     get_filename_component(_Python_PREFIX ${_Python_PREFIX} PATH)
0082     if(_Python_PREFIX)
0083       set(_Python_INCLUDE_PATH_HINT ${_Python_PREFIX}/include)
0084     endif()
0085     unset(_Python_PREFIX)
0086 
0087     find_path(GPB_PYTHON${version}_INCLUDE_DIR
0088       NAMES Python.h
0089       HINTS
0090         ${_Python_INCLUDE_PATH_HINT}
0091       PATHS
0092         [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
0093         [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_CURRENT_VERSION}\\InstallPath]/include
0094       PATH_SUFFIXES
0095         python${_CURRENT_VERSION}mu
0096         python${_CURRENT_VERSION}m
0097         python${_CURRENT_VERSION}u
0098         python${_CURRENT_VERSION}
0099     )
0100     # sip.h is version agnostic, it may be located in the version specific path
0101     # or one of the default locations
0102     find_path(GPB_PYTHON${version}_SIP_DIR
0103        NAMES sip.h
0104        PATHS
0105          ${GPB_PYTHON${version}_INCLUDE_DIR}
0106     )
0107   endif()
0108 
0109   find_program(GPB_PYTHON${version}_COMMAND python${version})
0110 endmacro()
0111 
0112 macro(_create_imported_python_target version)
0113   if(GPB_PYTHON${version}_LIBRARY AND GPB_PYTHON${version}_INCLUDE_DIR AND
0114      EXISTS "${GPB_PYTHON${version}_INCLUDE_DIR}/patchlevel.h" AND
0115      EXISTS "${GPB_PYTHON${version}_SIP_DIR}/sip.h")
0116     list(APPEND _pyversions ${version})
0117 
0118     file(STRINGS "${GPB_PYTHON${version}_INCLUDE_DIR}/patchlevel.h" python_version_define
0119          REGEX "^#define[ \t]+PY_MINOR_VERSION[ \t]+[0-9]+")
0120     string(REGEX REPLACE "^#define[ \t]+PY_MINOR_VERSION[ \t]+([0-9]+)" "\\1"
0121                          min_ver "${python_version_define}")
0122     unset(python_version_define)
0123 
0124     set(pyversion${version}_maj_min ${version}.${min_ver})
0125 
0126     add_library(Python::Libs${version} UNKNOWN IMPORTED)
0127     set_property(TARGET Python::Libs${version} PROPERTY IMPORTED_LOCATION ${GPB_PYTHON${version}_LIBRARY})
0128     set_property(TARGET Python::Libs${version} PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GPB_PYTHON${version}_INCLUDE_DIR})
0129 
0130     set(_default_KDE_INSTALL_USE_PYTHON${version}_SYS_PATHS OFF)
0131     if(NOT DEFINED KDE_INSTALL_USE_PYTHON${version}_SYS_PATHS)
0132       execute_process (
0133         COMMAND "${GPB_PYTHON${version}_COMMAND}" -c "import sys; from distutils import sysconfig;sys.stdout.write(sysconfig.PREFIX)"
0134         OUTPUT_VARIABLE gpb_python${version}_prefix
0135       )
0136       if(gpb_python${version}_prefix STREQUAL "${CMAKE_INSTALL_PREFIX}")
0137         message(STATUS "Installing in the same prefix as Python${version}, adopting their path scheme.")
0138         set(_default_KDE_INSTALL_USE_PYTHON${version}_SYS_PATHS ON)
0139       else()
0140         message(STATUS "NOT installing in the same prefix as Python${version}.")
0141       endif()
0142     endif()
0143 
0144   endif()
0145 endmacro()
0146 
0147 macro(_report_NOT_FOUND message)
0148   if(NOT ${CMAKE_FIND_PACKAGE_NAME}_FIND_QUIETLY)
0149     set(_GPB_MESSAGE_TYPE STATUS)
0150     if(${CMAKE_FIND_PACKAGE_NAME}_FIND_REQUIRED)
0151       set(_GPB_MESSAGE_TYPE FATAL_ERROR)
0152     endif()
0153     message(${_GPB_MESSAGE_TYPE} ${message})
0154   endif()
0155   set(PythonModuleGeneration_FOUND FALSE)
0156   return()
0157 endmacro()
0158 
0159 if (NOT Qt5Core_FOUND)
0160   _report_NOT_FOUND("Qt 5 must be found before finding ${CMAKE_FIND_PACKAGE_NAME}.")
0161 endif()
0162 
0163 if (NOT GPB_PYTHON3_LIBRARY)
0164   set(_PYTHON3_MIN_VERSION 4)
0165 
0166   # This value is safe to increment over time, it is used only as a reasonable
0167   # upper bound to start searching from
0168   set(_PYTHON3_MAX_VERSION 50)
0169 
0170   _find_python(3 ${_PYTHON3_MAX_VERSION})
0171 
0172   if (GPB_PYTHON3_LIBRARY)
0173     message(FATAL_ERROR "The max python version in ${CMAKE_FIND_PACKAGE_NAME} must be updated.")
0174   endif()
0175 
0176   # Look for the highest supported version of Python 3 by looking for a minor
0177   # version that doesn't exist and decrementing until we find a match.
0178   set(_PYTHON3_FIND_VERSION ${_PYTHON3_MAX_VERSION})
0179 
0180   while(NOT GPB_PYTHON3_LIBRARY
0181       AND NOT GPB_PYTHON3_INCLUDE_DIR
0182       AND NOT EXISTS "${GPB_PYTHON3_INCLUDE_DIR}/patchlevel.h"
0183       AND NOT _PYTHON3_FIND_VERSION EQUAL ${_PYTHON3_MIN_VERSION})
0184     math(EXPR _PYTHON3_FIND_VERSION "${_PYTHON3_FIND_VERSION} - 1")
0185     _find_python(3 ${_PYTHON3_FIND_VERSION})
0186   endwhile()
0187 endif()
0188 _create_imported_python_target(3)
0189 
0190 _find_python(2 7)
0191 _create_imported_python_target(2)
0192 
0193 option (KDE_INSTALL_USE_PYTHON3_SYS_PATHS "Install Python3 bindings to the Python3 install dir"
0194         "${_default_KDE_INSTALL_USE_PYTHON3_SYS_PATHS}")
0195 option (KDE_INSTALL_USE_PYTHON2_SYS_PATHS "Install Python2 bindings to the Python2 install dir"
0196         "${_default_KDE_INSTALL_USE_PYTHON2_SYS_PATHS}")
0197 
0198 if (NOT _pyversions)
0199   _report_NOT_FOUND("At least one python version must be available to use ${CMAKE_FIND_PACKAGE_NAME}.")
0200 endif()
0201 
0202 foreach(pyversion ${_pyversions})
0203 
0204   if(KDE_INSTALL_PYTHON${pyversion}DIR)
0205      # Use dir from command line
0206 
0207   elseif(KDE_INSTALL_USE_PYTHON${pyversion}_SYS_PATHS)
0208     execute_process (
0209       COMMAND "${GPB_PYTHON${pyversion}_COMMAND}" -c "import sys; from distutils import sysconfig;sys.stdout.write(sysconfig.get_python_lib(plat_specific=True,standard_lib=False))"
0210       OUTPUT_VARIABLE KDE_INSTALL_PYTHON${pyversion}DIR
0211     )
0212 
0213   else()
0214     set(KDE_INSTALL_PYTHON${pyversion}DIR lib/python${pyversion${pyversion}_maj_min}/site-packages)
0215   endif()
0216 
0217   if(NOT IS_ABSOLUTE ${KDE_INSTALL_PYTHON${pyversion}DIR})
0218     set(KDE_INSTALL_FULL_PYTHON${pyversion}DIR
0219         "${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_PYTHON${pyversion}DIR}")
0220   else()
0221     set(KDE_INSTALL_FULL_PYTHON${pyversion}DIR "${KDE_INSTALL_PYTHON${pyversion}DIR}")
0222   endif()
0223 
0224 endforeach()
0225 
0226 find_program(GBP_SIP_COMMAND sip)
0227 
0228 if (NOT GBP_SIP_COMMAND)
0229   _report_NOT_FOUND("The sip executable must be available to use ${CMAKE_FIND_PACKAGE_NAME}.")
0230 endif()
0231 
0232 if (NOT libclang_LIBRARY)
0233   set(_LIBCLANG_MAX_MAJOR_VERSION 7)
0234   set(_LIBCLANG_MIN_MAJOR_VERSION 5)
0235 
0236   find_library(libclang_LIBRARY clang-${_LIBCLANG_MAX_MAJOR_VERSION}.0)
0237 
0238   if (libclang_LIBRARY)
0239     message(FATAL_ERROR "The max libclang version in ${CMAKE_FIND_PACKAGE_NAME} must be updated.")
0240   endif()
0241 
0242   set(_LIBCLANG_FIND_VERSION ${_LIBCLANG_MAX_MAJOR_VERSION})
0243   while(NOT libclang_LIBRARY AND NOT _LIBCLANG_FIND_VERSION EQUAL _LIBCLANG_MIN_MAJOR_VERSION)
0244     math(EXPR _LIBCLANG_FIND_VERSION "${_LIBCLANG_FIND_VERSION} - 1")
0245     set(_GPB_CLANG_SUFFIX ${_LIBCLANG_FIND_VERSION}.0)
0246     find_library(libclang_LIBRARY clang-${_LIBCLANG_FIND_VERSION}.0)
0247   endwhile()
0248 
0249   if (NOT libclang_LIBRARY)
0250     find_library(libclang_LIBRARY clang)
0251   endif()
0252 else()
0253   string(REGEX MATCH ".*clang-([0-9]+\\.[0-9]+).*" _GPB_CLANG_SUFFIX ${libclang_LIBRARY})
0254   set(_GPB_CLANG_SUFFIX ${CMAKE_MATCH_1})
0255 endif()
0256 
0257 if (NOT libclang_LIBRARY)
0258   _report_NOT_FOUND("Could not find libclang version 5.0 or greater.")
0259 else()
0260   message(STATUS "Found ${libclang_LIBRARY}")
0261 endif()
0262 
0263 foreach (pyversion "3" "2")
0264   set(GPB_PYTHON_COMMAND ${GPB_PYTHON${pyversion}_COMMAND})
0265   if (NOT GPB_PYTHON_COMMAND)
0266     continue()
0267   endif()
0268   message(STATUS "Testing if ${GPB_PYTHON_COMMAND} can be used to run sip_generator")
0269 
0270   execute_process(
0271     COMMAND ${GPB_PYTHON_COMMAND} ${CMAKE_CURRENT_LIST_DIR}/sip_generator.py --self-check ${libclang_LIBRARY}
0272     RESULT_VARIABLE selfCheckErrors
0273     ERROR_QUIET
0274   )
0275 
0276   if (selfCheckErrors)
0277     message(STATUS "sip_generator self-check for ${GPB_PYTHON_COMMAND} failed")
0278     unset(GPB_PYTHON_COMMAND)
0279   else()
0280     message(STATUS "Self-check passed, Using ${GPB_PYTHON_COMMAND} to generate bindings")
0281     break()
0282   endif()
0283 endforeach()
0284 
0285 if (NOT GPB_PYTHON_COMMAND)
0286    _report_NOT_FOUND("No usable python version found to run sip_generator for the ${CMAKE_FIND_PACKAGE_NAME} Module.")
0287 endif()
0288 
0289 get_filename_component(libclang_file "${libclang_file}" REALPATH)
0290 
0291 find_file(SIP_Qt5Core_Mod_FILE
0292   NAMES QtCoremod.sip
0293   HINTS ${KDE_INSTALL_PYTHON3DIR}/PyQt5/bindings/QtCore
0294   PATH_SUFFIXES share/sip/PyQt5/QtCore
0295 )
0296 
0297 if(NOT SIP_Qt5Core_Mod_FILE)
0298   _report_NOT_FOUND("PyQt module files not found for the ${CMAKE_FIND_PACKAGE_NAME} Module.")
0299 endif()
0300 
0301 set(PythonModuleGeneration_FOUND TRUE)
0302 
0303 set(GPB_MODULE_DIR ${CMAKE_CURRENT_LIST_DIR})
0304 
0305 function(_compute_implicit_include_dirs)
0306   find_program(_GBP_CLANG_CXX_DRIVER_PATH NAMES clang++-${_GPB_CLANG_SUFFIX} clang++)
0307   if (NOT _GBP_CLANG_CXX_DRIVER_PATH)
0308     message(FATAL_ERROR "Failed to find clang driver corresponding to ${libclang_LIBRARY}")
0309   endif()
0310   execute_process(COMMAND ${_GBP_CLANG_CXX_DRIVER_PATH} -v -E -x c++ -
0311                   ERROR_VARIABLE _compilerOutput
0312                   OUTPUT_VARIABLE _compilerStdout
0313                   INPUT_FILE /dev/null)
0314 
0315   if( "${_compilerOutput}" MATCHES "> search starts here[^\n]+\n *(.+ *\n) *End of (search) list" )
0316 
0317     # split the output into lines and then remove leading and trailing spaces from each of them:
0318     string(REGEX MATCHALL "[^\n]+\n" _includeLines "${CMAKE_MATCH_1}")
0319     foreach(nextLine ${_includeLines})
0320       # on OSX, gcc says things like this:  "/System/Library/Frameworks (framework directory)", strip the last part
0321       string(REGEX REPLACE "\\(framework directory\\)" "" nextLineNoFramework "${nextLine}")
0322       # strip spaces at the beginning and the end
0323       string(STRIP "${nextLineNoFramework}" _includePath)
0324       list(APPEND _resultIncludeDirs "${_includePath}")
0325     endforeach()
0326   endif()
0327 
0328   set(_GPB_IMPLICIT_INCLUDE_DIRS ${_resultIncludeDirs} PARENT_SCOPE)
0329 endfunction()
0330 
0331 function(ecm_generate_python_binding)
0332 
0333     set(oneValueArgs TARGET PYTHONNAMESPACE MODULENAME RULES_FILE)
0334     set(multiValueArgs SIP_DEPENDS SIP_INCLUDES HEADERS)
0335 
0336     cmake_parse_arguments(GPB "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
0337 
0338     file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${GPB_MODULENAME}mod.sip"
0339           "
0340 %Module ${GPB_PYTHONNAMESPACE}.${GPB_MODULENAME}
0341 
0342 %ModuleHeaderCode
0343 #pragma GCC visibility push(default)
0344 %End\n\n")
0345 
0346     set(generator_depends "${GPB_MODULE_DIR}/sip_generator.py"
0347         "${GPB_MODULE_DIR}/rules_engine.py"
0348         "${GPB_MODULE_DIR}/FindPythonModuleGeneration.cmake"
0349         )
0350 
0351     if (NOT _GPB_IMPLICIT_INCLUDE_DIRS)
0352       _compute_implicit_include_dirs()
0353     endif()
0354 
0355     foreach(dep ${GPB_SIP_DEPENDS})
0356         if (IS_ABSOLUTE ${dep})
0357           list(APPEND generator_depends "${dep}")
0358         endif()
0359         file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${GPB_MODULENAME}mod.sip"
0360           "%Import ${dep}\n\n")
0361     endforeach()
0362 
0363     set(sip_files)
0364     set(commands)
0365 
0366     if (NOT GPB_RULES_FILE)
0367       set(GPB_RULES_FILE "${GPB_MODULE_DIR}/Qt5Ruleset.py")
0368     endif()
0369 
0370     list(APPEND generator_depends ${GPB_RULES_FILE})
0371 
0372     foreach(hdr ${GPB_HEADERS})
0373 
0374         get_filename_component(hdr_file ${hdr} ABSOLUTE)
0375 
0376         get_filename_component(hdr ${hdr} NAME_WE)
0377         string(TOLOWER ${hdr}.h hdr_filename)
0378 
0379         if (NOT EXISTS "${hdr_file}")
0380           message(FATAL_ERROR "File not found: ${hdr_file}")
0381         endif()
0382 
0383         set(sip_file "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${hdr}.sip")
0384         list(APPEND sip_files ${sip_file})
0385 
0386         set(inc_dirs "-I$<JOIN:$<TARGET_PROPERTY:${GPB_TARGET},INTERFACE_INCLUDE_DIRECTORIES>,;-I>")
0387         set(sys_inc_dirs)
0388         foreach(d ${_GPB_IMPLICIT_INCLUDE_DIRS})
0389            list(APPEND sys_inc_dirs "-isystem" "${d}")
0390         endforeach()
0391         set(comp_defs "-D$<JOIN:$<TARGET_PROPERTY:${GPB_TARGET},INTERFACE_COMPILE_DEFINITIONS>,;-D>")
0392 
0393         # We might like to use $<TARGET_PROPERTY:${GPB_TARGET},CXX_STANDARD>, but
0394         # unfortunately CMake does not populate that property as a side-effect of evaluating
0395         # COMPILE_FEATURES (Qt specifies feature requirements in its INTERFACE_COMPILE_FEATURES, and
0396         # those are consumed to set the CXX_STANDARD internally in CMake, but evidently too late)
0397         set(stdFlag "-std=gnu++14")
0398 
0399         set(comp_flags "$<JOIN:$<TARGET_PROPERTY:${GPB_TARGET},INTERFACE_COMPILE_OPTIONS>;${stdFlag},;>")
0400 
0401         add_custom_command(OUTPUT ${sip_file}
0402             COMMAND ${GPB_PYTHON_COMMAND} ${GPB_MODULE_DIR}/sip_generator.py
0403               --flags " ${inc_dirs};${sys_inc_dirs};${comp_defs};${comp_flags}"
0404               --include_filename "${hdr_filename}"
0405               ${libclang_LIBRARY}
0406               ${GPB_RULES_FILE}
0407               "${hdr_file}"
0408               "${sip_file}"
0409             DEPENDS ${hdr_file} ${generator_depends}
0410             VERBATIM
0411         )
0412 
0413         file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${GPB_MODULENAME}mod.sip"
0414           "%Include ${hdr}.sip\n")
0415     endforeach()
0416 
0417     file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/module.sbf"
0418         "
0419 target = ${GPB_MODULENAME}
0420 sources = sip${GPB_MODULENAME}cmodule.cpp
0421 headers = sipAPI${GPB_MODULENAME}
0422 "
0423     )
0424 
0425     get_filename_component(SIP_PYQT5_DIR ${SIP_Qt5Core_Mod_FILE} PATH)
0426     get_filename_component(SIP_PYQT5_DIR ${SIP_PYQT5_DIR} PATH)
0427 
0428     set(sip_includes -I "${SIP_PYQT5_DIR}")
0429     if (GPB_SIP_INCLUDES)
0430       list(APPEND sip_includes -I "$<JOIN:${GPB_SIP_INCLUDES},-I>")
0431     endif()
0432     foreach(path ${CMAKE_PREFIX_PATH} ${CMAKE_INSTALL_PREFIX})
0433       if (EXISTS ${path}/share/sip)
0434         list(APPEND sip_includes -I "${path}/share/sip")
0435       endif()
0436     endforeach()
0437 
0438     add_custom_target(generate_${GPB_MODULENAME}_sip_files ALL DEPENDS ${sip_files})
0439 
0440     add_custom_command(OUTPUT
0441       "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/unified${GPB_MODULENAME}.cpp"
0442       COMMAND ${GPB_PYTHON_COMMAND} "${GPB_MODULE_DIR}/run-sip.py" --sip ${GBP_SIP_COMMAND}
0443        --unify "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/unified${GPB_MODULENAME}.cpp"
0444        --module-name "${GPB_MODULENAME}"
0445        -c "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}"
0446        -b "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/module.sbf"
0447 
0448        -x VendorID -x Py_v3
0449 
0450        -I "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}"
0451        ${sip_includes}
0452        "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${GPB_MODULENAME}mod.sip"
0453        DEPENDS generate_${GPB_MODULENAME}_sip_files "${GPB_MODULE_DIR}/run-sip.py" ${generator_depends}
0454     )
0455 
0456     add_custom_target(sip_generated_${GPB_MODULENAME}_files ALL
0457           DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/unified${GPB_MODULENAME}.cpp")
0458 
0459     file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}"
0460          "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}")
0461 
0462     foreach(pyversion ${_pyversions})
0463         message(STATUS "Found dependencies for python${pyversion}, generating bindings")
0464         message(STATUS "Python${pyversion} install dir: ${KDE_INSTALL_FULL_PYTHON${pyversion}DIR}")
0465 
0466         execute_process(COMMAND "${CMAKE_COMMAND}"
0467           "-DPYTHON_UMBRELLA_MODULE_FILE=${CMAKE_BINARY_DIR}/py${pyversion}/${GPB_PYTHONNAMESPACE}/__init__.py"
0468           -P "${GPB_MODULE_DIR}/GeneratePythonBindingUmbrellaModule.cmake"
0469         )
0470 
0471         add_library(Py${pyversion}KF5${GPB_MODULENAME} MODULE
0472           "${CMAKE_CURRENT_BINARY_DIR}/pybuild/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/unified${GPB_MODULENAME}.cpp"
0473         )
0474         add_dependencies(Py${pyversion}KF5${GPB_MODULENAME} sip_generated_${GPB_MODULENAME}_files)
0475         target_link_libraries(Py${pyversion}KF5${GPB_MODULENAME} PRIVATE ${GPB_TARGET} Python::Libs${pyversion})
0476 
0477         target_compile_options(Py${pyversion}KF5${GPB_MODULENAME} PRIVATE -fstack-protector-strong -Wno-deprecated-declarations -Wno-overloaded-virtual)
0478         target_include_directories(Py${pyversion}KF5${GPB_MODULENAME} PRIVATE ${GPB_SIP_INCLUDES})
0479         target_link_libraries(Py${pyversion}KF5${GPB_MODULENAME} PRIVATE -Wl,-Bsymbolic-functions -Wl,-z,relro)
0480 
0481         set_property(TARGET Py${pyversion}KF5${GPB_MODULENAME} PROPERTY AUTOMOC OFF)
0482         set_property(TARGET Py${pyversion}KF5${GPB_MODULENAME} PROPERTY PREFIX "")
0483         set_property(TARGET Py${pyversion}KF5${GPB_MODULENAME} PROPERTY LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/py${pyversion}/${GPB_PYTHONNAMESPACE}")
0484         set_property(TARGET Py${pyversion}KF5${GPB_MODULENAME} PROPERTY
0485             OUTPUT_NAME "${GPB_MODULENAME}")
0486 
0487         if (GPB_SIP_DEPENDS MATCHES PyKF5)
0488           set(_kf5_python_prefix ${KDE_INSTALL_FULL_PYTHON${pyversion}DIR})
0489         else()
0490           set(_kf5_python_prefix ${CMAKE_BINARY_DIR}/py${pyversion})
0491         endif()
0492         add_test(NAME Py${pyversion}Test${GPB_MODULENAME} COMMAND
0493             ${GPB_PYTHON${pyversion}_COMMAND} "${CMAKE_SOURCE_DIR}/autotests/pythontest.py"
0494             ${_kf5_python_prefix}
0495         )
0496 
0497         install(DIRECTORY ${CMAKE_BINARY_DIR}/py${pyversion}/${GPB_PYTHONNAMESPACE}
0498           DESTINATION ${KDE_INSTALL_PYTHON${pyversion}DIR})
0499         install(FILES ${sip_files} "${CMAKE_CURRENT_BINARY_DIR}/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}/${GPB_MODULENAME}mod.sip"
0500           DESTINATION share/sip/${GPB_PYTHONNAMESPACE}/${GPB_MODULENAME}
0501         )
0502     endforeach()
0503 endfunction()