cMake: Add support for compiling against Qt6 (#7647)

Removes the BUILD_QT5 flag and adds a new FREECAD_QT_VERSION option,
which can be set to either "Auto" (default), 5, or 6. Auto detects which
version of Qt is installed on the system and chooses it. If both version
are installed, Qt5 is used.

Note that this DOES NOT implement compiling against Qt6, it only adds
the necessary cMake infrastructure to begin work on the source code
changes that will be required.
This commit is contained in:
Chris Hennes
2022-10-31 09:24:09 -05:00
committed by GitHub
parent 7c6684a821
commit 2f7be9e782
37 changed files with 595 additions and 662 deletions

View File

@@ -1,18 +1,12 @@
# Try to find PySide2 utilities, PYSIDE2UIC and PYSIDE2RCC:
# PYSIDE2UICBINARY - Location of PYSIDE2UIC executable
# PYSIDE2RCCBINARY - Location of PYSIDE2RCC executable
# PYSIDE2_TOOLS_FOUND - PySide2 utilities found.
# PYSIDE_UIC_EXECUTABLE - Location of PYSIDE2UIC executable
# PYSIDE_RCC_EXECUTABLE - Location of PYSIDE2RCC executable
# PYSIDE_TOOLS_FOUND - PySide2 utilities found.
# Also provides macro similar to FindQt4.cmake's WRAP_UI and WRAP_RC,
# for the automatic generation of Python code from Qt4's user interface
# ('.ui') and resource ('.qrc') files. These macros are called:
# - PYSIDE_WRAP_UI
# - PYSIDE_WRAP_RC
IF(PYSIDE2UICBINARY AND PYSIDE2RCCBINARY)
IF(PYSIDE2_UIC_EXECUTABLE AND PYSIDE2_RCC_EXECUTABLE)
# Already in cache, be silent
set(PYSIDE2_TOOLS_FOUND_QUIETLY TRUE)
ENDIF(PYSIDE2UICBINARY AND PYSIDE2RCCBINARY)
ENDIF()
if(WIN32 OR ${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
#pyside2 tools are often in same location as python interpreter
@@ -27,88 +21,31 @@ FIND_PACKAGE(Qt5 COMPONENTS Core Widgets)
IF(Qt5Core_VERSION VERSION_LESS 5.14)
# Legacy (< 5.14)
FIND_PROGRAM(PYSIDE2UICBINARY NAMES python2-pyside2-uic pyside2-uic pyside2-uic-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} pyuic5 HINTS ${PYSIDE_BIN_DIR})
FIND_PROGRAM(PYSIDE2RCCBINARY NAMES pyside2-rcc pyside2-rcc-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} pyrcc5 HINTS ${PYSIDE_BIN_DIR})
FIND_PROGRAM(PYSIDE2_UIC_EXECUTABLE NAMES python2-pyside2-uic pyside2-uic pyside2-uic-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} pyuic5 HINTS ${PYSIDE_BIN_DIR})
FIND_PROGRAM(PYSIDE2_RCC_EXECUTABLE NAMES pyside2-rcc pyside2-rcc-${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR} pyrcc5 HINTS ${PYSIDE_BIN_DIR})
set(UICOPTIONS "")
set(RCCOPTIONS "")
ELSE()
# New (>= 5.14)
if (TARGET Qt::uic)
get_property(PYSIDE2UICBINARY TARGET Qt::uic PROPERTY LOCATION)
get_property(PYSIDE2_UIC_EXECUTABLE TARGET Qt::uic PROPERTY LOCATION)
set(UICOPTIONS "--generator=python")
endif()
if (TARGET Qt::rcc)
get_property(PYSIDE2RCCBINARY TARGET Qt::rcc PROPERTY LOCATION)
get_property(PYSIDE2_RCC_EXECUTABLE TARGET Qt::rcc PROPERTY LOCATION)
set(RCCOPTIONS "--generator=python" "--compress-algo=zlib" "--compress=1")
endif()
ENDIF(Qt5Core_VERSION VERSION_LESS 5.14)
ENDIF()
MACRO(PYSIDE_WRAP_UI outfiles)
if (NOT PYSIDE2UICBINARY)
message(FATAL_ERROR "Qt uic is required for generating ${ARGN}")
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_TARGET(${it} ALL
# DEPENDS ${outfile}
#)
if(WIN32 OR APPLE)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYSIDE2UICBINARY} ${UICOPTIONS} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
else()
# Especially on Open Build Service we don't want changing date like
# pyside2-uic generates in comments at beginning., which is why
# we follow the tool command with a POSIX-friendly sed.
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND "${PYSIDE2UICBINARY}" ${UICOPTIONS} "${infile}" -o "${outfile}"
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
MAIN_DEPENDENCY "${infile}"
)
endif()
list(APPEND ${outfiles} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYSIDE_WRAP_UI)
file(TO_NATIVE_PATH ${PYSIDE2_RCC_EXECUTABLE} PYSIDE_RCC_EXECUTABLE)
file(TO_NATIVE_PATH ${PYSIDE2_UIC_EXECUTABLE} PYSIDE_UIC_EXECUTABLE)
MACRO(PYSIDE_WRAP_RC outfiles)
if (NOT PYSIDE2RCCBINARY)
message(FATAL_ERROR "Qt rcc is required for generating ${ARGN}")
endif()
FOREACH(it ${ARGN})
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
SET(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py")
#ADD_CUSTOM_TARGET(${it} ALL
# DEPENDS ${outfile}
#)
if(WIN32 OR APPLE)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYSIDE2RCCBINARY} ${RCCOPTIONS} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
else()
# Especially on Open Build Service we don't want changing date like
# pyside-rcc generates in comments at beginning, which is why
# we follow the tool command with in-place sed.
ADD_CUSTOM_COMMAND(OUTPUT "${outfile}"
COMMAND "${PYSIDE2RCCBINARY}" ${RCCOPTIONS} "${infile}" ${PY_ATTRIBUTE} -o "${outfile}"
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
MAIN_DEPENDENCY "${infile}"
)
endif()
list(APPEND ${outfiles} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYSIDE_WRAP_RC)
if(PYSIDE2RCCBINARY AND PYSIDE2UICBINARY)
set(PYSIDE2_TOOLS_FOUND TRUE)
if(PYSIDE_RCC_EXECUTABLE AND PYSIDE_UIC_EXECUTABLE)
set(PYSIDE_TOOLS_FOUND TRUE)
if (NOT PySide2Tools_FIND_QUIETLY)
message(STATUS "Found PySide2 tools: ${PYSIDE2UICBINARY}, ${PYSIDE2RCCBINARY}")
message(STATUS "Found PySide2 tools: ${PYSIDE_UIC_EXECUTABLE}, ${PYSIDE_RCC_EXECUTABLE}")
endif (NOT PySide2Tools_FIND_QUIETLY)
else(PYSIDE2RCCBINARY AND PYSIDE2UICBINARY)
else()
if(PySide2Tools_FIND_REQUIRED)
message(FATAL_ERROR "PySide2 tools could not be found, but are required.")
else(PySide2Tools_FIND_REQUIRED)
@@ -116,4 +53,4 @@ else(PYSIDE2RCCBINARY AND PYSIDE2UICBINARY)
message(STATUS "PySide2 tools: not found.")
endif (NOT PySide2Tools_FIND_QUIETLY)
endif(PySide2Tools_FIND_REQUIRED)
endif(PYSIDE2RCCBINARY AND PYSIDE2UICBINARY)
endif()

