1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 02:36:34 +01:00

PyFalkon: Fix build system

It is now enabled when PySide2, Shiboken2 and PythonLibs are found.
This commit is contained in:
David Rosca 2018-02-26 10:37:47 +01:00
parent 3f1d37ab69
commit ee84b87d20
No known key found for this signature in database
GPG Key ID: EBC3FC294452C6D8
7 changed files with 52 additions and 389 deletions

View File

@ -97,6 +97,14 @@ set(KF5_MIN_VERSION "5.27.0")
find_package(KF5Wallet ${KF5_MIN_VERSION} CONFIG)
set_package_properties(KF5Wallet PROPERTIES DESCRIPTION "KWallet password backend plugin" TYPE OPTIONAL)
# Optional: PySide2
find_package(PySide2 "2.0.0")
find_package(Shiboken2 "2.0.0")
find_package(PythonLibs "3.0")
set_package_properties(PySide2 PROPERTIES DESCRIPTION "Python plugins" TYPE OPTIONAL)
set_package_properties(Shiboken2 PROPERTIES DESCRIPTION "Python plugins" TYPE OPTIONAL)
set_package_properties(PythonLibs PROPERTIES DESCRIPTION "Python plugins" TYPE OPTIONAL)
# Git revision
if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
find_package(Git QUIET)

View File

