PyQt5 cmake improvements

This commit is contained in:
Sandro Mani 2021-09-28 21:01:47 +02:00
parent e6d3480ffc
commit c5bb41dc01
6 changed files with 102 additions and 89 deletions

View File

@ -929,12 +929,12 @@ if (WITH_CORE AND WITH_BINDINGS AND NOT WITH_QT6)
set (QGIS_PYTHON_OUTPUT_DIRECTORY ${PYTHON_OUTPUT_DIRECTORY}/qgis)
# python support: check for interpreter, sip, pyqt5
find_package(SIP REQUIRED)
find_package(PyQt5 REQUIRED)
set(PYQT_SIP_FLAGS ${PYQT5_SIP_FLAGS})
set(PYQT_SIP_DIR ${PYQT5_SIP_DIR})
separate_arguments(PYQT_SIP_FLAGS) # convert space separated values to a list
find_package(SIP REQUIRED)
find_package(Qsci REQUIRED)
include(PythonMacros)
include(PyQtMacros)

View File

@ -11,40 +11,58 @@
#
# This file defines the following variables:
#
# PYQT5_VERSION - The version of PyQt5 found expressed as a 6 digit hex number
# suitable for comparison as a string
#
# PYQT5_VERSION_STR - The version of PyQt5 as a human readable string.
#
# PYQT5_VERSION_TAG - The PyQt version tag using by PyQt's sip files.
#
# PYQT5_SIP_DIR - The directory holding the PyQt5 .sip files.
#
# PYQT5_SIP_FLAGS - The SIP flags used to build PyQt.
IF(EXISTS PYQT5_VERSION)
IF(EXISTS PYQT5_VERSION_STR)
# Already in cache, be silent
SET(PYQT5_FOUND TRUE)
ELSE(EXISTS PYQT5_VERSION)
ELSE(EXISTS PYQT5_VERSION_STR)
FIND_FILE(_find_pyqt5_py FindPyQt5.py PATHS ${CMAKE_MODULE_PATH} NO_CMAKE_FIND_ROOT_PATH)
IF(SIP_BUILD_EXECUTABLE)
# SIP >= 5.0 path
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} ${_find_pyqt5_py} OUTPUT_VARIABLE pyqt_config)
IF(pyqt_config)
STRING(REGEX REPLACE "^pyqt_version:([^\n]+).*$" "\\1" PYQT5_VERSION ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_version_str:([^\n]+).*$" "\\1" PYQT5_VERSION_STR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_version_tag:([^\n]+).*$" "\\1" PYQT5_VERSION_TAG ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_version_num:([^\n]+).*$" "\\1" PYQT5_VERSION_NUM ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_mod_dir:([^\n]+).*$" "\\1" PYQT5_MOD_DIR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT5_SIP_DIR ${pyqt_config})
IF(EXISTS ${PYQT5_SIP_DIR}/Qt5)
SET(PYQT5_SIP_DIR ${PYQT5_SIP_DIR}/Qt5)
ENDIF(EXISTS ${PYQT5_SIP_DIR}/Qt5)
STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT5_SIP_FLAGS ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_bin_dir:([^\n]+).*$" "\\1" PYQT5_BIN_DIR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_sip_module:([^\n]+).*$" "\\1" PYQT5_SIP_IMPORT ${pyqt_config})
SET(PYQT5_FOUND TRUE)
ENDIF(pyqt_config)
FILE(GLOB _pyqt5_metadata "${Python_SITEARCH}/PyQt5*.dist-info/METADATA")
IF(_pyqt5_metadata)
FILE(READ ${_pyqt5_metadata} _pyqt5_metadata_contents)
STRING(REGEX REPLACE ".*\nVersion: ([^\n]+).*$" "\\1" PYQT5_VERSION_STR ${_pyqt5_metadata_contents})
ELSE(_pyqt5_metadata)
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} -c "from PyQt5.QtCore import PYQT_VERSION_STR; print(PYQT_VERSION_STR)" OUTPUT_VARIABLE PYQT5_VERSION_STR)
ENDIF(_pyqt5_metadata)
IF(PYQT5_VERSION_STR)
SET(PYQT5_MOD_DIR "${Python_SITEARCH}/PyQt5")
SET(PYQT5_SIP_DIR "${Python_SITEARCH}/PyQt5/bindings")
FIND_PROGRAM(__pyuic5 "pyuic5")
GET_FILENAME_COMPONENT(PYQT5_BIN_DIR ${__pyuic5} DIRECTORY)
SET(PYQT5_FOUND TRUE)
ENDIF(PYQT5_VERSION_STR)
ELSE(SIP_BUILD_EXECUTABLE)
# SIP 4.x path
FIND_FILE(_find_pyqt5_py FindPyQt5.py PATHS ${CMAKE_MODULE_PATH} NO_CMAKE_FIND_ROOT_PATH)
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} ${_find_pyqt5_py} OUTPUT_VARIABLE pyqt_config)
IF(pyqt_config)
STRING(REGEX REPLACE "^pyqt_version_str:([^\n]+).*$" "\\1" PYQT5_VERSION_STR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_mod_dir:([^\n]+).*$" "\\1" PYQT5_MOD_DIR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_sip_dir:([^\n]+).*$" "\\1" PYQT5_SIP_DIR ${pyqt_config})
IF(EXISTS ${PYQT5_SIP_DIR}/Qt5)
SET(PYQT5_SIP_DIR ${PYQT5_SIP_DIR}/Qt5)
ENDIF(EXISTS ${PYQT5_SIP_DIR}/Qt5)
STRING(REGEX REPLACE ".*\npyqt_sip_flags:([^\n]+).*$" "\\1" PYQT5_SIP_FLAGS ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_bin_dir:([^\n]+).*$" "\\1" PYQT5_BIN_DIR ${pyqt_config})
STRING(REGEX REPLACE ".*\npyqt_sip_module:([^\n]+).*$" "\\1" PYQT5_SIP_IMPORT ${pyqt_config})
SET(PYQT5_FOUND TRUE)
ENDIF(pyqt_config)
ENDIF(SIP_BUILD_EXECUTABLE)
IF(PYQT5_FOUND)
IF(NOT PyQt5_FIND_QUIETLY)
@ -56,4 +74,4 @@ ELSE(EXISTS PYQT5_VERSION)
ENDIF(PyQt5_FIND_REQUIRED)
ENDIF(PYQT5_FOUND)
ENDIF(EXISTS PYQT5_VERSION)
ENDIF(EXISTS PYQT5_VERSION_STR)

View File

@ -32,57 +32,24 @@
import os.path
import PyQt5.QtCore
import sipconfig
import sys
try:
__import__('sipbuild')
except ImportError:
import sipconfig # won't work for SIP v5
import sys
cfg = sipconfig.Configuration()
sip_dir = cfg.default_sip_dir
for p in (os.path.join(sip_dir, "PyQt5"),
os.path.join(sip_dir, "PyQt5-3"),
sip_dir,
os.path.join(cfg.default_mod_dir, "PyQt5", "bindings")):
if os.path.exists(os.path.join(p, "QtCore", "QtCoremod.sip")):
sip_dir = p
break
cfg = sipconfig.Configuration()
sip_dir = cfg.default_sip_dir
for p in (os.path.join(sip_dir, "PyQt5"),
os.path.join(sip_dir, "PyQt5-3"),
sip_dir,
os.path.join(cfg.default_mod_dir, "PyQt5", "bindings")):
if os.path.exists(os.path.join(p, "QtCore", "QtCoremod.sip")):
sip_dir = p
break
cfg = {
'pyqt_mod_dir': os.path.join(cfg.default_mod_dir, "PyQt5"),
'pyqt_sip_dir': sip_dir,
'pyqt_bin_dir': cfg.default_bin_dir,
}
else: # Code for SIP v5
from distutils.sysconfig import get_python_lib
import shutil
cfg = {
'pyqt_mod_dir': os.path.dirname(PyQt5.__file__),
'pyqt_sip_dir': os.path.join(get_python_lib(plat_specific=1), "PyQt5", "bindings"),
'pyqt_bin_dir': os.path.dirname(shutil.which("pyuic5")),
}
print("pyqt_version:%06.0x" % PyQt5.QtCore.PYQT_VERSION)
print("pyqt_version_num:%d" % PyQt5.QtCore.PYQT_VERSION)
print("pyqt_version_str:%s" % PyQt5.QtCore.PYQT_VERSION_STR)
pyqt_version_tag = ""
in_t = False
pyqt_config_list = PyQt5.QtCore.PYQT_CONFIGURATION["sip_flags"].split(' ')
for item in pyqt_config_list:
if item == "-t":
in_t = True
elif in_t:
if item.startswith("Qt_5"):
pyqt_version_tag = item
else:
in_t = False
print("pyqt_version_tag:%s" % pyqt_version_tag)
print("pyqt_mod_dir:%s" % cfg['pyqt_mod_dir'])
print("pyqt_sip_dir:%s" % cfg['pyqt_sip_dir'])
print("pyqt_mod_dir:%s" % os.path.join(cfg.default_mod_dir, "PyQt5"))
print("pyqt_sip_dir:%s" % sip_dir)
print("pyqt_sip_flags:%s" % PyQt5.QtCore.PYQT_CONFIGURATION['sip_flags'])
print("pyqt_bin_dir:%s" % cfg['pyqt_bin_dir'])
print("pyqt_bin_dir:%s" % cfg.default_bin_dir)
try:
import PyQt5.sip

View File

@ -21,23 +21,43 @@ IF(QSCI_MOD_VERSION_STR)
SET(QSCI_FOUND TRUE)
ELSE(QSCI_MOD_VERSION_STR)
FIND_FILE(_find_qsci_py FindQsci.py PATHS ${CMAKE_MODULE_PATH} NO_CMAKE_FIND_ROOT_PATH)
IF(SIP_BUILD_EXECUTABLE)
# SIP >= 5.0 path
SET(QSCI_VER 5)
FILE(GLOB _qsci_metadata "${Python_SITEARCH}/QScintilla*.dist-info/METADATA")
IF(_qsci_metadata)
FILE(READ ${_qsci_metadata} _qsci_metadata_contents)
STRING(REGEX REPLACE ".*\nVersion: ([^\n]+).*$" "\\1" QSCI_MOD_VERSION_STR ${_qsci_metadata_contents})
ELSE(_qsci_metadata)
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} -c "from PyQt5.Qsci import QSCINTILLA_VERSION_STR; print(QSCINTILLA_VERSION_STR)" OUTPUT_VARIABLE QSCI_MOD_VERSION_STR)
ENDIF(_qsci_metadata)
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} ${_find_qsci_py} ${QSCI_VER} OUTPUT_VARIABLE qsci_ver)
IF(QSCI_MOD_VERSION_STR)
SET(QSCI_SIP_DIR "${PYQT5_SIP_DIR}")
SET(QSCI_FOUND TRUE)
ENDIF(QSCI_MOD_VERSION_STR)
IF(qsci_ver)
STRING(REGEX REPLACE "^qsci_version_str:([^\n]+).*$" "\\1" QSCI_MOD_VERSION_STR ${qsci_ver})
SET(QSCI_FOUND TRUE)
ENDIF(qsci_ver)
ELSE(SIP_BUILD_EXECUTABLE)
# SIP 4.x path
FIND_FILE(_find_qsci_py FindQsci.py PATHS ${CMAKE_MODULE_PATH} NO_CMAKE_FIND_ROOT_PATH)
SET(QSCI_VER 5)
EXECUTE_PROCESS(COMMAND ${Python_EXECUTABLE} ${_find_qsci_py} ${QSCI_VER} OUTPUT_VARIABLE qsci_ver)
IF(qsci_ver)
STRING(REGEX REPLACE "^qsci_version_str:([^\n]+).*$" "\\1" QSCI_MOD_VERSION_STR ${qsci_ver})
FIND_PATH(QSCI_SIP_DIR
NAMES Qsci/qscimod5.sip
PATHS ${PYQT5_SIP_DIR} ${SIP_DEFAULT_SIP_DIR}
)
SET(QSCI_FOUND TRUE)
ENDIF(qsci_ver)
ENDIF(SIP_BUILD_EXECUTABLE)
IF(QSCI_FOUND)
FIND_PATH(QSCI_SIP_DIR
NAMES Qsci/qscimod5.sip
PATHS ${PYQT5_SIP_DIR} ${SIP_DEFAULT_SIP_DIR}
)
IF(NOT QSCI_FIND_QUIETLY)
MESSAGE(STATUS "Found QScintilla2 PyQt module: ${QSCI_MOD_VERSION_STR}")
ENDIF(NOT QSCI_FIND_QUIETLY)