View File

@@ -0,0 +1,36 @@
# Try to find PYSIDE6 utilities, PYSIDE6UIC and PYSIDE6RCC:
# PYSIDE_UIC_EXECUTABLE - Location of PYSIDE6UIC executable
# PYSIDE_RCC_EXECUTABLE - Location of PYSIDE6RCC executable
# PYSIDE_TOOLS_FOUND - PYSIDE6 utilities found.
IF(PYSIDE6_UIC_EXECUTABLE AND PYSIDE6_RCC_EXECUTABLE)
# Already in cache, be silent
set(PYSIDE_TOOLS_FOUND_QUIETLY TRUE)
ENDIF()
if (TARGET Qt6::uic)
get_target_property(PYSIDE6_UIC_EXECUTABLE Qt6::uic LOCATION)
set(UICOPTIONS "--generator=python")
endif()
if (TARGET Qt6::rcc)
get_target_property(PYSIDE6_RCC_EXECUTABLE Qt6::rcc LOCATION)
set(RCCOPTIONS "--generator=python" "--compress-algo=zlib" "--compress=1")
endif()
file(TO_NATIVE_PATH ${PYSIDE6_RCC_EXECUTABLE} PYSIDE_RCC_EXECUTABLE)
file(TO_NATIVE_PATH ${PYSIDE6_UIC_EXECUTABLE} PYSIDE_UIC_EXECUTABLE)
if(PYSIDE_RCC_EXECUTABLE AND PYSIDE_UIC_EXECUTABLE)
set(PYSIDE_TOOLS_FOUND TRUE)
if (NOT PYSIDE6Tools_FIND_QUIETLY)
message(STATUS "Found PYSIDE6 tools: ${PYSIDE_UIC_EXECUTABLE}, ${PYSIDE_RCC_EXECUTABLE}")
endif ()
else()
if(PYSIDE6Tools_FIND_REQUIRED)
message(FATAL_ERROR "PYSIDE6 tools could not be found, but are required.")
else()
if (NOT PYSIDE6Tools_FIND_QUIETLY)
message(STATUS "PYSIDE6 tools: not found.")
endif ()
endif()
endif()

View File

