--- /dev/null +++ ./cmake/CMakeBuilder.py @@ -0,0 +1,13 @@ +from sipbuild import SetuptoolsBuilder + + +class CMakeBuilder(SetuptoolsBuilder): + def __init__(self, project, **kwargs): + print("Using the CMake builder") + super().__init__(project, **kwargs) + + def build(self): + """ Only Generate the source files """ + print("Generating the source files") + self._generate_bindings() + self._generate_scripts() \ No newline at end of file --- /dev/null +++ ./cmake/FindSIP.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2007, Simon Edwards +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of the Simon Edwards nor the +# names of its contributors may be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY Simon Edwards ''AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL Simon Edwards BE LIABLE FOR ANY +# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# FindSIP.py +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + +try: + import sipbuild + + print("sip_version:%06.0x" % sipbuild.version.SIP_VERSION) + print("sip_version_num:%d" % sipbuild.version.SIP_VERSION) + print("sip_version_str:%s" % sipbuild.version.SIP_VERSION_STR) + + from distutils.sysconfig import get_python_lib + python_modules_dir = get_python_lib(plat_specific=1) + print("default_sip_dir:%s" % python_modules_dir) +except ImportError: # Code for SIP v4 + import sipconfig + + sipcfg = sipconfig.Configuration() + print("sip_version:%06.0x" % sipcfg.sip_version) + print("sip_version_num:%d" % sipcfg.sip_version) + print("sip_version_str:%s" % sipcfg.sip_version_str) + print("sip_bin:%s" % sipcfg.sip_bin) + print("default_sip_dir:%s" % sipcfg.default_sip_dir) + print("sip_inc_dir:%s" % sipcfg.sip_inc_dir) + # SIP 4.19.10+ has new sipcfg.sip_module_dir + if hasattr(sipcfg, "sip_module_dir"): + print("sip_module_dir:%s" % sipcfg.sip_module_dir) + else: + print("sip_module_dir:%s" % sipcfg.sip_mod_dir) --- /dev/null +++ ./cmake/FindSIP.cmake @@ -0,0 +1,65 @@ +# Find SIP +# ~~~~~~~~ +# +# SIP website: http://www.riverbankcomputing.co.uk/sip/index.php +# +# Find the installed version of SIP. FindSIP should be called after Python +# has been found. +# +# This file defines the following variables: +# +# SIP_VERSION - The version of SIP found expressed as a 6 digit hex number +# suitable for comparison as a string. +# +# SIP_VERSION_STR - The version of SIP found as a human readable string. +# +# SIP_BINARY_PATH - Path and filename of the SIP command line executable. +# +# SIP_INCLUDE_DIR - Directory holding the SIP C++ header file. +# +# SIP_DEFAULT_SIP_DIR - Default directory where .sip files should be installed +# into. + +# Copyright (c) 2007, Simon Edwards +# Redistribution and use is allowed according to the terms of the BSD license. +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. + + + +IF(SIP_VERSION OR SIP_BUILD_EXECUTABLE) + # Already in cache, be silent + SET(SIP_FOUND TRUE) +ELSE() + + FIND_FILE(_find_sip_py FindSIP.py PATHS ${CMAKE_MODULE_PATH} NO_CMAKE_FIND_ROOT_PATH) + + EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} ${_find_sip_py} OUTPUT_VARIABLE sip_config) + IF(sip_config) + STRING(REGEX REPLACE "^sip_version:([^\n]+).*$" "\\1" SIP_VERSION ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_version_num:([^\n]+).*$" "\\1" SIP_VERSION_NUM ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config}) + STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config}) + IF(${SIP_VERSION_STR} VERSION_LESS 5) + STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_BINARY_PATH ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config}) + STRING(REGEX REPLACE ".*\nsip_module_dir:([^\n]+).*$" "\\1" SIP_MODULE_DIR ${sip_config}) + ELSE(${SIP_VERSION_STR} VERSION_LESS 5) + FIND_PROGRAM(SIP_BUILD_EXECUTABLE sip-build) + ENDIF(${SIP_VERSION_STR} VERSION_LESS 5) + SET(SIP_FOUND TRUE) + ENDIF(sip_config) + + IF(SIP_FOUND) + IF(NOT SIP_FIND_QUIETLY) + MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}") + ENDIF(NOT SIP_FIND_QUIETLY) + ELSE(SIP_FOUND) + IF(SIP_FIND_REQUIRED) + MESSAGE(FATAL_ERROR "Could not find SIP") + ENDIF(SIP_FIND_REQUIRED) + ENDIF(SIP_FOUND) + +ENDIF() + +include(${CMAKE_SOURCE_DIR}/cmake/SIPMacros.cmake) +ADD_DEFINITIONS(-DSIP_VERSION=0x${SIP_VERSION}) --- /dev/null +++ ./cmake/SIPMacros.cmake @@ -0,0 +1,105 @@ +# Macros for SIP +# ~~~~~~~~~~~~~~ + +set(SIP_ARGS --pep484-pyi --no-protected-is-public) + +function(add_sip_module MODULE_TARGET) + if(NOT SIP_BUILD_EXECUTABLE) + set(SIP_BUILD_EXECUTABLE ${CMAKE_PREFIX_PATH}/Scripts/sip-build) + endif() + + message(STATUS "SIP: Generating pyproject.toml") + configure_file(${CMAKE_SOURCE_DIR}/pyproject.toml.in ${CMAKE_CURRENT_BINARY_DIR}/pyproject.toml) + configure_file(${CMAKE_SOURCE_DIR}/cmake/CMakeBuilder.py ${CMAKE_CURRENT_BINARY_DIR}/CMakeBuilder.py) + if(WIN32) + set(ext .pyd) + set(env_path_sep ";") + else() + set(ext .so) + set(env_path_sep ":") + endif() + + message(STATUS "SIP: Generating source files") + execute_process( + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${PYTHONPATH}${env_path_sep}$ENV{PYTHONPATH}${env_path_sep}${CMAKE_CURRENT_BINARY_DIR}" ${SIP_BUILD_EXECUTABLE} ${SIP_ARGS} + COMMAND_ECHO STDOUT + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ + ) + # This will generate the source-files during the configuration step in CMake. Needed to obtain the sources + + # Touch the generated files (8 in total) to make them dirty and force them to rebuild + message(STATUS "SIP: Touching the source files") + set(_sip_output_files) + list(LENGTH SIP_FILES _no_outputfiles) + foreach(_concat_file_nr RANGE 0 ${_no_outputfiles}) + if(${_concat_file_nr} LESS 8) + list(APPEND _sip_output_files "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}/${MODULE_TARGET}/sip${MODULE_TARGET}part${_concat_file_nr}.cpp") + endif() + endforeach() + + # Find the generated source files + message(STATUS "SIP: Collecting the generated source files") + file(GLOB sip_c "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}/${MODULE_TARGET}/*.c") + file(GLOB sip_cpp "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}/${MODULE_TARGET}/*.cpp") + file(GLOB sip_hdr "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}/${MODULE_TARGET}/*.h") + + # Add the user specified source files + message(STATUS "SIP: Collecting the user specified source files") + get_target_property(usr_src ${MODULE_TARGET} SOURCES) + + # create the target library and link all the files (generated and user specified + message(STATUS "SIP: Linking the interface target against the shared library") + set(sip_sources "${sip_c}" "${sip_cpp}") + if(${usr_src}) + list(APPEND sip_sources "${usr_src}") + endif() + + if (BUILD_SHARED_LIBS) + add_library("sip_${MODULE_TARGET}" SHARED ${sip_sources}) + else() + add_library("sip_${MODULE_TARGET}" STATIC ${sip_sources}) + endif() + + # Make sure that the library name of the target is the same as the MODULE_TARGET with the appropriate extension + target_link_libraries("sip_${MODULE_TARGET}" PRIVATE "${MODULE_TARGET}") + set_target_properties("sip_${MODULE_TARGET}" PROPERTIES PREFIX "") + set_target_properties("sip_${MODULE_TARGET}" PROPERTIES SUFFIX ${ext}) + set_target_properties("sip_${MODULE_TARGET}" PROPERTIES OUTPUT_NAME "${MODULE_TARGET}") + + # Add the custom command to (re-)generate the files and mark them as dirty. This allows the user to actually work + # on the sip definition files without having to reconfigure the complete project. + add_custom_command( + TARGET "sip_${MODULE_TARGET}" + COMMAND ${CMAKE_COMMAND} -E env "PYTHONPATH=${PYTHONPATH}${env_path_sep}$ENV{PYTHONPATH}${env_path_sep}${CMAKE_CURRENT_BINARY_DIR}" ${SIP_BUILD_EXECUTABLE} ${SIP_ARGS} + COMMAND ${CMAKE_COMMAND} -E touch ${_sip_output_files} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ + MAIN_DEPENDENCY ${MODULE_SIP} + DEPENDS ${sip_sources} + VERBATIM + ) + + set_target_properties("sip_${MODULE_TARGET}" + PROPERTIES + RESOURCE "${CMAKE_CURRENT_BINARY_DIR}/${MODULE_TARGET}/${MODULE_TARGET}/${MODULE_TARGET}.pyi") +endfunction() + +function(install_sip_module MODULE_TARGET) + if(DEFINED ARGV1) + set(_install_path ${ARGV1}) + else() + if(DEFINED Python_SITEARCH) + set(_install_path ${Python_SITEARCH}) + elseif(DEFINED Python_SITELIB) + set(_install_path ${Python_SITELIB}) + else() + message(FATAL_ERROR "SIP: Specify the site-packages location") + endif() + endif() + message(STATUS "SIP: Installing Python module and PEP 484 file in ${_install_path}") + install(TARGETS "sip_${MODULE_TARGET}" + ARCHIVE DESTINATION ${_install_path} + LIBRARY DESTINATION ${_install_path} + RUNTIME DESTINATION ${_install_path} + RESOURCE DESTINATION ${_install_path} + ) +endfunction()