# Copyright (C) 2023 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause cmake_minimum_required(VERSION 3.18) cmake_policy(VERSION 3.18) # Enable policy to not use RPATH settings for install_name on macOS. if(POLICY CMP0068) cmake_policy(SET CMP0068 NEW) endif() # Enable policy to run automoc on generated files. if(POLICY CMP0071) cmake_policy(SET CMP0071 NEW) endif() # Consider changing the project name to something relevant for you. project(wiggly LANGUAGES CXX) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) find_package(Qt6 COMPONENTS Core Gui Widgets) # ================================ General configuration ====================================== # Set CPP standard to C++17 minimum. set(CMAKE_CXX_STANDARD 17) # The wiggly library for which we will create bindings. You can change the name to something # relevant for your project. set(wiggly_library "libwiggly") # The name of the generated bindings module (as imported in Python). You can change the name # to something relevant for your project. set(bindings_library "wiggly") # The header file with all the types and functions for which bindings will be generated. # Usually it simply includes other headers of the library you are creating bindings for. set(wrapped_header ${CMAKE_SOURCE_DIR}/bindings.h) # The typesystem xml file which defines the relationships between the C++ types / functions # and the corresponding Python equivalents. set(typesystem_file ${CMAKE_SOURCE_DIR}/bindings.xml) # Specify which C++ files will be generated by shiboken. This includes the module wrapper # and a '.cpp' file per C++ type. These are needed for generating the module shared # library. set(generated_sources ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/wiggly_module_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/wigglywidget_wrapper.cpp) # ================================== Dependency detection ====================================== # Find required packages find_package(Python COMPONENTS Interpreter Development REQUIRED) # On RHEL and some other distros, Python wheels and site-packages may be installed under 'lib64' # instead of 'lib'. The FindPython CMake module may set Python_SITELIB to 'lib', which is incorrect # for these cases. To ensure compatibility, we override Python_SITELIB by querying Python directly. # This guarantees the correct site-packages path is used regardless of platform or Python build. execute_process( COMMAND ${Python_EXECUTABLE} -c "import site; print(next(p for p in site.getsitepackages() if 'site-packages' in p))" OUTPUT_VARIABLE Python_SITELIB OUTPUT_STRIP_TRAILING_WHITESPACE ) list(APPEND CMAKE_PREFIX_PATH "${Python_SITELIB}/shiboken6_generator/lib/cmake" ) find_package(Shiboken6Tools REQUIRED) # ==================================== RPATH configuration ==================================== # ============================================================================================= # !!! (The section below is deployment related, so in a real world application you will want to # take care of this properly with some custom script or tool). # ============================================================================================= # 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 ${CMAKE_CURRENT_SOURCE_DIR}) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) # ============================================================================================= # !!! End of dubious section. # ============================================================================================= # =============================== CMake target - wiggly_library =============================== # Get the relevant Qt include dirs, to pass them on to shiboken. get_property(QT_WIDGETS_INCLUDE_DIRS TARGET Qt6::Widgets PROPERTY INTERFACE_INCLUDE_DIRECTORIES) set(INCLUDES "") foreach(INCLUDE_DIR ${QT_WIDGETS_INCLUDE_DIRS}) list(APPEND INCLUDES "-I${INCLUDE_DIR}") endforeach() # On macOS, check if Qt is a framework build. This affects how include paths should be handled. get_target_property(QtCore_is_framework Qt6::Core FRAMEWORK) if (QtCore_is_framework) get_target_property(qt_core_library_location Qt6::Core LOCATION) get_filename_component(qt_core_library_location_dir "${qt_core_library_location}" DIRECTORY) get_filename_component(lib_dir "${qt_core_library_location_dir}/../" ABSOLUTE) list(APPEND INCLUDES "--framework-include-paths=${lib_dir}") endif() # We need to include the headers for the module bindings that we use. set(pyside_additional_includes "") foreach(INCLUDE_DIR ${pyside_include_dir}) list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtCore") list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtGui") list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtWidgets") endforeach() # Define the wiggly shared library for which we will create bindings. set(${wiggly_library}_sources wigglywidget.cpp) add_library(${wiggly_library} SHARED ${${wiggly_library}_sources}) set_property(TARGET ${wiggly_library} PROPERTY PREFIX "") # Needed mostly on Windows to export symbols, and create a .lib file, otherwise the binding # library can't link to the wiggly library. target_compile_definitions(${wiggly_library} PRIVATE BINDINGS_BUILD) target_link_libraries(${wiggly_library} PRIVATE Qt6::Widgets) # ====================== Shiboken target for generating binding C++ files ==================== # Define Qt modules needed set(qt_modules Core Gui Widgets) # Create Python bindings using Shiboken6Tools function shiboken_generator_create_binding( EXTENSION_TARGET ${bindings_library} GENERATED_SOURCES ${generated_sources} HEADERS ${wrapped_header} TYPESYSTEM_FILE ${typesystem_file} LIBRARY_TARGET ${wiggly_library} QT_MODULES Core Gui Widgets ) # ================================= Dubious deployment section ================================ set(windows_shiboken_shared_libraries) if(WIN32) # ========================================================================================= # !!! (The section below is deployment related, so in a real world application you will # want to take care of this properly (this is simply to eliminate errors that users usually # encounter. # ========================================================================================= # Circumvent some "#pragma comment(lib)"s in "include/pyconfig.h" which might force to link # against a wrong python shared library. set(python_versions_list 3 36 37 38 39) set(python_additional_link_flags "") foreach(ver ${python_versions_list}) set(python_additional_link_flags "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}_d.lib\"") set(python_additional_link_flags "${python_additional_link_flags} /NODEFAULTLIB:\"python${ver}.lib\"") endforeach() set_target_properties(${bindings_library} PROPERTIES LINK_FLAGS "${python_additional_link_flags}") # Get the correct DLL path for the current build type if(CMAKE_BUILD_TYPE STREQUAL "Debug") get_target_property(dll_path Shiboken6::libshiboken IMPORTED_LOCATION_DEBUG) else() get_target_property(dll_path Shiboken6::libshiboken IMPORTED_LOCATION_RELEASE) endif() file(TO_CMAKE_PATH "${dll_path}" dll_path) set(windows_shiboken_shared_libraries "${dll_path}") # ========================================================================================= endif() # ============================================================================================= # !!! (The section below is deployment related, so in a real world application you will want to # take care of this properly with some custom script or tool). # ============================================================================================= # Install the library and the bindings module into the source folder near the main.py file, so # that the Python interpeter successfully imports the used module. install(TARGETS ${bindings_library} ${wiggly_library} LIBRARY DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} RUNTIME DESTINATION ${CMAKE_CURRENT_SOURCE_DIR} ) install(FILES ${windows_shiboken_shared_libraries} DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}) # ============================================================================================= # !!! End of dubious section. # =============================================================================================