diff options
Diffstat (limited to 'build_scripts/main.py')
-rw-r--r-- | build_scripts/main.py | 448 |
1 files changed, 228 insertions, 220 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py index b64d6f1a9..cdc6dce7e 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 * @@ -49,14 +50,17 @@ setup_script_dir = os.getcwd() build_scripts_dir = os.path.join(setup_script_dir, 'build_scripts') setup_py_path = os.path.join(setup_script_dir, "setup.py") +start_time = int(time.time()) + +def elapsed(): + return int(time.time()) - start_time + @memoize def get_package_timestamp(): """ In a Coin CI build the returned timestamp will be the Coin integration id timestamp. For regular builds it's just the current timestamp or a user provided one.""" - if OPTION_PACKAGE_TIMESTAMP: - return OPTION_PACKAGE_TIMESTAMP - return int(time.time()) + return OPTION_PACKAGE_TIMESTAMP if OPTION_PACKAGE_TIMESTAMP else start_time @memoize def get_package_version(): @@ -90,15 +94,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 +108,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 +118,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 +127,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 = r'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: @@ -205,20 +201,16 @@ if not os.path.exists(OPTION_CMAKE): print("'{}' does not exist.".format(OPTION_CMAKE)) sys.exit(1) -if sys.platform == "win32": - if OPTION_MAKESPEC is None: - OPTION_MAKESPEC = "msvc" - if not OPTION_MAKESPEC in ["msvc", "mingw"]: - print("Invalid option --make-spec. Available values are {}".format( - ["msvc", "mingw"])) - sys.exit(1) -else: - if OPTION_MAKESPEC is None: - OPTION_MAKESPEC = "make" - if not OPTION_MAKESPEC in ["make"]: - print("Invalid option --make-spec. Available values are {}".format( - ["make"])) - sys.exit(1) +# First element is default +available_mkspecs = ["msvc", "mingw", "ninja"] if sys.platform == "win32" else ["make", "ninja"] + +if OPTION_MAKESPEC is None: + OPTION_MAKESPEC = available_mkspecs[0] + +if not OPTION_MAKESPEC in available_mkspecs: + print('Invalid option --make-spec "{}". Available values are {}'.format( + OPTION_MAKESPEC, available_mkspecs)) + sys.exit(1) if OPTION_JOBS: if sys.platform == 'win32' and OPTION_NO_JOM: @@ -293,8 +285,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,27 +295,22 @@ 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)) + log.info("Removing {}".format(d)) try: rmtree(d) 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 @@ -360,7 +346,7 @@ class PysideInstall(_install): def run(self): _install.run(self) - log.info('*** Install completed') + print('*** Install completed ({}s)'.format(elapsed())) class PysideDevelop(_develop): @@ -389,26 +375,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): @@ -512,6 +487,9 @@ class PysideBuild(_build): elif OPTION_MAKESPEC == "mingw": make_name = "mingw32-make" make_generator = "MinGW Makefiles" + elif OPTION_MAKESPEC == "ninja": + make_name = "ninja" + make_generator = "Ninja" else: raise DistutilsSetupError( "Invalid option --make-spec.") @@ -539,10 +517,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 +636,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 +665,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 +681,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.") + print('*** Build completed ({}s)'.format(elapsed())) + + 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 +745,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 +785,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 @@ -941,8 +913,17 @@ class PysideBuild(_build): module_src_dir = os.path.join(self.sources_dir, extension) # Build module - cmake_cmd = [ - OPTION_CMAKE, + cmake_cmd = [OPTION_CMAKE] + if OPTION_QUIET: + # Pass a special custom option, to allow printing a lot less information when doing + # a quiet build. + cmake_cmd.append('-DQUIET_BUILD=1') + if self.make_generator == "Unix Makefiles": + # Hide progress messages for each built source file. + # Doesn't seem to work if set within the cmake files themselves. + cmake_cmd.append('-DCMAKE_RULE_MESSAGES=0') + + cmake_cmd += [ "-G", self.make_generator, "-DBUILD_TESTS={}".format(self.build_tests), "-DQt5Help_DIR={}".format(self.qtinfo.docs_dir), @@ -953,6 +934,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 +1006,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") @@ -1120,7 +1112,9 @@ class PysideBuild(_build): log.info("Waiting 1 second, to ensure installation is " "successful...") time.sleep(1) - if run_process([self.make_path, "install/fast"]) != 0: + # ninja: error: unknown target 'install/fast' + target = 'install/fast' if self.make_generator != 'Ninja' else 'install' + if run_process([self.make_path, target]) != 0: raise DistutilsSetupError("Error pseudo installing {}".format( extension)) else: @@ -1129,15 +1123,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 +1154,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 +1179,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 +1216,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 +1283,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 @@ -1304,17 +1321,8 @@ class PysideBuild(_build): if not os.path.exists(srcpath): continue rpath_cmd(srcpath) - print("Patched rpath to '$ORIGIN/' (Linux) or " - "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 = '' + log.info("Patched rpath to '$ORIGIN/' (Linux) or " + "updated rpath (OS/X) in {}.".format(srcpath)) cmd_class_dict = { |