From: Konstantin Leontev Date: Wed, 29 Nov 2023 11:38:32 +0000 (+0000) Subject: [bos #35148][EDF] (2023-T1) Evaluation of PySide. Added an ability to build SalomePyQ... X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=6456407b93e41b188dd52a2cda139b983addd472;p=modules%2Fgui.git [bos #35148][EDF] (2023-T1) Evaluation of PySide. Added an ability to build SalomePyQt module with PySide2. --- diff --git a/CMakeLists.txt b/CMakeLists.txt index a278e3ef4..3f81650dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,6 +84,8 @@ OPTION(SALOME_USE_PYCONSOLE "Enable Python GUI interface (Mandatory in classic c OPTION(SALOME_USE_QXGRAPHVIEWER "Enable QX graph visualization (Mandatory in classic configurations)" ON) OPTION(SALOME_USE_PVVIEWER "Enable ParaView visualization (Mandatory in classic configurations)" ON) +OPTION(SALOME_USE_PYSIDE "Use PySide2 to create Python bindings for Qt" ON) + CMAKE_DEPENDENT_OPTION(SALOME_USE_SALOMEOBJECT "Enable Salome Object (Mandatory in classic configurations)" ON "SALOME_LIGHT_ONLY" ON) diff --git a/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt b/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt index 35603b9d5..8c77ebfae 100644 --- a/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt +++ b/src/SALOME_PYQT/SalomePyQt/CMakeLists.txt @@ -100,31 +100,210 @@ SET(_moc_HEADERS SalomePyQt.h) # --- resources --- -# sip files / to be processed by sip -SET(_sip_files SalomePyQt.sip) -IF(SALOME_USE_PLOT2DVIEWER) - LIST(APPEND _sip_files SalomePyQt_Plot2d.sip) -ENDIF(SALOME_USE_PLOT2DVIEWER) - -# --- sources --- - # sources / moc wrappings QT_WRAP_MOC(_moc_SOURCES ${_moc_HEADERS}) -# sources / sip wrappings -PYQT_WRAP_SIP(_sip_SOURCES ${_sip_files}) - # sources / static SET(_other_SOURCES SalomePyQt.cxx) -# sources / to compile -SET(SalomePyQt_SOURCES ${_other_SOURCES} ${_moc_SOURCES} ${_sip_SOURCES}) +# --- PyQt5/PySide switch --- + +IF(SALOME_USE_PYSIDE) + + # Most of the code below is a modified version of SampleBinding Example from PySide2 repo. + MESSAGE(STATUS "SALOME_USE_PYSIDE is defined. Start compilation with PySide2.") + + # ======================== General Configuration ============================================== + + # The names sample_library and bindings_library below are from Shiboken SampleBinding Example. + # They used here for easy comparing with example during testing period. + SET(lib_base_name "SalomePyQt") + + # The SalomePyQt library for which we will create bindings. + SET(sample_library "lib${lib_base_name}") + + # The name of the generated bindings module (as imported by Python). + SET(bindings_library "${lib_base_name}") + + # The header file with all the types and functions for which bindings will be generated. + SET(wrapped_header ${CMAKE_CURRENT_SOURCE_DIR}/${lib_base_name}_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}/${lib_base_name}_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. + # All generated files go out in lower case, so we need to lower them here to prevent + # file not found error in case of using just original names. + STRING(TOLOWER ${bindings_library} bindings_library_lowercase) + SET(generated_sources + ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/${bindings_library_lowercase}_wrapper.cpp + ${CMAKE_CURRENT_BINARY_DIR}/${bindings_library}/${bindings_library_lowercase}_module_wrapper.cpp) + + # ========================= Shiboken Detection ================================================ + + # Use provided python interpreter if given. + IF(NOT python_interpreter) + FIND_PROGRAM(python_interpreter "python") + ENDIF() + MESSAGE(STATUS "Using python interpreter: ${python_interpreter}") + + # Macro to get various pyside / python include / link flags and paths. + # Uses the not entirely supported utils/pyside2_config.py file. + MACRO(pyside2_config option output_var) + IF(${ARGC} GREATER 2) + SET(is_list ${ARGV2}) + ELSE() + SET(is_list "") + ENDIF() + + EXECUTE_PROCESS( + COMMAND ${python_interpreter} "${CMAKE_CURRENT_SOURCE_DIR}/pyside2_config.py" + ${option} + OUTPUT_VARIABLE ${output_var} + OUTPUT_STRIP_TRAILING_WHITESPACE) + + IF("${${output_var}}" STREQUAL "") + MESSAGE(FATAL_ERROR "Error: Calling pyside2_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. + pyside2_config(--shiboken2-module-path shiboken2_module_path) + pyside2_config(--shiboken2-generator-path shiboken2_generator_path) + pyside2_config(--python-include-path python_include_dir) + pyside2_config(--shiboken2-generator-include-path shiboken2_include_dir 1) + pyside2_config(--shiboken2-module-shared-libraries-cmake shiboken2_shared_libraries 0) + pyside2_config(--python-link-flags-cmake python_linking_data 0) + pyside2_config(--pyside2-path pyside2-path) + + MESSAGE(STATUS "shiboken2_module_path: ${shiboken2_module_path}") + MESSAGE(STATUS "shiboken2_generator_path: ${shiboken2_generator_path}") + MESSAGE(STATUS "python_include_dir: ${python_include_dir}") + MESSAGE(STATUS "shiboken2_include_dir: ${shiboken2_include_dir}") + MESSAGE(STATUS "shiboken2_shared_libraries: ${shiboken2_shared_libraries}") + MESSAGE(STATUS "python_linking_data: ${python_linking_data}") + MESSAGE(STATUS "pyside2-path: ${pyside2-path}") + + SET(shiboken_path "${shiboken2_generator_path}/shiboken2${CMAKE_EXECUTABLE_SUFFIX}") + IF(NOT EXISTS ${shiboken_path}) + MESSAGE(FATAL_ERROR "Shiboken executable not found at path: ${shiboken_path}") + ENDIF() + + # ========================== RPATH Configuration ============================================== + + # 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 ${shiboken2_module_path} ${CMAKE_CURRENT_BINARY_DIR}) + SET(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) + + # ========================== CMake Target - SalomePyQt ==================================== + + # sources / to compile + SET(SalomePyQt_SOURCES ${_other_SOURCES} ${_moc_SOURCES}) + + ADD_LIBRARY(${sample_library} SHARED ${SalomePyQt_SOURCES}) + TARGET_LINK_LIBRARIES(${sample_library} ${_link_LIBRARIES}) + SET_PROPERTY(TARGET ${sample_library} PROPERTY PREFIX "") -# --- rules --- + # Needed mostly on Windows to export symbols, and create a .lib file, otherwise the binding + # library can't link to the sample library. + TARGET_COMPILE_DEFINITIONS(${sample_library} PRIVATE BINDINGS_BUILD) -ADD_LIBRARY(SalomePyQt MODULE ${SalomePyQt_SOURCES}) -TARGET_LINK_LIBRARIES(SalomePyQt ${_link_LIBRARIES}) -INSTALL(TARGETS SalomePyQt DESTINATION ${SALOME_INSTALL_LIBS}) + # ========================== Shiboken Target for generating binding C++ files ================= + + # Get includes and make a colon-separated string to pass to shiboken options + GET_DIRECTORY_PROPERTY(include_directories_list INCLUDE_DIRECTORIES) + LIST(JOIN include_directories_list ":" include_directories_string) + + # Set up the options to pass to shiboken. + SET(shiboken_options --generator-set=shiboken --enable-parent-ctor-heuristic + --enable-return-value-heuristic --use-isnull-as-nb_nonzero + --avoid-protected-hack + --include-paths=${include_directories_string} + -T${pyside2-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}) + + # Prepare pyside2 includes + FILE(GLOB_RECURSE pyside2_include_dirs LIST_DIRECTORIES true ${pyside2-path}/include/*) + LIST(FILTER pyside2_include_dirs EXCLUDE REGEX \.h$) + LIST(APPEND pyside2_include_dirs ${pyside2-path}/include) + MESSAGE(STATUS "pyside2_include_dirs: ${pyside2_include_dirs}") + + # Apply relevant include and link flags. + TARGET_INCLUDE_DIRECTORIES(${bindings_library} PRIVATE + ${python_include_dir} + ${shiboken2_include_dir} + ${CMAKE_CURRENT_SOURCE_DIR} + ${pyside2_include_dirs} + ) + + TARGET_LINK_LIBRARIES(${bindings_library} PRIVATE + ${shiboken2_shared_libraries} + ${sample_library} + ${_link_LIBRARIES} + ) + + # 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}") + + # 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} ${sample_library} + LIBRARY DESTINATION ${SALOME_INSTALL_LIBS} + RUNTIME DESTINATION ${SALOME_INSTALL_LIBS} + ) + +ELSE() + + # sip files / to be processed by sip + SET(_sip_files SalomePyQt.sip) + IF(SALOME_USE_PLOT2DVIEWER) + LIST(APPEND _sip_files SalomePyQt_Plot2d.sip) + ENDIF(SALOME_USE_PLOT2DVIEWER) + + # sources / sip wrappings + PYQT_WRAP_SIP(_sip_SOURCES ${_sip_files}) + + # --- sources --- + + # sources / to compile + SET(SalomePyQt_SOURCES ${_other_SOURCES} ${_moc_SOURCES} ${_sip_SOURCES}) + + # --- rules --- + + ADD_LIBRARY(SalomePyQt MODULE ${SalomePyQt_SOURCES}) + TARGET_LINK_LIBRARIES(SalomePyQt ${_link_LIBRARIES}) + INSTALL(TARGETS SalomePyQt DESTINATION ${SALOME_INSTALL_LIBS}) + +ENDIF() IF(WIN32) SET_TARGET_PROPERTIES(SalomePyQt PROPERTIES SUFFIX ".pyd" DEBUG_OUTPUT_NAME SalomePyQt_d RELEASE_OUTPUT_NAME SalomePyQt) diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.h b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.h new file mode 100644 index 000000000..e2c99f863 --- /dev/null +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.h @@ -0,0 +1,32 @@ +// Copyright (C) 2007-2023 CEA, EDF, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// + +// File : SalomePyQt_bindings.h +// Author : Konstantin LEONTEV +// + +#ifndef SALOME_PYQT_BINDINGS_H +#define SALOME_PYQT_BINDINGS_H + +#include "SalomePyQt.h" + +#endif // SALOME_PYQT_BINDINGS_H diff --git a/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.xml b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.xml new file mode 100644 index 000000000..31e252106 --- /dev/null +++ b/src/SALOME_PYQT/SalomePyQt/SalomePyQt_bindings.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + Py_RETURN_TRUE; + + + + + + + + + + + + + + + + + + + + + + + + + + + %PYARG_0 = %0; + + + + + + + diff --git a/src/SALOME_PYQT/SalomePyQt/pyside2_config.py b/src/SALOME_PYQT/SalomePyQt/pyside2_config.py new file mode 100644 index 000000000..b4b7fe70f --- /dev/null +++ b/src/SALOME_PYQT/SalomePyQt/pyside2_config.py @@ -0,0 +1,378 @@ +############################################################################# +## +## Copyright (C) 2019 The Qt Company Ltd. +## Contact: http://www.qt.io/licensing/ +## +## This file is part of the Qt for Python examples of the Qt Toolkit. +## +## $QT_BEGIN_LICENSE:BSD$ +## You may use this file under the terms of the BSD license as follows: +## +## "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 Qt Company Ltd 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 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 COPYRIGHT +## OWNER 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." +## +## $QT_END_LICENSE$ +## +############################################################################# + +import os, glob, re, sys +from distutils import sysconfig + +generic_error = (' Did you forget to activate your virtualenv? Or perhaps' + ' you forgot to build / install PySide2 into your currently active Python' + ' environment?') +pyside2_error = 'Unable to locate PySide2.' + generic_error +shiboken2_module_error = 'Unable to locate shiboken2-module.' + generic_error +shiboken2_generator_error = 'Unable to locate shiboken2-generator.' + generic_error +pyside2_libs_error = 'Unable to locate the PySide2 shared libraries.' + generic_error +python_link_error = 'Unable to locate the Python library for linking.' +python_include_error = 'Unable to locate the Python include headers directory.' + +options = [] + +# option, function, error, description +options.append(("--shiboken2-module-path", + lambda: find_shiboken2_module(), + shiboken2_module_error, + "Print shiboken2 module location")) +options.append(("--shiboken2-generator-path", + lambda: find_shiboken2_generator(), + shiboken2_generator_error, + "Print shiboken2 generator location")) +options.append(("--pyside2-path", lambda: find_pyside2(), pyside2_error, + "Print PySide2 location")) + +options.append(("--python-include-path", + lambda: get_python_include_path(), + python_include_error, + "Print Python include path")) +options.append(("--shiboken2-generator-include-path", + lambda: get_package_include_path(Package.shiboken2_generator), + pyside2_error, + "Print shiboken2 generator include paths")) +options.append(("--pyside2-include-path", + lambda: get_package_include_path(Package.pyside2), + pyside2_error, + "Print PySide2 include paths")) + +options.append(("--python-link-flags-qmake", lambda: python_link_flags_qmake(), python_link_error, + "Print python link flags for qmake")) +options.append(("--python-link-flags-cmake", lambda: python_link_flags_cmake(), python_link_error, + "Print python link flags for cmake")) + +options.append(("--shiboken2-module-qmake-lflags", + lambda: get_package_qmake_lflags(Package.shiboken2_module), pyside2_error, + "Print shiboken2 shared library link flags for qmake")) +options.append(("--pyside2-qmake-lflags", + lambda: get_package_qmake_lflags(Package.pyside2), pyside2_error, + "Print PySide2 shared library link flags for qmake")) + +options.append(("--shiboken2-module-shared-libraries-qmake", + lambda: get_shared_libraries_qmake(Package.shiboken2_module), pyside2_libs_error, + "Print paths of shiboken2 shared libraries (.so's, .dylib's, .dll's) for qmake")) +options.append(("--shiboken2-module-shared-libraries-cmake", + lambda: get_shared_libraries_cmake(Package.shiboken2_module), pyside2_libs_error, + "Print paths of shiboken2 shared libraries (.so's, .dylib's, .dll's) for cmake")) + +options.append(("--pyside2-shared-libraries-qmake", + lambda: get_shared_libraries_qmake(Package.pyside2), pyside2_libs_error, + "Print paths of PySide2 shared libraries (.so's, .dylib's, .dll's) for qmake")) +options.append(("--pyside2-shared-libraries-cmake", + lambda: get_shared_libraries_cmake(Package.pyside2), pyside2_libs_error, + "Print paths of PySide2 shared libraries (.so's, .dylib's, .dll's) for cmake")) + +options_usage = '' +for i, (flag, _, _, description) in enumerate(options): + options_usage += ' {:<45} {}'.format(flag, description) + if i < len(options) - 1: + options_usage += '\n' + +usage = """ +Utility to determine include/link options of shiboken2/PySide2 and Python for qmake/CMake projects +that would like to embed or build custom shiboken2/PySide2 bindings. + +Usage: pyside2_config.py [option] +Options: +{} + -a Print all options and their values + --help/-h Print this help +""".format(options_usage) + +option = sys.argv[1] if len(sys.argv) == 2 else '-a' +if option == '-h' or option == '--help': + print(usage) + sys.exit(0) + + +class Package(object): + shiboken2_module = 1 + shiboken2_generator = 2 + pyside2 = 3 + + +def clean_path(path): + return path if sys.platform != 'win32' else path.replace('\\', '/') + + +def shared_library_suffix(): + if sys.platform == 'win32': + return 'lib' + elif sys.platform == 'darwin': + return 'dylib' + # Linux + else: + return 'so.*' + + +def import_suffixes(): + if (sys.version_info >= (3, 4)): + import importlib.machinery + return importlib.machinery.EXTENSION_SUFFIXES + else: + import imp + result = [] + for t in imp.get_suffixes(): + result.append(t[0]) + return result + + +def is_debug(): + debug_suffix = '_d.pyd' if sys.platform == 'win32' else '_d.so' + return any([s.endswith(debug_suffix) for s in import_suffixes()]) + + +def shared_library_glob_pattern(): + glob = '*.' + shared_library_suffix() + return glob if sys.platform == 'win32' else 'lib' + glob + + +def filter_shared_libraries(libs_list): + def predicate(lib_name): + basename = os.path.basename(lib_name) + if 'shiboken' in basename or 'pyside2' in basename: + return True + return False + result = [lib for lib in libs_list if predicate(lib)] + return result + + +# Return qmake link option for a library file name +def link_option(lib): + # On Linux: + # Since we cannot include symlinks with wheel packages + # we are using an absolute path for the libpyside and libshiboken + # libraries when compiling the project + baseName = os.path.basename(lib) + link = ' -l' + if sys.platform in ['linux', 'linux2']: # Linux: 'libfoo.so' -> '/absolute/path/libfoo.so' + link = lib + elif sys.platform in ['darwin']: # Darwin: 'libfoo.so' -> '-lfoo' + link += os.path.splitext(baseName[3:])[0] + else: # Windows: 'libfoo.dll' -> 'libfoo.dll' + link += os.path.splitext(baseName)[0] + return link + + +# Locate PySide2 via sys.path package path. +def find_pyside2(): + return find_package_path("PySide2") + + +def find_shiboken2_module(): + return find_package_path("shiboken2") + + +def find_shiboken2_generator(): + return find_package_path("shiboken2_generator") + + +def find_package(which_package): + if which_package == Package.shiboken2_module: + return find_shiboken2_module() + if which_package == Package.shiboken2_generator: + return find_shiboken2_generator() + if which_package == Package.pyside2: + return find_pyside2() + return None + + +def find_package_path(dir_name): + for p in sys.path: + # Salome integration: + # Changed because on Debian 11 shiboken being installed in + # /usr/local/lib/python3.9/dist-packages + # instead of + # /home/user/.local/lib/python3.9/site-packages + #if 'site-' in p: + if 'site-' in p or 'dist-' in p: + package = os.path.join(p, dir_name) + if os.path.exists(package): + return clean_path(os.path.realpath(package)) + return None + + +# Return version as "3.5" +def python_version(): + return str(sys.version_info[0]) + '.' + str(sys.version_info[1]) + + +def get_python_include_path(): + return sysconfig.get_python_inc() + + +def python_link_flags_qmake(): + flags = python_link_data() + if sys.platform == 'win32': + libdir = flags['libdir'] + # This will add the "~1" shortcut for directories that + # contain white spaces + # e.g.: "Program Files" to "Progra~1" + for d in libdir.split("\\"): + if " " in d: + libdir = libdir.replace(d, d.split(" ")[0][:-1]+"~1") + return '-L{} -l{}'.format(libdir, flags['lib']) + elif sys.platform == 'darwin': + return '-L{} -l{}'.format(flags['libdir'], flags['lib']) + + else: + # Linux and anything else + return '-L{} -l{}'.format(flags['libdir'], flags['lib']) + + +def python_link_flags_cmake(): + flags = python_link_data() + libdir = flags['libdir'] + lib = re.sub(r'.dll$', '.lib', flags['lib']) + return '{};{}'.format(libdir, lib) + + +def python_link_data(): + # @TODO Fix to work with static builds of Python + libdir = sysconfig.get_config_var('LIBDIR') + if libdir is None: + libdir = os.path.abspath(os.path.join( + sysconfig.get_config_var('LIBDEST'), "..", "libs")) + version = python_version() + version_no_dots = version.replace('.', '') + + flags = {} + flags['libdir'] = libdir + if sys.platform == 'win32': + suffix = '_d' if is_debug() else '' + flags['lib'] = 'python{}{}'.format(version_no_dots, suffix) + + elif sys.platform == 'darwin': + flags['lib'] = 'python{}'.format(version) + + # Linux and anything else + else: + if sys.version_info[0] < 3: + suffix = '_d' if is_debug() else '' + flags['lib'] = 'python{}{}'.format(version, suffix) + else: + flags['lib'] = 'python{}{}'.format(version, sys.abiflags) + + return flags + + +def get_package_include_path(which_package): + package_path = find_package(which_package) + if package_path is None: + return None + + includes = "{0}/include".format(package_path) + + return includes + + +def get_package_qmake_lflags(which_package): + package_path = find_package(which_package) + if package_path is None: + return None + + link = "-L{}".format(package_path) + glob_result = glob.glob(os.path.join(package_path, shared_library_glob_pattern())) + for lib in filter_shared_libraries(glob_result): + link += ' ' + link += link_option(lib) + return link + + +def get_shared_libraries_data(which_package): + package_path = find_package(which_package) + if package_path is None: + return None + + glob_result = glob.glob(os.path.join(package_path, shared_library_glob_pattern())) + filtered_libs = filter_shared_libraries(glob_result) + libs = [] + if sys.platform == 'win32': + for lib in filtered_libs: + libs.append(os.path.realpath(lib)) + else: + for lib in filtered_libs: + libs.append(lib) + return libs + + +def get_shared_libraries_qmake(which_package): + libs = get_shared_libraries_data(which_package) + if libs is None: + return None + + if sys.platform == 'win32': + if not libs: + return '' + dlls = '' + for lib in libs: + dll = os.path.splitext(lib)[0] + '.dll' + dlls += dll + ' ' + + return dlls + else: + libs_string = '' + for lib in libs: + libs_string += lib + ' ' + return libs_string + + +def get_shared_libraries_cmake(which_package): + libs = get_shared_libraries_data(which_package) + result = ';'.join(libs) + return result + + +print_all = option == "-a" +for argument, handler, error, _ in options: + if option == argument or print_all: + handler_result = handler() + if handler_result is None: + sys.exit(error) + + line = handler_result + if print_all: + line = "{:<40}: ".format(argument) + line + print(line) diff --git a/src/SalomeApp/salome_pluginsmanager.py b/src/SalomeApp/salome_pluginsmanager.py index fb27befd0..7a5f9b33a 100644 --- a/src/SalomeApp/salome_pluginsmanager.py +++ b/src/SalomeApp/salome_pluginsmanager.py @@ -82,16 +82,30 @@ context attributes: """ import os,sys,traceback -from qtsalome import * import salome +import SalomePyQt + +from salome.kernel.logger import Logger +#from salome.kernel.termcolor import GREEN +logger=Logger("PluginsManager") #,color=GREEN) +# VSR 21/11/2011 : do not show infos in the debug mode +#logger.showDebug() + +# Check if SalomePyQt uses PySide2 +if hasattr(SalomePyQt, 'use_pyside'): + logger.info('SalomePyQt implemented with PySide2') + from PySide2.QtWidgets import QMenu, QApplication, QMessageBox +else: + logger.info('SalomePyQt implemented with PyQt5') + from qtsalome import * + SEP=":" if sys.platform == "win32": SEP = ";" # Get SALOME PyQt interface -import SalomePyQt sgPyQt = SalomePyQt.SalomePyQt() # Get SALOME Swig interface @@ -138,11 +152,6 @@ def findMenu(lmenu,menu): PLUGIN_PATH_PATTERN="share/salome/plugins" MATCH_ENDING_PATTERN="_plugins.py" from salome.kernel.syshelper import walktree -from salome.kernel.logger import Logger -#from salome.kernel.termcolor import GREEN -logger=Logger("PluginsManager") #,color=GREEN) -# VSR 21/11/2011 : do not show infos in the debug mode -#logger.showDebug() class PluginsManager: def __init__(self,module,name,basemenuname,menuname):