aboutsummaryrefslogtreecommitdiffstats
path: root/build_scripts/main.py
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2018-07-20 18:54:05 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2018-10-12 14:45:35 +0000
commit43fe3494a9d902034896e3afa7b5158c77163be0 (patch)
tree07bbd20b8bd322fdf062b87dfade1e1e74d80433 /build_scripts/main.py
parentc6c9f057cddc0e0b885a648489264538eba0a158 (diff)
Allow building shiboken2 and PySide2 as separate wheels
Actually this creates 3 wheel packages: - shiboken2 (the python module and libshiboken shared library) - shiboken2-generator (contains the generator executable, libclang and dependent Qt libraries) - PySide2 (the PySide2 modules and Qt shared libraries, and tools like rcc, uic) Calling the setup.py script will not do the actual build now (in the sense of calling CMake, make, etc.). Instead it will spawn new processes (via subprocess.call) calling the same setup.py script, but with different arguments. These "sub-invocations" will do the actual building. Thus, the "top-level invocation" will decide which packages to build and delegate that to the "sub-invocations" of setup.py. A new optional command line argument is introduced called "--build-type" which defaults to "all", and can also be set to "shiboken2", "shiboken2-generator" and "pyside2". A user can choose which packages to build using this option. The "top-level invocation" uses this option to decide how many "sub-invocations" to execute. A new command line argument called "--internal-build-type" takes the same values as the one above. It defines which package will actually be built in the new spawned "sub-invocation" process. The "top-level invocation" sets this automatically for each "sub-invocation" depending on the value of "--build-type". This option is also useful for developers that may want to debug the python building code in the "sub-invocation". Developers can set this manually via the command line, and thus avoid the process spawning indirection. A new class Config is introduced to facilitate storage of the various state needed for building a single package. A new class SetupRunner is introduced that takes care of the "--build-type" and "--internal-build-type" argument handling and delegation of "sub-invocations". A new class Options is introduced to 'hopefully', in the future, streamline the mess of option handling that we currently have. setup.py now is now simplified to mostly just call SetupRunner.run_setup(). Certain refactorings were done to facilitate further clean-up of the build code, the current code is definitely not the end all be all. Various other changes that were needed to implement the wheel separation: - a new cmake_helpers directory is added to share common cmake code between packages. - the custom popenasync.py file is removed in favor of using subprocess.call in as many places as possible, and thus avoid 10 different functions for process creation. - Manifest.in is removed, because copying to the setuptools build dir is now done directly by prepare_packages functions. - because prepare_packages copies directly to the setuptools build dir, avoiding the pyside_package dir, we do less copying of big Qt files now. - versioning of PySide2 and shiboken2 packages is now separate. shiboken2 and shiboken2-generator share the same versions for now though. - shiboken2 is now listed as a required package for PySide2, to facilitate pip requirements.txt dependencies. - coin_build_instructions currently needs to install an unreleased version of wheel, due to a bug that breaks installation of generated wheel files. - added separate command line options to pyside2_config.py for shiboken2-module and shiboken2-generator. - adapted samplebinding and scriptableapplication projects due to shiboken being a separate package. - adapted pyside2-tool and shiboken2-tool python scripts for setup tools entry points. - made some optimizations not to invoke cmake for shiboken2-generator when doing a top-level "all" build. - fixed unnecessary rpaths not to be included on Linux (mainly the Qt rpaths). Task-nubmer: PYSIDE-749 Change-Id: I0336043955624c1d12ed254802c442608cced5fb Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'build_scripts/main.py')
-rw-r--r--build_scripts/main.py387
1 files changed, 191 insertions, 196 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py
index b64d6f1a9..50f751caa 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -42,6 +42,7 @@ from distutils.version import LooseVersion
import os
import time
+from .config import config
from .utils import memoize, get_python_dict
from .options import *
@@ -90,15 +91,11 @@ def get_setuptools_extension_modules():
extension_modules = [Extension(*extension_args, **extension_kwargs)]
return extension_modules
-# Buildable extensions.
-contained_modules = ['shiboken2', 'pyside2', 'pyside2-tools']
# Git submodules: ["submodule_name",
# "location_relative_to_sources_folder"]
submodules = [["pyside2-tools"]]
-pyside_package_dir_name = "pyside_package"
-
try:
import setuptools
except ImportError:
@@ -108,13 +105,8 @@ except ImportError:
import sys
import platform
import re
-import fnmatch
-
-import difflib # for a close match of dirname and module
-import functools
-from distutils import log
-from distutils.errors import DistutilsOptionError
+import distutils.log as log
from distutils.errors import DistutilsSetupError
from distutils.sysconfig import get_config_var
from distutils.sysconfig import get_python_lib
@@ -123,7 +115,7 @@ from distutils.command.build import build as _build
from distutils.command.build_ext import build_ext as _build_ext
from distutils.util import get_platform
-from setuptools import setup, Extension
+from setuptools import Extension
from setuptools.command.install import install as _install
from setuptools.command.install_lib import install_lib as _install_lib
from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
@@ -132,39 +124,40 @@ from setuptools.command.build_py import build_py as _build_py
from .qtinfo import QtInfo
from .utils import rmtree, detect_clang, copyfile, copydir, run_process_output, run_process
-from .utils import update_env_path, init_msvc_env, filter_match, macos_fix_rpaths_for_library
+from .utils import update_env_path, init_msvc_env, filter_match
+from .utils import macos_fix_rpaths_for_library
+from .utils import linux_fix_rpaths_for_library
from .platforms.unix import prepare_packages_posix
from .platforms.windows_desktop import prepare_packages_win32
from .wheel_override import wheel_module_exists, get_bdist_wheel_override
from textwrap import dedent
-# make sure that setup.py is run with an allowed python version
+
def check_allowed_python_version():
+ """
+ Make sure that setup.py is run with an allowed python version.
+ """
+
import re
- pattern = "'Programming Language :: Python :: (\d+)\.(\d+)'"
+ pattern = "Programming Language :: Python :: (\d+)\.(\d+)"
supported = []
- with open(setup_py_path) as setup:
- for line in setup.readlines():
- found = re.search(pattern, line)
- if found:
- major = int(found.group(1))
- minor = int(found.group(2))
- supported.append( (major, minor) )
+
+ for line in config.python_version_classifiers:
+ found = re.search(pattern, line)
+ if found:
+ major = int(found.group(1))
+ minor = int(found.group(2))
+ supported.append( (major, minor) )
this_py = sys.version_info[:2]
if this_py not in supported:
- print("only these python versions are supported:", supported)
+ print("Unsupported python version detected. Only these python versions are supported: {}"
+ .format(supported))
sys.exit(1)
-check_allowed_python_version()
qt_src_dir = ''
-# This is used automatically by distutils.command.install object, to
-# specify final installation location.
-OPTION_FINAL_INSTALL_PREFIX = option_value("prefix")
-
-
if OPTION_QT_VERSION is None:
OPTION_QT_VERSION = "5"
if OPTION_QMAKE is None:
@@ -293,8 +286,7 @@ def get_qt_version():
qt_version = qtinfo.version
if not qt_version:
- log.error("Failed to query the Qt version with qmake {0}".format(
- self.qtinfo.qmake_command))
+ log.error("Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command))
sys.exit(1)
if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
@@ -304,12 +296,13 @@ def get_qt_version():
return qt_version
+
def prepare_build():
if (os.path.isdir(".git") and not OPTION_IGNOREGIT and
not OPTION_ONLYPACKAGE and not OPTION_REUSE_BUILD):
prepare_sub_modules()
- # Clean up temp and package folders
- for n in [pyside_package_dir_name, "build"]:
+ # Clean up temp build folder.
+ for n in ["build"]:
d = os.path.join(setup_script_dir, n)
if os.path.isdir(d):
print("Removing {}".format(d))
@@ -318,13 +311,7 @@ def prepare_build():
except Exception as e:
print('***** problem removing "{}"'.format(d))
print('ignored error: {}'.format(e))
- # Prepare package folders
- ppdn = pyside_package_dir_name
- absolute_paths = [os.path.join(ppdn, "PySide2"),
- os.path.join(ppdn, "pyside2uic")]
- for pkg in absolute_paths:
- pkg_dir = os.path.join(setup_script_dir, pkg)
- os.makedirs(pkg_dir)
+
# locate Qt sources for the documentation
if OPTION_QT_SRC is None:
install_prefix = qtinfo.prefix_dir
@@ -389,26 +376,15 @@ class PysideBuildExt(_build_ext):
pass
-
-# pyside_build_py and pyside_install_lib are reimplemented to preserve
-# symlinks when distutils / setuptools copy files to various
-# directories through the different build stages.
class PysideBuildPy(_build_py):
def __init__(self, *args, **kwargs):
_build_py.__init__(self, *args, **kwargs)
- def build_package_data(self):
- """Copies files from pyside_package into build/xxx directory"""
-
- for package, src_dir, build_dir, filenames in self.data_files:
- for filename in filenames:
- target = os.path.join(build_dir, filename)
- self.mkpath(os.path.dirname(target))
- srcfile = os.path.abspath(os.path.join(src_dir, filename))
- # Using our own copyfile makes sure to preserve symlinks.
- copyfile(srcfile, target)
+# _install_lib is reimplemented to preserve
+# symlinks when distutils / setuptools copy files to various
+# directories from the setup tools build dir to the install dir.
class PysideInstallLib(_install_lib):
def __init__(self, *args, **kwargs):
@@ -539,10 +515,12 @@ class PysideBuild(_build):
py_prefix = get_config_var("prefix")
if not py_prefix or not os.path.exists(py_prefix):
py_prefix = sys.prefix
+ self.py_prefix = py_prefix
if sys.platform == "win32":
py_scripts_dir = os.path.join(py_prefix, "Scripts")
else:
py_scripts_dir = os.path.join(py_prefix, "bin")
+ self.py_scripts_dir = py_scripts_dir
if py_libdir is None or not os.path.exists(py_libdir):
if sys.platform == "win32":
py_libdir = os.path.join(py_prefix, "libs")
@@ -656,7 +634,7 @@ class PysideBuild(_build):
qt_version = get_qt_version()
# Update the PATH environment variable
- additional_paths = [py_scripts_dir, qt_dir]
+ additional_paths = [self.py_scripts_dir, qt_dir]
# Add Clang to path for Windows.
# Revisit once Clang is bundled with Qt.
@@ -685,19 +663,11 @@ class PysideBuild(_build):
install_dir = os.path.join(script_dir, prefix() + "_install",
"{}".format(build_name))
- # Try to ensure that tools built by this script (such as shiboken2)
- # are found before any that may already be installed on the system.
- update_env_path([os.path.join(install_dir, 'bin')])
-
- # Tell cmake to look here for *.cmake files
- os.environ['CMAKE_PREFIX_PATH'] = install_dir
-
self.make_path = make_path
self.make_generator = make_generator
self.debug = OPTION_DEBUG
self.script_dir = script_dir
- self.pyside_package_dir = os.path.join(self.script_dir,
- pyside_package_dir_name)
+ self.st_build_dir = os.path.join(self.script_dir, self.build_lib)
self.sources_dir = sources_dir
self.build_dir = build_dir
self.install_dir = install_dir
@@ -709,14 +679,61 @@ class PysideBuild(_build):
self.site_packages_dir = get_python_lib(1, 0, prefix=install_dir)
self.build_tests = OPTION_BUILDTESTS
- setuptools_install_prefix = get_python_lib(1)
- if OPTION_FINAL_INSTALL_PREFIX:
- setuptools_install_prefix = OPTION_FINAL_INSTALL_PREFIX
-
# Save the shiboken build dir path for clang deployment
# purposes.
self.shiboken_build_dir = os.path.join(self.build_dir, "shiboken2")
+ self.log_pre_build_info()
+
+ # Prepare folders
+ if not os.path.exists(self.sources_dir):
+ log.info("Creating sources folder {}...".format(self.sources_dir))
+ os.makedirs(self.sources_dir)
+ if not os.path.exists(self.build_dir):
+ log.info("Creating build folder {}...".format(self.build_dir))
+ os.makedirs(self.build_dir)
+ if not os.path.exists(self.install_dir):
+ log.info("Creating install folder {}...".format(self.install_dir))
+ os.makedirs(self.install_dir)
+
+ if not (OPTION_ONLYPACKAGE
+ and not config.is_internal_shiboken_generator_build_and_part_of_top_level_all()):
+ # Build extensions
+ for ext in config.get_buildable_extensions():
+ self.build_extension(ext)
+
+ if OPTION_BUILDTESTS:
+ # we record the latest successful build and note the
+ # build directory for supporting the tests.
+ timestamp = time.strftime('%Y-%m-%d_%H%M%S')
+ build_history = os.path.join(setup_script_dir, 'build_history')
+ unique_dir = os.path.join(build_history, timestamp)
+ os.makedirs(unique_dir)
+ fpath = os.path.join(unique_dir, 'build_dir.txt')
+ with open(fpath, 'w') as f:
+ print(build_dir, file=f)
+ log.info("Created {}".format(build_history))
+
+ if not OPTION_SKIP_PACKAGING:
+ # Build patchelf if needed
+ self.build_patchelf()
+
+ # Prepare packages
+ self.prepare_packages()
+
+ # Build packages
+ _build.run(self)
+ else:
+ log.info("Skipped preparing and building packages.")
+ log.info('*** Build completed')
+
+ def log_pre_build_info(self):
+ if config.is_internal_shiboken_generator_build_and_part_of_top_level_all():
+ return
+
+ setuptools_install_prefix = get_python_lib(1)
+ if OPTION_FINAL_INSTALL_PREFIX:
+ setuptools_install_prefix = OPTION_FINAL_INSTALL_PREFIX
log.info("=" * 30)
log.info("Package version: {}".format(get_package_version()))
log.info("Build type: {}".format(self.build_type))
@@ -726,40 +743,34 @@ class PysideBuild(_build):
log.info("Make generator: {}".format(self.make_generator))
log.info("Make jobs: {}".format(OPTION_JOBS))
log.info("-" * 3)
-
log.info("setup.py directory: {}".format(self.script_dir))
log.info("Build scripts directory: {}".format(build_scripts_dir))
log.info("Sources directory: {}".format(self.sources_dir))
-
log.info(dedent("""
- Building PySide2 will create and touch directories
+ Building {st_package_name} will create and touch directories
in the following order:
make build directory (py*_build/*/*) ->
make install directory (py*_install/*/*) ->
- {} directory (pyside_package/*) ->
setuptools build directory (build/*/*) ->
setuptools install directory
(usually path-installed-python/lib/python*/site-packages/*)
- """).format(pyside_package_dir_name))
-
+ """).format(st_package_name=config.package_name()))
log.info("make build directory: {}".format(self.build_dir))
log.info("make install directory: {}".format(self.install_dir))
- log.info("{} directory: {}".format(pyside_package_dir_name,
- self.pyside_package_dir))
- log.info("setuptools build directory: {}".format(
- os.path.join(self.script_dir, "build")))
- log.info("setuptools install directory: {}".format(
- setuptools_install_prefix))
- log.info("make-installed site-packages directory: {} \n"
- " (only relevant for copying files from "
- "'make install directory' to '{} directory'".format(
- self.site_packages_dir, pyside_package_dir_name))
+ log.info("setuptools build directory: {}".format(self.st_build_dir))
+ log.info("setuptools install directory: {}".format(setuptools_install_prefix))
+ log.info(dedent("""
+ make-installed site-packages directory: {}
+ (only relevant for copying files from 'make install directory'
+ to 'setuptools build directory'
+ """).format(
+ self.site_packages_dir))
log.info("-" * 3)
log.info("Python executable: {}".format(self.py_executable))
log.info("Python includes: {}".format(self.py_include_dir))
log.info("Python library: {}".format(self.py_library))
- log.info("Python prefix: {}".format(py_prefix))
- log.info("Python scripts: {}".format(py_scripts_dir))
+ log.info("Python prefix: {}".format(self.py_prefix))
+ log.info("Python scripts: {}".format(self.py_scripts_dir))
log.info("-" * 3)
log.info("Qt qmake: {}".format(self.qtinfo.qmake_command))
log.info("Qt version: {}".format(self.qtinfo.version))
@@ -772,52 +783,11 @@ class PysideBuild(_build):
if sys.platform == 'darwin':
pyside_macos_deployment_target = (
PysideBuild.macos_pyside_min_deployment_target()
- )
+ )
log.info("MACOSX_DEPLOYMENT_TARGET set to: {}".format(
pyside_macos_deployment_target))
log.info("=" * 30)
- # Prepare folders
- if not os.path.exists(self.sources_dir):
- log.info("Creating sources folder {}...".format(self.sources_dir))
- os.makedirs(self.sources_dir)
- if not os.path.exists(self.build_dir):
- log.info("Creating build folder {}...".format(self.build_dir))
- os.makedirs(self.build_dir)
- if not os.path.exists(self.install_dir):
- log.info("Creating install folder {}...".format(self.install_dir))
- os.makedirs(self.install_dir)
-
- if not OPTION_ONLYPACKAGE:
- # Build extensions
- for ext in contained_modules:
- self.build_extension(ext)
-
- if OPTION_BUILDTESTS:
- # we record the latest successful build and note the
- # build directory for supporting the tests.
- timestamp = time.strftime('%Y-%m-%d_%H%M%S')
- build_history = os.path.join(setup_script_dir, 'build_history')
- unique_dir = os.path.join(build_history, timestamp)
- os.makedirs(unique_dir)
- fpath = os.path.join(unique_dir, 'build_dir.txt')
- with open(fpath, 'w') as f:
- print(build_dir, file=f)
- log.info("Created {}".format(build_history))
-
- if not OPTION_SKIP_PACKAGING:
- # Build patchelf if needed
- self.build_patchelf()
-
- # Prepare packages
- self.prepare_packages()
-
- # Build packages
- _build.run(self)
- else:
- log.info("Skipped preparing and building packages.")
- log.info('*** Build completed')
-
@staticmethod
def macos_qt_min_deployment_target():
target = qtinfo.macos_min_deployment_target
@@ -953,6 +923,17 @@ class PysideBuild(_build):
cmake_cmd.append("-DPYTHON_EXECUTABLE={}".format(self.py_executable))
cmake_cmd.append("-DPYTHON_INCLUDE_DIR={}".format(self.py_include_dir))
cmake_cmd.append("-DPYTHON_LIBRARY={}".format(self.py_library))
+
+ # If a custom shiboken cmake config directory path was provided, pass it to CMake.
+ if OPTION_SHIBOKEN_CONFIG_DIR and config.is_internal_pyside_build():
+ if os.path.exists(OPTION_SHIBOKEN_CONFIG_DIR):
+ log.info("Using custom provided shiboken2 installation: {}"
+ .format(OPTION_SHIBOKEN_CONFIG_DIR))
+ cmake_cmd.append("-DShiboken2_DIR={}".format(OPTION_SHIBOKEN_CONFIG_DIR))
+ else:
+ log.info("Custom provided shiboken2 installation not found. Path given: {}"
+ .format(OPTION_SHIBOKEN_CONFIG_DIR))
+
if OPTION_MODULE_SUBSET:
module_sub_set = ''
for m in OPTION_MODULE_SUBSET.split(','):
@@ -1014,20 +995,20 @@ class PysideBuild(_build):
cmake_cmd.append("-DPYSIDE_QT_CONF_PREFIX={}".format(
pyside_qt_conf_prefix))
- # Pass package version to CMake, so this string can be
- # embedded into _config.py file.
- package_version = get_package_version()
- cmake_cmd.append("-DPYSIDE_SETUP_PY_PACKAGE_VERSION={}".format(
- package_version))
-
- # In case if this is a snapshot build, also pass the
- # timestamp as a separate value, because it the only
- # version component that is actually generated by setup.py.
- timestamp = ''
- if OPTION_SNAPSHOT_BUILD:
- timestamp = get_package_timestamp()
- cmake_cmd.append("-DPYSIDE_SETUP_PY_PACKAGE_TIMESTAMP={}".format(
- timestamp))
+ # Pass package version to CMake, so this string can be
+ # embedded into _config.py file.
+ package_version = get_package_version()
+ cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_VERSION={}".format(
+ package_version))
+
+ # In case if this is a snapshot build, also pass the
+ # timestamp as a separate value, because it is the only
+ # version component that is actually generated by setup.py.
+ timestamp = ''
+ if OPTION_SNAPSHOT_BUILD:
+ timestamp = get_package_timestamp()
+ cmake_cmd.append("-DPACKAGE_SETUP_PY_PACKAGE_TIMESTAMP={}".format(
+ timestamp))
if extension.lower() in ["shiboken2", "pyside2-tools"]:
cmake_cmd.append("-DCMAKE_INSTALL_RPATH_USE_LINK_PATH=yes")
@@ -1129,15 +1110,24 @@ class PysideBuild(_build):
os.chdir(self.script_dir)
def prepare_packages(self):
+ """
+ This will copy all relevant files from the various locations in the "cmake install dir",
+ to the setup tools build dir (which is read from self.build_lib provided by distutils).
+
+ After that setuptools.command.build_py is smart enough to copy everything
+ from the build dir to the install dir (the virtualenv site-packages for example).
+ """
try:
- log.info("Preparing packages...")
+ log.info("\nPreparing setup tools build directory.\n")
vars = {
"site_packages_dir": self.site_packages_dir,
"sources_dir": self.sources_dir,
"install_dir": self.install_dir,
"build_dir": self.build_dir,
"script_dir": self.script_dir,
- "pyside_package_dir": self.pyside_package_dir,
+ "st_build_dir": self.st_build_dir,
+ "cmake_package_name": config.package_name(),
+ "st_package_name": config.package_name(),
"ssl_libs_dir": OPTION_OPENSSL,
"py_version": self.py_version,
"qt_version": self.qtinfo.version,
@@ -1151,6 +1141,12 @@ class PysideBuild(_build):
"qt_qml_dir": self.qtinfo.qml_dir,
"target_arch": self.py_arch,
}
+
+ # Needed for correct file installation in generator build
+ # case.
+ if config.is_internal_shiboken_generator_build():
+ vars['cmake_package_name'] = config.shiboken_module_option_name
+
os.chdir(self.script_dir)
if sys.platform == "win32":
@@ -1170,19 +1166,21 @@ class PysideBuild(_build):
def get_built_pyside_config(self, vars):
# Get config that contains list of built modules, and
# SOVERSIONs of the built libraries.
- pyside_package_dir = vars['pyside_package_dir']
- config_path = os.path.join(pyside_package_dir, "PySide2", "_config.py")
- config = get_python_dict(config_path)
- return config
+ st_build_dir = vars['st_build_dir']
+ config_path = os.path.join(st_build_dir, config.package_name(), "_config.py")
+ temp_config = get_python_dict(config_path)
+ if 'built_modules' not in temp_config:
+ temp_config['built_modules'] = []
+ return temp_config
def is_webengine_built(self, built_modules):
return ('WebEngineWidgets' in built_modules or 'WebEngineCore' in built_modules
or 'WebEngine' in built_modules)
- def prepare_standalone_clang(self, is_win = False):
+ def prepare_standalone_clang(self, is_win=False):
"""
- Copies the libclang library to the pyside package so that
- shiboken executable works.
+ Copies the libclang library to the shiboken2-generator
+ package so that the shiboken executable works.
"""
log.info('Finding path to the libclang shared library.')
cmake_cmd = [
@@ -1205,47 +1203,54 @@ class PysideBuild(_build):
if not clang_lib_path:
raise RuntimeError("Could not find the location of the libclang "
- "library inside the CMake cache file.")
+ "library inside the CMake cache file.")
- target_name = None
if is_win:
# clang_lib_path points to the static import library
# (lib/libclang.lib), whereas we want to copy the shared
# library (bin/libclang.dll).
- clang_lib_path = re.sub(r'lib/libclang.lib$', 'bin/libclang.dll',
- clang_lib_path)
+ clang_lib_path = re.sub(r'lib/libclang.lib$',
+ 'bin/libclang.dll',
+ clang_lib_path)
else:
- if sys.platform != 'darwin' and os.path.islink(clang_lib_path):
- # On Linux, we get "libclang.so" from CMake which is
- # a symlink:
- # libclang.so -> libclang.so.6 -> libclang.so.6.0.
- # shiboken2 links against libclang.so.6. So, we
- # determine the target name by resolving just
- # one symlink (note: os.path.realpath() resolves all).
- target_name = os.readlink(clang_lib_path)
- # We want to resolve any symlink on Linux and macOS, and
- # copy the actual file.
- clang_lib_path = os.path.realpath(clang_lib_path)
-
- if not target_name:
- target_name = os.path.basename(clang_lib_path)
-
- # Path to directory containing libclang.
- clang_lib_dir = os.path.dirname(clang_lib_path)
-
- # The destination will be the package folder near the other
- # extension modules.
- destination_dir = "{}/PySide2".format(os.path.join(self.script_dir,
- 'pyside_package'))
+ # shiboken2 links against libclang.so.6 or a similarly
+ # named library.
+ # If the linked against library is a symlink, resolve
+ # the symlink once (but not all the way to the real
+ # file) on Linux and macOS,
+ # so that we get the path to the "SO version" symlink
+ # (the one used as the install name in the shared library
+ # dependency section).
+ # E.g. On Linux libclang.so -> libclang.so.6 ->
+ # libclang.so.6.0.
+ # "libclang.so.6" is the name we want for the copied file.
+ if os.path.islink(clang_lib_path):
+ link_target = os.readlink(clang_lib_path)
+ if os.path.isabs(link_target):
+ clang_lib_path = link_target
+ else:
+ # link_target is relative, transform to absolute.
+ clang_lib_path = os.path.join(os.path.dirname(clang_lib_path), link_target)
+ clang_lib_path = os.path.abspath(clang_lib_path)
+
+ # The destination will be the shiboken package folder.
+ vars = {}
+ vars['st_build_dir'] = self.st_build_dir
+ vars['st_package_name'] = config.package_name()
+ destination_dir = "{st_build_dir}/{st_package_name}".format(**vars)
+
if os.path.exists(clang_lib_path):
- log.info('Copying libclang shared library {} to the package folder as {}.'.format(
- clang_lib_path, target_name))
basename = os.path.basename(clang_lib_path)
- destination_path = os.path.join(destination_dir, target_name)
+ log.info('Copying libclang shared library {} to the package folder as {}.'.format(
+ clang_lib_path, basename))
+ destination_path = os.path.join(destination_dir, basename)
# Need to modify permissions in case file is not writable
# (a reinstall would cause a permission denied error).
- copyfile(clang_lib_path, destination_path, make_writable_by_owner=True)
+ copyfile(clang_lib_path,
+ destination_path,
+ force_copy_symlink=True,
+ make_writable_by_owner=True)
else:
raise RuntimeError("Error copying libclang library "
"from {} to {}. ".format(
@@ -1265,18 +1270,17 @@ class PysideBuild(_build):
else:
# Add rpath values pointing to $ORIGIN and the
# installed qt lib directory.
- local_rpath = '$ORIGIN/'
- qt_lib_dir = self.qtinfo.libs_dir
+ final_rpath = self.qtinfo.libs_dir
if OPTION_STANDALONE:
- qt_lib_dir = "$ORIGIN/Qt/lib"
- final_rpath = local_rpath + ':' + qt_lib_dir
- cmd = [self._patchelf_path, '--set-rpath', final_rpath, srcpath]
- if run_process(cmd) != 0:
- raise RuntimeError("Error patching rpath in " + srcpath)
+ final_rpath = "$ORIGIN/Qt/lib"
+ override = OPTION_STANDALONE
+ linux_fix_rpaths_for_library(self._patchelf_path, srcpath, final_rpath,
+ override=override)
elif sys.platform == 'darwin':
pyside_libs = [lib for lib in os.listdir(
package_path) if filter_match(lib, ["*.so", "*.dylib"])]
+
def rpath_cmd(srcpath):
final_rpath = ''
# Command line rpath option takes precedence over
@@ -1308,15 +1312,6 @@ class PysideBuild(_build):
"updated rpath (OS/X) in {}.".format(srcpath))
-try:
- with open(os.path.join(setup_script_dir, 'README.rst')) as f:
- README = f.read()
- with open(os.path.join(setup_script_dir, 'CHANGES.rst')) as f:
- CHANGES = f.read()
-except IOError:
- README = CHANGES = ''
-
-
cmd_class_dict = {
'build': PysideBuild,
'build_py': PysideBuildPy,