@@ -0,0 +1,88 @@
# ADAPTED FOR FREECAD FROM VTK'S vtkQt.cmake
# ORIGINAL VTK COPYRIGHT NOTICE FOLLOWS (BSD 3-CLAUSE)
#
# /*=========================================================================
#
# Program: Visualization Toolkit
# Module: Copyright.txt
#
# Copyright (c) 1993-2015 Ken Martin, Will Schroeder, Bill Lorensen
# 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 name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
# of any contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``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 THE AUTHORS OR CONTRIBUTORS 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.
#
# =========================================================================*/
# FREECAD_QT_VERSION is used to choose between Qt5 and Qt6.
# If it is set to Auto(default), FreeCAD finds and uses the
# version installed on the system. If both versions are
# found, Qt5 is preferred.
# The output variable is FREECAD_QT_MAJOR_VERSION, which will be either 5 or 6
macro(ChooseQtVersion)
set(freecad_supported_qt_versions "Auto" 5 6)
# The following `if` check can be removed once CMake 3.21 is required and
# the policy CMP0126 is set to NEW.
if (NOT DEFINED FREECAD_QT_VERSION)
set(FREECAD_QT_VERSION "Auto" CACHE
STRING "Expected Qt major version. Valid values are Auto, 5, 6.")
set_property(CACHE FREECAD_QT_VERSION PROPERTY STRINGS "${freecad_supported_qt_versions}")
endif()
if(FREECAD_LIBPACK_USE)
if (NOT Qt5_DIR OR Qt5_DIR STREQUAL "Qt5_DIR-NOTFOUND")
message(STATUS "Using Qt5 directory from LibPack in ${FREECAD_LIBPACK_DIR}/lib/cmake/Qt5")
set(Qt5_DIR ${FREECAD_LIBPACK_DIR}/lib/cmake/Qt5)
endif()
endif()
if (NOT FREECAD_QT_VERSION STREQUAL "Auto")
if (NOT FREECAD_QT_VERSION IN_LIST freecad_supported_qt_versions)
message(FATAL_ERROR
"Supported Qt versions are \"${freecad_supported_qt_versions}\". But "
"FREECAD_QT_VERSION is set to ${FREECAD_QT_VERSION}.")
endif ()
set(_FREECAD_QT_VERSION "${FREECAD_QT_VERSION}")
else ()
find_package(Qt5 QUIET COMPONENTS Core)
set(_FREECAD_QT_VERSION 5)
if (NOT Qt5_FOUND)
find_package(Qt6 QUIET COMPONENTS Core)
if (NOT Qt6_FOUND)
message(FATAL_ERROR
"Could not find a valid Qt installation. Consider setting Qt5_DIR or Qt6_DIR (as needed).")
endif ()
set(_FREECAD_QT_VERSION 6)
endif ()
endif ()
set(FREECAD_QT_MAJOR_VERSION "${_FREECAD_QT_VERSION}" CACHE INTERNAL
"Major version number for the Qt installation used.")
message(STATUS "Compiling with Qt ${FREECAD_QT_MAJOR_VERSION}")
endmacro()

View File

@@ -18,24 +18,24 @@ macro(FreeCADLibpackChecks)
endif(FREECAD_LIBPACK_CHECKFILE_CLBUNDLER)
# -------------------------------- PyCXX --------------------------------
find_package(PyCXX REQUIRED)
find_package(PyCXX REQUIRED)
# -------------------------------- Swig ----------------------------------
find_package(SWIG)
find_package(SWIG)
if(NOT SWIG_FOUND)
message("==================================================\n"
"SWIG not found, don't build SWIG binding for pivy.\n"
"==================================================\n")
endif(NOT SWIG_FOUND)
if(NOT SWIG_FOUND)
message("==================================================\n"
"SWIG not found, don't build SWIG binding for pivy.\n"
"==================================================\n")
endif(NOT SWIG_FOUND)
# -------------------------------- Salome SMESH --------------------------
if(NOT FREECAD_USE_EXTERNAL_SMESH)
set(SMESH_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/3rdParty/salomesmesh/inc)
endif()
if(NOT FREECAD_USE_EXTERNAL_SMESH)
set(SMESH_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/src/3rdParty/salomesmesh/inc)
endif()
endif(FREECAD_LIBPACK_USE)
endif(FREECAD_LIBPACK_USE)
endmacro(FreeCADLibpackChecks)

View File

@@ -61,7 +61,8 @@ macro(InitializeFreeCADBuildOptions)
option(FREECAD_LIBPACK_USE "Use the LibPack to Build FreeCAD (only Win32 so far)." OFF)
set(FREECAD_LIBPACK_DIR "" CACHE PATH "Directory of the FreeCAD LibPack")
endif(MSVC)
option(BUILD_QT5 "Build with Qt5." ON)
ChooseQtVersion()
# https://blog.kitware.com/constraining-values-with-comboboxes-in-cmake-cmake-gui/
set(FREECAD_USE_OCC_VARIANT "Community Edition" CACHE STRING "Official OpenCASCADE version or community edition")
@@ -70,14 +71,6 @@ macro(InitializeFreeCADBuildOptions)
"Community Edition"
)
if (BUILD_QT5)
set(FREECAD_USE_QTWEBMODULE "Automatic" CACHE STRING "Qt Webkit or Qt WebEngine")
set_property(CACHE FREECAD_USE_QTWEBMODULE PROPERTY STRINGS
"Automatic"
"Qt Webkit"
"Qt WebEngine"
)
endif()
configure_file(${CMAKE_SOURCE_DIR}/src/QtOpenGL.h.cmake ${CMAKE_BINARY_DIR}/src/QtOpenGL.h)
option(BUILD_DESIGNER_PLUGIN "Build and install the designer plugin" OFF)

View File

