1
0
mirror of https://github.com/python-LimeReport/python-LimeReport.git synced 2025-09-04 17:12:22 +03:00
python-LimeReport/CMakeLists.txt

271 lines
11 KiB
CMake

cmake_minimum_required(VERSION 3.16)
cmake_policy(VERSION 3.16)
# Enable policy to run automoc on generated files.
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
# ================================ General configuration ======================================
project(LimeReport)
set(USE_QT6 ON)
if (NOT DEFINED ENABLE_ZINT)
set(ENABLE_ZINT OFF)
endif()
#
set(LIMEREPORT_STATIC ON)
# Find Python
find_package (Python3 COMPONENTS Interpreter)
if(NOT Python3_Interpreter_FOUND)
message(FATAL_ERROR "Python3 not found")
endif()
message(STATUS "Using python: ${Python3_EXECUTABLE}")
find_package(QT REQUIRED NAMES Qt6)
# Find the required Qt packages
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Widgets Sql Network Xml Svg Qml PrintSupport)
# Set CPP standard to C++11 minimum.
set(CMAKE_CXX_STANDARD 11)
# The C++ project library for which we will create bindings.
set(qtads_subdir "LimeReport")
set(qtads_dir ${CMAKE_CURRENT_SOURCE_DIR}/${qtads_subdir})
add_subdirectory(${qtads_subdir} EXCLUDE_FROM_ALL)
set(project_library limereport-qt${QT_VERSION_MAJOR})
# The name of the generated bindings module (as imported in Python).
set(bindings_library "LimeReport")
# 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_CURRENT_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_CURRENT_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}/limereport_module_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_enums_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_reportengine_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_icallbackdatasource_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_idatasource_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_idatasourceholder_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_idatasourcemanager_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/limereport_idbcredentialsprovider_wrapper.cpp
)
# ================================== Shiboken detection ======================================
# Macro to get various pyside / python include / link flags and paths.
# Uses the not entirely supported utils/pyside_config.py file.
macro(pyside_config option output_var)
if(${ARGC} GREATER 2)
set(is_list ${ARGV2})
else()
set(is_list "")
endif()
execute_process(
COMMAND ${Python3_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/pyside_config.py"
${option}
OUTPUT_VARIABLE ${output_var}
OUTPUT_STRIP_TRAILING_WHITESPACE)
if ("${${output_var}}" STREQUAL "")
message(FATAL_ERROR "Error: Calling ${Python3_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/pyside_config.py ${option} returned no output.")
endif()
if(is_list)
string (REPLACE " " ";" ${output_var} "${${output_var}}")
endif()
endmacro()
# Query for the shiboken generator path, Python path, include paths and linker flags.
pyside_config(--shiboken-module-path shiboken_module_path)
pyside_config(--shiboken-generator-path shiboken_generator_path)
pyside_config(--pyside-path pyside_path)
pyside_config(--pyside-include-path pyside_include_dir 1)
pyside_config(--python-include-path python_include_dir)
pyside_config(--shiboken-generator-include-path shiboken_include_dir 1)
pyside_config(--shiboken-module-shared-libraries-cmake shiboken_shared_libraries 0)
pyside_config(--python-link-flags-cmake python_linking_data 0)
pyside_config(--pyside-shared-libraries-cmake pyside_shared_libraries 0)
set(shiboken_path "${shiboken_generator_path}/shiboken6${CMAKE_EXECUTABLE_SUFFIX}")
if(NOT EXISTS ${shiboken_path})
message(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}")
endif()
# ==================================== RPATH configuration ====================================
if(UNIX AND NOT APPLE)
set(CMAKE_BUILD_RPATH "$ORIGIN/lib:$ORIGIN/../PySide6/:$ORIGIN/../PySide6/Qt/lib:$ORIGIN/../shiboken6")
endif()
if(APPLE)
set(CMAKE_BUILD_RPATH "@loader_path/lib;@loader_path/../PySide6/;@loader_path/../PySide6/Qt/lib;@loader_path/../shiboken6")
set(MACOSX_RPATH TRUE)
endif()
# ============================== Qt Includes for project_library ==============================
# Get the relevant Qt include dirs, to pass them on to shiboken.
set(QT_INCLUDE_DIR "")
get_target_property(QT_INCLUDE_DIR_LIST Qt6::Core INTERFACE_INCLUDE_DIRECTORIES)
foreach(_Q ${QT_INCLUDE_DIR_LIST})
if(NOT "${_Q}" MATCHES "QtCore$")
set(QT_INCLUDE_DIR "${_Q}")
endif()
endforeach()
if(QT_INCLUDE_DIR STREQUAL "")
message(FATAL_ERROR "Unable to obtain the Qt include directory")
endif()
set(QT_INCLUDES "")
list(APPEND QT_INCLUDES "-I${QT_INCLUDE_DIR}")
get_property(QT_CORE_INCLUDE_DIRS TARGET Qt6::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_CORE_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_WIDGETS_INCLUDE_DIRS TARGET Qt6::Widgets PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_WIDGETS_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_SQL_INCLUDE_DIRS TARGET Qt6::Sql PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_SQL_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_NETWORK_INCLUDE_DIRS TARGET Qt6::Network PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_NETWORK_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_XML_INCLUDE_DIRS TARGET Qt6::Xml PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_XML_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_SVG_INCLUDE_DIRS TARGET Qt6::Svg PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_SVG_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_QML_INCLUDE_DIRS TARGET Qt6::Qml PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_QML_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(QT_PRINTSUPPORT_INCLUDE_DIRS TARGET Qt6::PrintSupport PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${QT_PRINTSUPPORT_INCLUDE_DIRS})
list(APPEND QT_INCLUDES "-I${INCLUDE_DIR}")
endforeach()
# Check if Qt is a framework build on macOS. This affects how include paths should be handled.
get_target_property(QtCore_is_framework Qt6::Core FRAMEWORK)
if (QtCore_is_framework)
# Get the path to the Qt framework dir.
set(QT_FRAMEWORK_INCLUDE_DIR "${QT6_INSTALL_PREFIX}/${QT6_INSTALL_LIBS}")
message(STATUS "*** QT_FRAMEWORK_INCLUDE_DIR is ${QT_FRAMEWORK_INCLUDE_DIR}")
list(APPEND QT_INCLUDES "--framework-include-paths=${QT_FRAMEWORK_INCLUDE_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")
list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtQml")
list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtNetwork")
list(APPEND pyside_additional_includes "${INCLUDE_DIR}/QtPrintSupport")
endforeach()
# ====================== Shiboken target for generating binding C++ files ====================
set(implicit_includes)
foreach(_current ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES})
set(implicit_includes ${implicit_includes} "-I${_current}")
endforeach()
# Set up the options to pass to shiboken.
set(shiboken_options --generator-set=shiboken --enable-parent-ctor-heuristic
--enable-pyside-extensions --enable-return-value-heuristic --use-isnull-as-nb_nonzero
--avoid-protected-hack
${QT_INCLUDES}
${implicit_includes}
-I${qtads_dir}/include
-T${CMAKE_CURRENT_SOURCE_DIR}
-T${pyside_path}/typesystems
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
)
set(generated_sources_dependencies ${wrapped_header} ${typesystem_file})
# Add custom target to run shiboken to generate the binding cpp files.
add_custom_command(OUTPUT ${generated_sources}
COMMAND ${shiboken_path}
${shiboken_options} ${wrapped_header} ${typesystem_file}
DEPENDS ${generated_sources_dependencies}
IMPLICIT_DEPENDS CXX ${wrapped_header}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Running generator for ${typesystem_file}.")
# =============================== CMake target - bindings_library =============================
# Set the cpp files which will be used for the bindings library.
set(${bindings_library}_sources ${generated_sources})
# Define and build the bindings library.
add_library(${bindings_library} MODULE ${${bindings_library}_sources})
# Apply relevant include and link flags.
target_include_directories(${bindings_library} PRIVATE ${pyside_additional_includes})
target_include_directories(${bindings_library} PRIVATE ${pyside_include_dir})
target_include_directories(${bindings_library} PRIVATE ${python_include_dir})
target_include_directories(${bindings_library} PRIVATE ${shiboken_include_dir})
target_include_directories(${bindings_library} PRIVATE "${CMAKE_SOURCE_DIR}/src")
target_link_libraries(${bindings_library} PRIVATE Qt6::Widgets)
target_link_libraries(${bindings_library} PRIVATE ${project_library})
target_link_libraries(${bindings_library} PRIVATE ${pyside_shared_libraries})
target_link_libraries(${bindings_library} PRIVATE ${shiboken_shared_libraries})
target_compile_options(limereport-qt${QT_VERSION_MAJOR} PRIVATE -Og)
target_compile_options(${bindings_library} PRIVATE -Og)
target_compile_definitions(${bindings_library} PRIVATE "-DPy_LIMITED_API=0x03070000")
# Adjust the name of generated module.
set_property(TARGET ${bindings_library} PROPERTY PREFIX "")
set_property(TARGET ${bindings_library} PROPERTY OUTPUT_NAME
"${bindings_library}${PYTHON_EXTENSION_SUFFIX}")
if(WIN32)
set_property(TARGET ${bindings_library} PROPERTY SUFFIX ".pyd")
endif()
# Make sure the linker doesn't complain about not finding Python symbols on macOS.
if(APPLE)
set_target_properties(${bindings_library} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
endif(APPLE)
if (WIN32)
list(GET python_linking_data 0 python_libdir)
target_link_directories(${bindings_library} PRIVATE ${python_libdir})
endif()