View File

@ -17,6 +17,8 @@ ENDIF(NOT PYUIC_PROGRAM)
# Adapted from QT4_WRAP_UI
MACRO(PYQT_WRAP_UI outfiles )
SET(PYUIC_WRAPPER_OUTPUT_DIRECTORY "${PYTHON_OUTPUT_DIRECTORY}")
SET(PYUIC_WRAPPER_PYTHON_EXECUTABLE "${Python_EXECUTABLE}")
IF(CMAKE_HOST_WIN32)
IF(USING_NINJA OR USING_NMAKE)
SET(PYUIC_WRAPPER "${CMAKE_SOURCE_DIR}/scripts/pyuic_wrapper.bat")
@ -25,18 +27,22 @@ MACRO(PYQT_WRAP_UI outfiles )
SET(PYUIC_WRAPPER "${CMAKE_SOURCE_DIR}/scripts/pyuic_wrapper.bat")
SET(PYUIC_WRAPPER_PATH "${QGIS_OUTPUT_DIRECTORY}/bin/${CMAKE_BUILD_TYPE}")
ENDIF(USING_NINJA OR USING_NMAKE)
ELSE(CMAKE_HOST_WIN32)
ELSEIF(MINGW)
# Clear all variables to invoke PYUIC_PROGRAM directly
SET(PYUIC_WRAPPER_OUTPUT_DIRECTORY "")
SET(PYUIC_WRAPPER_PYTHON_EXECUTABLE "")
ELSE()
# TODO osx
SET(PYUIC_WRAPPER "${CMAKE_SOURCE_DIR}/scripts/pyuic_wrapper.sh")
SET(PYUIC_WRAPPER_PATH "${QGIS_OUTPUT_DIRECTORY}/lib")
ENDIF(CMAKE_HOST_WIN32)
ENDIF()
FOREACH(it ${ARGN})
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
SET(outfile ${CMAKE_CURRENT_BINARY_DIR}/ui_${outfile}.py)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYUIC_WRAPPER} "${PYUIC_PROGRAM}" "${PYUIC_WRAPPER_PATH}" "${PYTHON_OUTPUT_DIRECTORY}" "${Python_EXECUTABLE}" ${infile} -o ${outfile}
COMMAND ${PYUIC_WRAPPER} "${PYUIC_PROGRAM}" "${PYUIC_WRAPPER_PATH}" "${PYUIC_WRAPPER_OUTPUT_DIRECTORY}" "${PYUIC_WRAPPER_PYTHON_EXECUTABLE}" ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
DEPENDS pygui pycore pyqtcompat
)

View File

@ -167,9 +167,11 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_definitions(-std=c++14)
endif()
if(UNIX AND NOT SIP_VERSION_NUM LESS 265984)
if((UNIX OR MINGW) AND SIP_VERSION_STR VERSION_GREATER_EQUAL 4.10 AND SIP_VERSION_STR VERSION_LESS 5.0)
set(SIP_EXTRA_OPTIONS -P ${SIP_EXTRA_OPTIONS})
add_definitions(-Dprotected=public)
elseif((UNIX OR MINGW) AND SIP_VERSION_STR VERSION_GREATER_EQUAL 5.0)
add_definitions(-Dprotected=public)
endif()
set (PY_MODULES core)