@ -37,6 +37,7 @@ Plugins::Plugins(QObject* parent)
loadSettings();
m_pythonPlugin = new QLibrary(QSL("PyFalkonPrivate"), this);
m_pythonPlugin->setLoadHints(QLibrary::ExportExternalSymbolsHint);
if (!m_pythonPlugin->load()) {
qDebug() << "Failed to load python support plugin" << m_pythonPlugin->errorString();
delete m_pythonPlugin;

View File

@ -19,8 +19,10 @@ if (KF5Wallet_FOUND)
add_subdirectory(KWalletPasswords)
endif()
if (PySide2_FOUND AND Shiboken2_FOUND AND PythonLibs_FOUND)
add_subdirectory(PyFalkon)
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
add_subdirectory(TestPlugin)
endif()
#add_subdirectory(PyFalkon)

View File

@ -1,41 +1,11 @@
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
# Enable policy to run automoc on generated files.
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
# Macro to get various pyside / python include / link flags.
macro(pyside2_config option output_var)
if(${ARGC} GREATER 2)
set(is_list ${ARGV2})
else()
set(is_list "")
endif()
execute_process(
COMMAND python "${CMAKE_CURRENT_SOURCE_DIR}/pyside2_config.py" ${option}
OUTPUT_VARIABLE ${output_var}
OUTPUT_STRIP_TRAILING_WHITESPACE)
if ("${${output_var}}" STREQUAL "")
message(FATAL_ERROR "Got empty string when running: pyside2_config.py ${option}")
endif()
if(is_list)
string (REPLACE " " ";" ${output_var} "${${output_var}}")
endif()
endmacro()
set(SHIBOKEN_PATH "/usr/bin/shiboken2")
set(TYPESYSTEMS_PATH "/usr/share/PySide2/typesystems")
if(NOT EXISTS ${SHIBOKEN_PATH})
message(FATAL_ERROR "Shiboken executable not found at path: ${SHIBOKEN_PATH}")
endif()
pyside2_config(--python-include PYTHON_INCLUDE_DIR)
pyside2_config(--pyside2-include PYSIDE2_INCLUDE_DIR 1)
pyside2_config(--python-link-cmake PYTHON_LINKING_DATA 1)
pyside2_config(--pyside2-shared-libraries-cmake PYSIDE2_SHARED_LIBRARIES 1)
# Get all relevant Qt include dirs, to pass them on to shiboken.
get_property(QT_CORE_INCLUDE_DIRS TARGET Qt5::Core PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
get_property(QT_GUI_INCLUDE_DIRS TARGET Qt5::Gui PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
@ -53,40 +23,20 @@ set(INCLUDES "")
foreach(INCLUDE_DIR ${QT_INCLUDE_DIRS})
list(APPEND INCLUDES "-I${INCLUDE_DIR}")
endforeach()
get_property(FalkonPrivate_INCLUDE_DIRS TARGET FalkonPrivate PROPERTY INCLUDE_DIRECTORIES)
foreach(INCLUDE_DIR ${FalkonPrivate_INCLUDE_DIRS})
list(APPEND INCLUDES "-I${INCLUDE_DIR}")
endforeach()
# Set up the options to pass to shiboken.
set(WRAPPED_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/wrappedclasses.h)
set(GLOBAL_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/pyfalkon_global.h)
set(TYPESYSTEM_FILE ${CMAKE_CURRENT_SOURCE_DIR}/pyfalkon.xml)
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
${INCLUDES}
-I${CMAKE_SOURCE_DIR}
-I${CMAKE_SOURCE_DIR}/src/lib/3rdparty
-I${CMAKE_SOURCE_DIR}/src/lib/adblock
-I${CMAKE_SOURCE_DIR}/src/lib/app
-I${CMAKE_SOURCE_DIR}/src/lib/autofill
-I${CMAKE_SOURCE_DIR}/src/lib/bookmarks
-I${CMAKE_SOURCE_DIR}/src/lib/cookies
-I${CMAKE_SOURCE_DIR}/src/lib/downloads
-I${CMAKE_SOURCE_DIR}/src/lib/history
-I${CMAKE_SOURCE_DIR}/src/lib/navigation
-I${CMAKE_SOURCE_DIR}/src/lib/network
-I${CMAKE_SOURCE_DIR}/src/lib/notifications
-I${CMAKE_SOURCE_DIR}/src/lib/opensearch
-I${CMAKE_SOURCE_DIR}/src/lib/other
-I${CMAKE_SOURCE_DIR}/src/lib/plugins
-I${CMAKE_SOURCE_DIR}/src/lib/popupwindow
-I${CMAKE_SOURCE_DIR}/src/lib/preferences
-I${CMAKE_SOURCE_DIR}/src/lib/session
-I${CMAKE_SOURCE_DIR}/src/lib/sidebar
-I${CMAKE_SOURCE_DIR}/src/lib/tabwidget
-I${CMAKE_SOURCE_DIR}/src/lib/tools
-I${CMAKE_SOURCE_DIR}/src/lib/webengine
-I${CMAKE_SOURCE_DIR}/src/lib/webtab
-T${CMAKE_SOURCE_DIR}
-T${TYPESYSTEMS_PATH}
-T${PYSIDE_TYPESYSTEMS}
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
)
@ -117,27 +67,27 @@ set(GENERATED_SOURCES
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon/mainapplication_wrapper.cpp
)
set(GENERATED_SOURCES_DEPENDENCIES
${WRAPPED_HEADER}
${GLOBAL_HEADER}
${TYPESYSTEM_FILE}
)
# Add custom target to run shiboken.
add_custom_command(OUTPUT ${GENERATED_SOURCES}
COMMAND ${SHIBOKEN_PATH}
${SHIBOKEN_OPTIONS} ${WRAPPED_HEADER} ${TYPESYSTEM_FILE}
COMMAND ${SHIBOKEN_BINARY}
${SHIBOKEN_OPTIONS} ${GLOBAL_HEADER} ${TYPESYSTEM_FILE}
DEPENDS ${GENERATED_SOURCES_DEPENDENCIES}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Running generator for ${TYPESYSTEM_FILE}.")
# We need to include the headers for the module bindings that we use.
set(PYSIDE2_ADDITIONAL_INCLUDES "")
foreach(INCLUDE_DIR ${PYSIDE2_INCLUDE_DIR})
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtCore")
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtGui")
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtNetwork")
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWidgets")
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWebChannel")
list(APPEND PYSIDE2_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWebEngineWidgets")
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}/QtNetwork")
list(APPEND PYSIDE_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWidgets")
list(APPEND PYSIDE_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWebChannel")
list(APPEND PYSIDE_ADDITIONAL_INCLUDES "${INCLUDE_DIR}/QtWebEngineWidgets")
endforeach()
set( PyFalkon_SRCS
@ -145,29 +95,28 @@ set( PyFalkon_SRCS
${GENERATED_SOURCES}
)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
add_library(PyFalkonPrivate SHARED ${PyFalkon_SRCS})
set_target_properties(PyFalkonPrivate PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION "2")
install(TARGETS PyFalkonPrivate ${KDE_INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY NAMELINK_SKIP)
target_include_directories(PyFalkonPrivate PRIVATE ${PYTHON_INCLUDE_DIR})
target_include_directories(PyFalkonPrivate PRIVATE ${PYSIDE2_INCLUDE_DIR})
target_include_directories(PyFalkonPrivate PRIVATE ${PYSIDE2_ADDITIONAL_INCLUDES})
target_include_directories(PyFalkonPrivate PRIVATE ${CMAKE_SOURCE_DIR})
target_include_directories(PyFalkonPrivate PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/PyFalkon)
target_include_directories(PyFalkonPrivate
PRIVATE
${SHIBOKEN_INCLUDE_DIR}
${SHIBOKEN_PYTHON_INCLUDE_DIR}
${PYSIDE_INCLUDE_DIR}
${PYSIDE_ADDITIONAL_INCLUDES}
${CMAKE_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}/PyFalkon
)
target_link_libraries(PyFalkonPrivate PRIVATE FalkonPrivate)
target_link_libraries(PyFalkonPrivate PRIVATE Qt5::Widgets)
target_link_libraries(PyFalkonPrivate PRIVATE ${PYSIDE2_SHARED_LIBRARIES})
# Find and link to the python library.
list(GET PYTHON_LINKING_DATA 0 PYTHON_LIBDIR)
list(GET PYTHON_LINKING_DATA 1 PYTHON_LIB)
find_library(PYTHON_LINK_FLAGS ${PYTHON_LIB} HINTS ${PYTHON_LIBDIR})
target_link_libraries(PyFalkonPrivate PRIVATE ${PYTHON_LINK_FLAGS})
target_link_libraries(PyFalkonPrivate
PRIVATE
FalkonPrivate
${PYTHON_LIBRARIES}
${SHIBOKEN_LIBRARY}
${SHIBOKEN_PYTHON_LIBRARIES}
${PYSIDE_LIBRARY}
)
# Same as CONFIG += no_keywords to avoid syntax errors in object.h due to the usage of the word Slot
target_compile_definitions(PyFalkonPrivate PRIVATE QT_NO_KEYWORDS)

View File

@ -1,289 +0,0 @@
#############################################################################
##
## Copyright (C) 2017 The Qt Company Ltd.
## Contact: http://www.qt.io/licensing/
##
## This file is part of the PySide 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, imp
from distutils import sysconfig
if sys.platform == 'win32':
import winreg
usage = """
Utility to determine include/link options of PySide2 and Python for qmake
Usage: pyside2_config.py [option]
Options:
--python-include Print Python include path
--python-link Print Python link flags
--pyside2 Print PySide2 location
--pyside2-include Print PySide2 include paths
--pyside2-link Print PySide2 link flags
--pyside2-shared-libraries Print paths of PySide2 shared libraries (.so's, .dylib's, .dll's)
--clang-bin-dir Print path to the clang bin directory
-a Print all
--help/-h Print this help
"""
def cleanPath(path):
return path if sys.platform != 'win32' else path.replace('\\', '/')
def sharedLibrarySuffix():
if sys.platform == 'win32':
return 'lib'
elif sys.platform == 'darwin':
return 'dylib'
return 'so'
def sharedLibraryGlobPattern():
glob = '*.' + sharedLibrarySuffix()
return glob
def filterPySide2SharedLibraries(list):
def predicate(item):
basename = os.path.basename(item)
if 'Qt' in basename and 'cpython' in basename:
return True
if 'shiboken' in basename or 'pyside2' in basename:
return True
return False
result = [item for item in list if predicate(item)]
return result
# Return qmake link option for a library file name
def linkOption(lib):
baseName = os.path.splitext(os.path.basename(lib))[0]
link = ' -l'
if sys.platform in ['linux', 'linux2', 'darwin']: # Linux: 'libfoo.so' -> '-lfoo'
link += baseName[3:]
else:
link += baseName
return link
# Locate PySide2 via package path
def findPySide2():
for p in sys.path:
if 'site-' in p:
pyside2 = os.path.join(p, 'PySide2')
if os.path.exists(pyside2):
return cleanPath(os.path.realpath(pyside2))
return None
# Return version as "3.5"
def pythonVersion():
return str(sys.version_info[0]) + '.' + str(sys.version_info[1])
def pythonInclude():
return sysconfig.get_python_inc()
def pythonLinkQmake():
flags = pythonLinkData()
if sys.platform == 'win32' or sys.platform == 'darwin':
return '-L{} -l{}'.format(flags['libdir'], flags['lib'])
# Linux and anything else
return '-l{}'.format(flags['lib'])
def pythonLinkCmake():
flags = pythonLinkData()
libdir = flags['libdir']
lib = re.sub(r'.dll$', '.lib', flags['lib'])
return '{} {}'.format(libdir, lib)
def pythonLinkData():
# @TODO Fix to work with static builds of Python
libdir = sysconfig.get_config_var('LIBDIR')
version = pythonVersion()
version_no_dots = version.replace('.', '')
flags = {}
flags['libdir'] = libdir
if sys.platform == 'win32':
suffix = '_d' if any([tup[0].endswith('_d.pyd') for tup in imp.get_suffixes()]) 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 any([tup[0].endswith('_d.so') for tup in imp.get_suffixes()]) else ''
flags['lib'] = 'python{}{}'.format(version, suffix)
else:
flags['lib'] = 'python{}{}'.format(version, sys.abiflags)
return flags
def pyside2Include():
pySide2 = findPySide2()
if pySide2 is None:
return None
return "/usr/include/PySide2 /usr/include/shiboken2"
def pyside2Link():
pySide2 = findPySide2()
if pySide2 is None:
return None
link = "-L{}".format(pySide2)
glob_result = glob.glob(os.path.join(pySide2, sharedLibraryGlobPattern()))
for lib in filterPySide2SharedLibraries(glob_result):
link += ' '
link += linkOption(lib)
return link
def pyside2SharedLibrariesData():
pySide2 = findPySide2()
if pySide2 is None:
return None
glob_result = glob.glob(os.path.join(pySide2, sharedLibraryGlobPattern()))
filtered_libs = filterPySide2SharedLibraries(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 pyside2SharedLibraries():
libs = pyside2SharedLibrariesData()
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 = ''
print(libs)
for lib in libs:
libs_string += ' ' + lib
return libs_string
def pyside2SharedLibrariesCmake():
libs = pyside2SharedLibrariesData()
result = ' '.join(libs)
result += ' /usr/lib/libpyside2.cpython-36m-x86_64-linux-gnu.so.2.0'
result += ' /usr/lib/libshiboken2.cpython-36m-x86_64-linux-gnu.so.2.0'
return result
def clangBinPath():
source = 'LLVM_INSTALL_DIR'
clangDir = os.environ.get(source, None)
if not clangDir:
source = 'CLANG_INSTALL_DIR'
clangDir = os.environ.get(source, None)
if not clangDir:
source = 'llvm-config'
try:
output = run_process_output([source, '--prefix'])
if output:
clangDir = output[0]
except OSError:
pass
if clangDir:
return os.path.realpath(clangDir + os.path.sep + 'bin')
return ''
option = sys.argv[1] if len(sys.argv) == 2 else '-a'
if option == '-h' or option == '--help':
print(usage)
sys.exit(0)
if option == '--pyside2' or option == '-a':
pySide2 = findPySide2()
if pySide2 is None:
sys.exit('Unable to locate PySide2')
print(pySide2)
if option == '--pyside2-link' or option == '-a':
l = pyside2Link()
if l is None:
sys.exit('Unable to locate PySide2')
print(l)
if option == '--pyside2-include' or option == '-a':
i = pyside2Include()
if i is None:
sys.exit('Unable to locate PySide2')
print(i)
if option == '--python-include' or option == '-a':
i = pythonInclude()
if i is None:
sys.exit('Unable to locate Python')
print(i)
if option == '--python-link' or option == '-a':
l = pythonLinkQmake()
if l is None:
sys.exit('Unable to locate Python')
print(l)
if option == '--python-link-cmake' or option == '-a':
l = pythonLinkCmake()
if l is None:
sys.exit('Unable to locate Python')
print(l)
if option == '--pyside2-shared-libraries' or option == '-a':
l = pyside2SharedLibraries()
if l is None:
sys.exit('Unable to locate the PySide2 shared libraries')
print(l)
if option == '--pyside2-shared-libraries-cmake' or option == '-a':
l = pyside2SharedLibrariesCmake()
if l is None:
sys.exit('Unable to locate the PySide2 shared libraries')
print(l)
if option == '--clang-bin-dir' or option == '-a':
l = clangBinPath()
if l is None:
sys.exit('Unable to locate Clang')
print(l)

View File

@ -83,15 +83,7 @@ static State init()
Py_Initialize();
qAddPostRoutine(cleanup);
state = PythonInitialized;
if (!PyImport_ImportModule("Falkon")) {
PyErr_Print();
qWarning() << "Failed to import Falkon module!";
return state = PythonError;
}
return state;
return state = PythonInitialized;
}
void pyfalkon_register_plugin(PluginInterface *plugin)