@@ -70,46 +70,36 @@ macro(PrintFinalReport)
message(STATUS "Eigen3: not found")
endif(DEFINED EIGEN3_FOUND)
message(STATUS "Qt5Core: ${Qt5Core_VERSION}")
message(STATUS "Qt5Network: ${Qt5Network_VERSION}")
message(STATUS "Qt5Xml: ${Qt5Xml_VERSION}")
message(STATUS "Qt5XmlPatterns: ${Qt5XmlPatterns_VERSION}")
message(STATUS "QtCore: ${QtCore_VERSION}")
message(STATUS "QtNetwork: ${QtNetwork_VERSION}")
message(STATUS "QtXml: ${QtXml_VERSION}")
if (BUILD_GUI)
message(STATUS "Qt5Widgets: ${Qt5Widgets_VERSION}")
message(STATUS "Qt5PrintSupport: ${Qt5PrintSupport_VERSION}")
message(STATUS "Qt5OpenGL: ${Qt5OpenGL_VERSION}")
message(STATUS "Qt5Svg: ${Qt5Svg_VERSION}")
message(STATUS "Qt5UiTools: ${Qt5UiTools_VERSION}")
message(STATUS "Qt5Concurrent: ${Qt5Concurrent_VERSION}")
message(STATUS "QtWidgets: ${QtWidgets_VERSION}")
message(STATUS "QtPrintSupport: ${QtPrintSupport_VERSION}")
message(STATUS "QtOpenGL: ${QtOpenGL_VERSION}")
message(STATUS "QtSvg: ${QtSvg_VERSION}")
message(STATUS "QtUiTools: ${QtUiTools_VERSION}")
message(STATUS "QtConcurrent: ${QtConcurrent_VERSION}")
if(BUILD_WEB)
if (Qt5WebKitWidgets_FOUND)
message(STATUS "Qt5WebKitWidgets: ${Qt5WebKitWidgets_VERSION}")
endif()
if (Qt5WebEngineWidgets_FOUND)
message(STATUS "Qt5WebEngineWidgets: ${Qt5WebEngineWidgets_VERSION}")
endif()
else(BUILD_WEB)
message(STATUS "Qt5WebKitWidgets: not needed (BUILD_WEB)")
message(STATUS "Qt5WebEngineWidgets: not needed (BUILD_WEB)")
endif(BUILD_WEB)
message(STATUS "QtWebEngineWidgets: ${QtWebEngineWidgets_VERSION}")
else()
message(STATUS "QtWebEngineWidgets: not needed (BUILD_WEB is OFF)")
endif()
if(BUILD_DESIGNER_PLUGIN)
message(STATUS "Designer plugin: ${DESIGNER_PLUGIN_LOCATION}/${libFreeCAD_widgets}")
else(BUILD_DESIGNER_PLUGIN)
message(STATUS "Designer plugin: not built per user request (BUILD_DESIGNER_PLUGIN)")
endif(BUILD_DESIGNER_PLUGIN)
if(${Qt5WinExtras_FOUND})
message(STATUS "Qt5WinExtras: ${Qt5WinExtras_VERSION}")
else()
message(STATUS "Designer plugin: not built (BUILD_DESIGNER_PLUGIN is OFF)")
endif()
else(BUILD_GUI)
message(STATUS "Qt5Widgets: not needed")
message(STATUS "Qt5PrintSupport: not needed")
message(STATUS "Qt5OpenGL: not needed")
message(STATUS "Qt5Svg: not needed")
message(STATUS "Qt5UiTools: not needed")
message(STATUS "Qt5Concurrent: not needed")
message(STATUS "Qt5WebKitWidgets: not needed")
endif(BUILD_GUI)
else()
message(STATUS "QtWidgets: not needed")
message(STATUS "QtPrintSupport: not needed")
message(STATUS "QtOpenGL: not needed")
message(STATUS "QtSvg: not needed")
message(STATUS "QtUiTools: not needed")
message(STATUS "QtConcurrent: not needed")
message(STATUS "QtWebKitWidgets: not needed")
endif()
if(DEFINED MACPORTS_PREFIX)
if(DEFINED Shiboken_FOUND)
@@ -127,24 +117,24 @@ macro(PrintFinalReport)
endif(DEFINED PySide_FOUND)
endif(DEFINED MACPORTS_PREFIX)
if(DEFINED Shiboken2_FOUND)
message(STATUS "Shiboken2: ${Shiboken2_VERSION} [${Shiboken2_DIR}] [${SHIBOKEN_INCLUDE_DIR}]")
else(DEFINED Shiboken2_FOUND)
message(STATUS "Shiboken2: not found")
endif(DEFINED Shiboken2_FOUND)
if(DEFINED PySide2_FOUND)
message(STATUS "PySide2: ${PySide2_VERSION} [${PYSIDE_INCLUDE_DIR}]")
if(DEFINED Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
message(STATUS "Shiboken: ${Shiboken_VERSION} [${Shiboken${SHIBOKEN_MAJOR_VERSION}_DIR}] [${SHIBOKEN_INCLUDE_DIR}]")
else()
message(STATUS "Shiboken: not found")
endif()
if(DEFINED PySide${SHIBOKEN_MAJOR_VERSION}_FOUND)
message(STATUS "PySide: ${PySide_VERSION} [${PYSIDE_INCLUDE_DIR}]")
if(NOT PYSIDE_INCLUDE_DIR)
message(STATUS " IncludeDir: Unable to find, python version mismatch?")
endif(NOT PYSIDE_INCLUDE_DIR)
else(DEFINED PySide2_FOUND)
message(STATUS "PySide2: not found")
endif(DEFINED PySide2_FOUND)
if(DEFINED PYSIDE2_TOOLS_FOUND)
message(STATUS "PySide2Tools: [${PYSIDE2UICBINARY}] [${PYSIDE2RCCBINARY}]")
else(DEFINED PYSIDE2_TOOLS_FOUND)
message(STATUS "PySide2Tools: not found")
endif(DEFINED PYSIDE2_TOOLS_FOUND)
endif()
else()
message(STATUS "PySide: not found")
endif()
if(DEFINED PYSIDE_TOOLS_FOUND)
message(STATUS "PySideTools: [${PYSIDE_UIC_EXECUTABLE}] [${PYSIDE_RCC_EXECUTABLE}]")
else()
message(STATUS "PySideTools: not found")
endif()
if(FREECAD_USE_FREETYPE)
if(DEFINED FREETYPE_FOUND)

View File

@@ -1,38 +1,55 @@
# -------------------------------- Qt --------------------------------
find_package(Qt5Core REQUIRED)
set(CMAKE_AUTOMOC TRUE)
# For FreeCAD 0.20, pegged to Ubuntu 18.04 LTS:
if(${Qt5Core_VERSION} VERSION_LESS "5.9")
message (FATAL_ERROR "FreeCAD v0.20 requires Qt5 5.9 or later")
set(FREECAD_QT_COMPONENTS Core Concurrent Network Xml)
if (FREECAD_QT_MAJOR_VERSION EQUAL 5)
list (APPEND FREECAD_QT_COMPONENTS XmlPatterns)
endif()
find_package(Qt5Network REQUIRED)
find_package(Qt5Xml REQUIRED)
find_package(Qt5XmlPatterns REQUIRED)
find_package(Qt5Concurrent REQUIRED)
if(BUILD_GUI)
find_package(Qt5Widgets REQUIRED)
find_package(Qt5PrintSupport REQUIRED)
find_package(Qt5OpenGL REQUIRED)
find_package(Qt5Svg REQUIRED)
find_package(Qt5UiTools REQUIRED)
if (FREECAD_QT_MAJOR_VERSION EQUAL 6)
list (APPEND FREECAD_QT_COMPONENTS GuiTools)
endif()
list (APPEND FREECAD_QT_COMPONENTS OpenGL PrintSupport Svg UiTools Widgets)
if (BUILD_WEB)
if (${FREECAD_USE_QTWEBMODULE} MATCHES "Qt Webkit")
find_package(Qt5WebKitWidgets REQUIRED)
elseif(${FREECAD_USE_QTWEBMODULE} MATCHES "Qt WebEngine")
find_package(Qt5WebEngineWidgets REQUIRED)
else() # Automatic
find_package(Qt5WebEngineWidgets QUIET)
if(NOT Qt5WebEngineWidgets_FOUND)
find_package(Qt5WebKitWidgets REQUIRED)
list (APPEND FREECAD_QT_COMPONENTS WebEngineWidgets)
endif()
if(BUILD_DESIGNER_PLUGIN)
list (APPEND FREECAD_QT_COMPONENTS Designer)
endif()
endif()
foreach(COMPONENT IN LISTS FREECAD_QT_COMPONENTS)
find_package(Qt${FREECAD_QT_MAJOR_VERSION} REQUIRED COMPONENTS ${COMPONENT})
set(Qt${COMPONENT}_LIBRARIES ${Qt${FREECAD_QT_MAJOR_VERSION}${COMPONENT}_LIBRARIES})
set(Qt${COMPONENT}_INCLUDE_DIRS ${Qt${FREECAD_QT_MAJOR_VERSION}${COMPONENT}_INCLUDE_DIRS})
set(Qt${COMPONENT}_FOUND ${Qt${FREECAD_QT_MAJOR_VERSION}${COMPONENT}_FOUND})
set(Qt${COMPONENT}_VERSION ${Qt${FREECAD_QT_MAJOR_VERSION}${COMPONENT}_VERSION})
endforeach()
set(CMAKE_AUTOMOC TRUE)
set(CMAKE_AUTOUIC TRUE)
set(QtCore_MOC_EXECUTABLE ${Qt${FREECAD_QT_MAJOR_VERSION}Core_MOC_EXECUTABLE})
message(STATUS "Set up to compile with Qt ${Qt${FREECAD_QT_MAJOR_VERSION}Core_VERSION}")
# In Qt 5.15 they added more generic names for these functions: "backport" those new names
# so we can migrate to using the non-version-named functions in all instances.
if (Qt${FREECAD_QT_MAJOR_VERSION}Core_VERSION VERSION_LESS 5.15.0)
message(STATUS "Manually creating qt_wrap_cpp() and qt_add_resources() to support Qt ${Qt${FREECAD_QT_MAJOR_VERSION}Core_VERSION}")
# Wrapper code adapted from Qt 6's Qt6CoreMacros.cmake file:
function(qt_add_resources outfiles)
qt5_add_resources("${outfiles}" ${ARGN})
if(TARGET ${outfiles})
cmake_parse_arguments(PARSE_ARGV 1 arg "" "OUTPUT_TARGETS" "")
if (arg_OUTPUT_TARGETS)
set(${arg_OUTPUT_TARGETS} ${${arg_OUTPUT_TARGETS}} PARENT_SCOPE)
endif()
else()
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
endif()
endif()
if(BUILD_DESIGNER_PLUGIN)
find_package(Qt5Designer REQUIRED)
endif()
if(MSVC)
find_package(Qt5WinExtras QUIET)
endif()
endif(BUILD_GUI)
endfunction()
function(qt_wrap_cpp outfiles)
qt5_wrap_cpp("${outfiles}" ${ARGN})
set("${outfiles}" "${${outfiles}}" PARENT_SCOPE)
endfunction()
endif()

View File

@@ -6,70 +6,90 @@ macro(SetupShibokenAndPyside)
find_package(PySide REQUIRED HINTS "${PYTHON_LIBRARY_DIR}/cmake")
endif(DEFINED MACPORTS_PREFIX)
if(FREECAD_QT_MAJOR_VERSION EQUAL 5)
set(SHIBOKEN_MAJOR_VERSION 2)
set(PYSIDE_MAJOR_VERSION 2)
else()
set(SHIBOKEN_MAJOR_VERSION ${FREECAD_QT_MAJOR_VERSION})
set(PYSIDE_MAJOR_VERSION ${FREECAD_QT_MAJOR_VERSION})
endif()
# Shiboken2Config.cmake may explicitly set CMAKE_BUILD_TYPE to Release which causes
# CMake to fail to create Makefiles for a debug build.
# So as a workaround we save and restore the value after checking for Shiboken2.
set (SAVE_BUILD_TYPE ${CMAKE_BUILD_TYPE})
find_package(Shiboken2 QUIET)# REQUIRED
find_package(Shiboken${SHIBOKEN_MAJOR_VERSION} QUIET)
set (CMAKE_BUILD_TYPE ${SAVE_BUILD_TYPE})
if (Shiboken2_FOUND)
# Shiboken2 config file was found but it may use the wrong Python version
if (Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
# Shiboken config file was found but it may use the wrong Python version
# Try to get the matching config suffix and repeat finding the package
set(SHIBOKEN_PATTERN .cpython-${Python3_VERSION_MAJOR}${Python3_VERSION_MINOR})
file(GLOB SHIBOKEN_CONFIG "${Shiboken2_DIR}/Shiboken2Config${SHIBOKEN_PATTERN}*.cmake")
file(GLOB SHIBOKEN_CONFIG "${Shiboken${SHIBOKEN_MAJOR_VERSION}_DIR}/Shiboken${SHIBOKEN_MAJOR_VERSION}Config${SHIBOKEN_PATTERN}*.cmake")
if (SHIBOKEN_CONFIG)
get_filename_component(SHIBOKEN_CONFIG_SUFFIX ${SHIBOKEN_CONFIG} NAME)
string(SUBSTRING ${SHIBOKEN_CONFIG_SUFFIX} 15 -1 SHIBOKEN_CONFIG_SUFFIX)
string(REPLACE ".cmake" "" PYTHON_CONFIG_SUFFIX ${SHIBOKEN_CONFIG_SUFFIX})
message(STATUS "PYTHON_CONFIG_SUFFIX: ${PYTHON_CONFIG_SUFFIX}")
find_package(Shiboken2 QUIET)
get_filename_component(SHIBOKEN_CONFIG_SUFFIX ${SHIBOKEN_CONFIG} NAME)
string(SUBSTRING ${SHIBOKEN_CONFIG_SUFFIX} 15 -1 SHIBOKEN_CONFIG_SUFFIX)
string(REPLACE ".cmake" "" PYTHON_CONFIG_SUFFIX ${SHIBOKEN_CONFIG_SUFFIX})
message(STATUS "PYTHON_CONFIG_SUFFIX: ${PYTHON_CONFIG_SUFFIX}")
find_package(Shiboken${SHIBOKEN_MAJOR_VERSION} QUIET)
endif()
endif()
# pyside2 changed its cmake files, this is the dance we have
# to dance to be compatible with the old (<5.12) and the new versions (>=5.12)
if(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
get_property(SHIBOKEN_INCLUDE_DIR TARGET Shiboken2::libshiboken PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken2::libshiboken)
if(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken)
get_property(SHIBOKEN_INCLUDE_DIR TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT SHIBOKEN_INCLUDE_DIR AND TARGET Shiboken${SHIBOKEN_MAJOR_VERSION}::libshiboken)
if(NOT SHIBOKEN_INCLUDE_DIR)
message("====================\n"
"shiboken2 not found.\n"
"====================\n")
endif(NOT SHIBOKEN_INCLUDE_DIR)
find_pip_package(Shiboken${SHIBOKEN_MAJOR_VERSION})
if (Shiboken${SHIBOKEN_MAJOR_VERSION}_FOUND)
set(Shiboken_INCLUDE_DIR ${Shiboken${SHIBOKEN_MAJOR_VERSION}_INCLUDE_DIRS})
set(Shiboken_LIBRARY ${Shiboken${SHIBOKEN_MAJOR_VERSION}_LIBRARIES})
set(Shiboken_FOUND TRUE)
endif()
endif()
find_package(PySide2 QUIET)# REQUIRED
find_package(PySide${PYSIDE_MAJOR_VERSION} QUIET)
if(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
get_property(PYSIDE_INCLUDE_DIR TARGET PySide2::pyside2 PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide2::pyside2)
if(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION})
get_property(PYSIDE_INCLUDE_DIR TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION} PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
endif(NOT PYSIDE_INCLUDE_DIR AND TARGET PySide${PYSIDE_MAJOR_VERSION}::pyside${PYSIDE_MAJOR_VERSION})
if(NOT PYSIDE_INCLUDE_DIR)
message("==================\n"
"PySide2 not found.\n"
"==================\n")
endif(NOT PYSIDE_INCLUDE_DIR)
find_pip_package(PySide${PYSIDE_MAJOR_VERSION})
if (PySide${PYSIDE_MAJOR_VERSION}_FOUND)
set(PySide_INCLUDE_DIR ${PySide${PYSIDE_MAJOR_VERSION}_INCLUDE_DIRS})
set(PySide_LIBRARY ${PySide${PYSIDE_MAJOR_VERSION}_LIBRARIES})
set(PySide_FOUND TRUE)
endif()
endif()
find_package(PySide2Tools QUIET) #REQUIRED # PySide2 utilities (pyside2-uic & pyside2-rcc)
if(NOT PYSIDE2_TOOLS_FOUND)
find_package(PySide${PYSIDE_MAJOR_VERSION}Tools QUIET) # PySide utilities (uic & rcc executables)
if(NOT PYSIDE_TOOLS_FOUND)
message("=======================\n"
"PySide2Tools not found.\n"
"PySide${PYSIDE_MAJOR_VERSION}Tools not found.\n"
"=======================\n")
endif(NOT PYSIDE2_TOOLS_FOUND)
endif()
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/Ext/PySide)
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/__init__.py "# PySide wrapper\n"
"from PySide2 import __version__\n"
"from PySide2 import __version_info__\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtCore.py "from PySide2.QtCore import *\n\n"
"from PySide${PYSIDE_MAJOR_VERSION} import __version__\n"
"from PySide${PYSIDE_MAJOR_VERSION} import __version_info__\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtCore.py "from PySide${PYSIDE_MAJOR_VERSION}.QtCore import *\n\n"
"#QCoreApplication.CodecForTr=0\n"
"#QCoreApplication.UnicodeUTF8=1\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtGui.py "from PySide2.QtGui import *\n"
"from PySide2.QtWidgets import *\n"
"QHeaderView.setResizeMode = QHeaderView.setSectionResizeMode\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtSvg.py "from PySide2.QtSvg import *\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtUiTools.py "from PySide2.QtUiTools import *\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtNetwork.py "from PySide${PYSIDE_MAJOR_VERSION}.QtNetwork import *\n")
if(BUILD_GUI)
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtGui.py "from PySide${PYSIDE_MAJOR_VERSION}.QtGui import *\n"
"from PySide${PYSIDE_MAJOR_VERSION}.QtWidgets import *\n"
"QHeaderView.setResizeMode = QHeaderView.setSectionResizeMode\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtSvg.py "from PySide${PYSIDE_MAJOR_VERSION}.QtSvg import *\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtUiTools.py "from PySide${PYSIDE_MAJOR_VERSION}.QtUiTools import *\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtWidgets.py "from PySide${PYSIDE_MAJOR_VERSION}.QtWidgets import *\n")
file(WRITE ${CMAKE_BINARY_DIR}/Ext/PySide/QtWebEngineWidgets.py "from PySide${PYSIDE_MAJOR_VERSION}.QtWebEngineWidgets import *\n")
endif()
if(APPLE AND NOT BUILD_WITH_CONDA)
install(
@@ -91,41 +111,148 @@ macro(SetupShibokenAndPyside)
if(SHIBOKEN_INCLUDE_DIR)
option(FREECAD_USE_SHIBOKEN "Links to the shiboken library at build time. If OFF its Python module is imported at runtime" ON)
else()
message(WARNING "Shiboken${PYSIDE_MAJOR_VERSION} include files not found, FREECAD_USE_SHIBOKEN automatically set to OFF")
option(FREECAD_USE_SHIBOKEN "Links to the shiboken library at build time. If OFF its Python module is imported at runtime" OFF)
endif()
# Now try to import the shiboken Python module and print a warning if it can't be loaded
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken2"
# Now try to import the shiboken Python module and print an error if it can't be loaded
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken${SHIBOKEN_MAJOR_VERSION}"
RESULT_VARIABLE FAILURE
OUTPUT_VARIABLE PRINT_OUTPUT
)
)
if(FAILURE)
message("=================================\n"
"shiboken Python module not found.\n"
"=================================\n")
endif()
if(FAILURE)
message(FATAL_ERROR,
"==================================\n"
"Shiboken${SHIBOKEN_MAJOR_VERSION} Python module not found.\n"
"==================================\n")
else()
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import shiboken${SHIBOKEN_MAJOR_VERSION};print(shiboken${SHIBOKEN_MAJOR_VERSION}.__version__, end='')"
RESULT_VARIABLE FAILURE
OUTPUT_VARIABLE Shiboken_VERSION
)
endif()
# If PySide cannot be found the build option will be set to OFF
if(PYSIDE_INCLUDE_DIR)
option(FREECAD_USE_PYSIDE "Links to the PySide libraries at build time." ON)
else()
message(WARNING "PySide${PYSIDE_MAJOR_VERSION} include files not found, FREECAD_USE_PYSIDE automatically set to OFF")
option(FREECAD_USE_PYSIDE "Links to the PySide libraries at build time." OFF)
endif()
# Independent of the build option PySide modules must be loaded at runtime. Print a warning if it fails.
# Independent of the build option PySide modules must be loaded at runtime. Print an error if it fails.
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide2;import os;print(os.path.dirname(PySide2.__file__), end='')"
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide${PYSIDE_MAJOR_VERSION};import os;print(os.path.dirname(PySide${PYSIDE_MAJOR_VERSION}.__file__), end='')"
RESULT_VARIABLE FAILURE
OUTPUT_VARIABLE PRINT_OUTPUT
)
if(FAILURE)
message("================================\n"
"PySide2 Python module not found.\n"
message(FATAL_ERROR,
"================================\n"
"PySide${PYSIDE_MAJOR_VERSION} Python module not found.\n"
"================================\n")
else()
message(STATUS "PySide2 Python module found at ${PRINT_OUTPUT}.\n")
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -c "import PySide${PYSIDE_MAJOR_VERSION};print(PySide${PYSIDE_MAJOR_VERSION}.__version__, end='')"
RESULT_VARIABLE FAILURE
OUTPUT_VARIABLE PySide_VERSION
)
message(STATUS "PySide ${PySide_VERSION} Python module found at ${PRINT_OUTPUT}.\n")
endif()
endmacro(SetupShibokenAndPyside)
# Locate the include directory for a pip-installed package -- uses pip show to find the base pip
# install directory, and then appends the package name and "/include" to the end
macro(find_pip_package PACKAGE)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} -m pip show ${PACKAGE}
RESULT_VARIABLE FAILURE
OUTPUT_VARIABLE PRINT_OUTPUT
)
if(NOT FAILURE)
# Extract Name: and Location: lines and use them to construct the include directory
string(REPLACE "\n" ";" PIP_OUTPUT_LINES ${PRINT_OUTPUT})
foreach(LINE IN LISTS PIP_OUTPUT_LINES)
STRING(FIND "${LINE}" "Name: " NAME_STRING_LOCATION)
STRING(FIND "${LINE}" "Location: " LOCATION_STRING_LOCATION)
if(${NAME_STRING_LOCATION} EQUAL 0)
STRING(SUBSTRING "${LINE}" 6 -1 PIP_PACKAGE_NAME)
elseif(${LOCATION_STRING_LOCATION} EQUAL 0)
STRING(SUBSTRING "${LINE}" 9 -1 PIP_PACKAGE_LOCATION)
endif()
endforeach()
file(TO_NATIVE_PATH "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/include" INCLUDE_DIR)
file(TO_NATIVE_PATH "${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}/lib" LIBRARY)
set(${PACKAGE}_INCLUDE_DIRS ${INCLUDE_DIR} PARENT_SCOPE)
set(${PACKAGE}_LIBRARIES ${LIBRARY} PARENT_SCOPE)
set(${PACKAGE}_FOUND ${LIBRARY} TRUE)
message(STATUS "Found pip-installed ${PACKAGE} in ${PIP_PACKAGE_LOCATION}/${PIP_PACKAGE_NAME}")
endif()
endmacro()
# Macros similar to FindQt4.cmake's WRAP_UI and WRAP_RC, for the automatic generation of Python
# code from Qt4's user interface ('.ui') and resource ('.qrc') files. These macros are called:
# - PYSIDE_WRAP_UI
# - PYSIDE_WRAP_RC
MACRO(PYSIDE_WRAP_UI outfiles)
if (NOT PYSIDE_UIC_EXECUTABLE)
message(FATAL_ERROR "Qt uic is required for generating ${ARGN}")
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)
if(WIN32 OR APPLE)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYSIDE_UIC_EXECUTABLE} ${UICOPTIONS} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
else()
# Especially on Open Build Service we don't want changing date like
# pyside2-uic generates in comments at beginning., which is why
# we follow the tool command with a POSIX-friendly sed.
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND "${PYSIDE_UIC_EXECUTABLE}" ${UICOPTIONS} "${infile}" -o "${outfile}"
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
MAIN_DEPENDENCY "${infile}"
)
endif()
list(APPEND ${outfiles} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYSIDE_WRAP_UI)
MACRO(PYSIDE_WRAP_RC outfiles)
if (NOT PYSIDE_RCC_EXECUTABLE)
message(FATAL_ERROR "Qt rcc is required for generating ${ARGN}")
endif()
FOREACH(it ${ARGN})
GET_FILENAME_COMPONENT(outfile ${it} NAME_WE)
GET_FILENAME_COMPONENT(infile ${it} ABSOLUTE)
SET(outfile "${CMAKE_CURRENT_BINARY_DIR}/${outfile}_rc.py")
#ADD_CUSTOM_TARGET(${it} ALL
# DEPENDS ${outfile}
#)
if(WIN32 OR APPLE)
ADD_CUSTOM_COMMAND(OUTPUT ${outfile}
COMMAND ${PYSIDE_RCC_EXECUTABLE} ${RCCOPTIONS} ${infile} -o ${outfile}
MAIN_DEPENDENCY ${infile}
)
else()
# Especially on Open Build Service we don't want changing date like
# pyside-rcc generates in comments at beginning, which is why
# we follow the tool command with in-place sed.
ADD_CUSTOM_COMMAND(OUTPUT "${outfile}"
COMMAND "${PYSIDE_RCC_EXECUTABLE}" ${RCCOPTIONS} "${infile}" ${PY_ATTRIBUTE} -o "${outfile}"
COMMAND sed "/^# /d" "${outfile}" >"${outfile}.tmp" && mv "${outfile}.tmp" "${outfile}"
MAIN_DEPENDENCY "${infile}"
)
endif()
list(APPEND ${outfiles} ${outfile})
ENDFOREACH(it)
ENDMACRO (PYSIDE_WRAP_RC)