[pyzo] 32/68: More removing of pyzolib in dev part
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Sep 28 09:47:10 UTC 2016
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch debian/master
in repository pyzo.
commit ec1962ca6d8dd9404d5983d767241af4b59cacae
Author: Almar Klein <almar.klein at gmail.com>
Date: Mon Sep 5 16:10:09 2016 +0200
More removing of pyzolib in dev part
---
README.md | 2 +-
dllutils.py | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
freezeScript.py | 13 ++--
3 files changed, 237 insertions(+), 9 deletions(-)
diff --git a/README.md b/README.md
index 684cb34..29acd87 100644
--- a/README.md
+++ b/README.md
@@ -23,7 +23,7 @@ system (Python 2.4 - 3.x, including Pypy).
### Installation
-Pyzo runs on Python3 and needs pyzolib and Pyside or PyQt4. On a modern
+Pyzo runs on Python3 and needs Pyside or PyQt4. On a modern
OS these should be easy to obtain. One can then install Pyzo with
`sudo python3 -m pip install pyzo`
diff --git a/dllutils.py b/dllutils.py
new file mode 100644
index 0000000..d619889
--- /dev/null
+++ b/dllutils.py
@@ -0,0 +1,231 @@
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012 Almar Klein
+# This module is distributed under the terms of the (new) BSD License.
+
+""" Various utilities to modify Dynamic Link libraries.
+
+Needed to build the Pyzo distro, and it's possible that this
+functionality is needed to fix extension modules after installation in
+a Pyzo distro.
+
+This is a mix of utilities for Windows, Mac and Linux.
+
+"""
+
+import os
+import stat
+import sys
+import subprocess
+import time
+import re
+
+
+_COMMAND_TO_SEARCH_PATH = []
+
+def get_command_to_set_search_path():
+ """ Get the command to change the RPATH of executables and dynamic
+ libraries. Returns None if there is no such command or if it
+ cannot be found.
+ """
+
+ # Check if already computed
+ if _COMMAND_TO_SEARCH_PATH:
+ return _COMMAND_TO_SEARCH_PATH[0]
+
+ # Get name of the utility
+ # In Pyzo it should be present in 'shared'.
+ utilCommand = None
+ if sys.platform.startswith('win'):
+ return
+ if sys.platform.startswith('linux'):
+ utilname = 'patchelf'
+ if sys.platform.startswith('darwin'):
+ utilname = 'install_name_tool'
+ if True:
+ # Try old Pyzo
+ utilCommand = os.path.join(sys.prefix, 'shared', utilname)
+ if not os.path.isfile(utilCommand):
+ utilCommand = utilname
+ # Try new Pyzo / anaconda
+ utilCommand = os.path.join(sys.prefix, 'bin', utilname)
+ if not os.path.isfile(utilCommand):
+ utilCommand = utilname
+ # Test whether it exists
+ try:
+ subprocess.check_output(['which', utilCommand])
+ except Exception:
+ raise RuntimeError('Could not get command (%s) to set search path.' % utilCommand)
+
+ # Store and return
+ _COMMAND_TO_SEARCH_PATH.append(utilCommand)
+ return utilCommand
+
+
+def set_search_path(fname, *args):
+ """ set_search_path(fname, *args)
+ For the given library/executable, set the search path to the
+ relative paths specified in args.
+
+ For Linux: The RPATH is the path to search for its dependencies.
+ http://enchildfone.wordpress.com/2010/03/23/a-description-of-rpath-origin-ld_library_path-and-portable-linux-binaries/
+
+ For Mac: We use the @rpath identifier to get similar behavior to
+ Linux. But each dependency must be specified. To realize this, we
+ need to check for each dependency whether it is on one of te given
+ search paths.
+
+ For Windows: not supported in any way. Windows searches next to the
+ library and then in system paths and PATH.
+
+ """
+
+ # Prepare
+ args = [arg.lstrip('/') for arg in args if arg]
+ args = [arg for arg in args if arg != '.'] # Because we add empty dir anyway
+ args.append('') # make libs search next to themselves
+ command = get_command_to_set_search_path()
+
+ if sys.platform.startswith('linux'):
+ # Create search path value
+ rpath = ':'.join( ['$ORIGIN/'+arg for arg in args] )
+ # Modify rpath using a call to patchelf utility
+ cmd = [command, '--set-rpath', rpath, fname]
+ subprocess.check_call(cmd)
+ print('Set RPATH for %r' % os.path.basename(fname))
+ #print('Set RPATH for %r: %r' % (os.path.basename(fname), rpath))
+
+ elif sys.platform.startswith('darwin'):
+ # ensure write permissions
+ mode = os.stat(fname).st_mode
+ if not (mode & stat.S_IWUSR):
+ os.chmod(fname, mode | stat.S_IWUSR)
+ # let the file itself know its place (simpyl on rpath)
+ name = os.path.basename(fname)
+ subprocess.call(('install_name_tool', '-id', '@rpath/'+name, fname))
+ # find the references: call otool -L on the file
+ otool = subprocess.Popen(('otool', '-L', fname),
+ stdout = subprocess.PIPE)
+ references = otool.stdout.readlines()[1:]
+
+ # Replace each reference
+ rereferencedlibs = []
+ for reference in references:
+ # find the actual referenced file name
+ referencedFile = reference.decode().strip().split()[0]
+ if referencedFile.startswith('@'):
+ continue # the referencedFile is already a relative path
+ # Get lib name
+ _, name = os.path.split(referencedFile)
+ if name.lower() == 'python':
+ name = 'libpython' # Rename Python lib on Mac
+ # see if we provided the referenced file
+ potentiallibs = [os.path.join(os.path.dirname(fname), arg, name)
+ for arg in args]
+ # if so, change the reference and rpath
+ if any([os.path.isfile(p) for p in potentiallibs]):
+ subprocess.call(('install_name_tool', '-change',
+ referencedFile, '@rpath/'+name, fname))
+ for arg in args:
+ mac_add_rpath(fname, '@loader_path/' + arg)
+ mac_add_rpath(fname, '@executable_path/') # use libpython next to exe
+ rereferencedlibs.append(name)
+ if rereferencedlibs:
+ print('Replaced refs for "%s": %s' %
+ (os.path.basename(fname), ', '.join(rereferencedlibs)) )
+
+ elif sys.platform.startswith('win'):
+ raise RuntimeError('Windows has no way of setting the search path on a library or exe.')
+ else:
+ raise RuntimeError('Do not know how to set search path of library or exe on %s' % sys.platform)
+
+
+def mac_add_rpath(fname, rpath):
+ """ mac_add_rpath(fname, rpath)
+ Set the rpath for a Mac library or executble. If the rpath is already
+ registered, it is ignored.
+ """
+ cmd = ['install_name_tool', '-add_rpath', rpath, fname]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ while p.poll() is None:
+ time.sleep(0.01)
+ if p.returncode:
+ msg = p.stdout.read().decode('utf-8')
+ if 'would duplicate path' in msg:
+ pass # Ignore t
+ else:
+ raise RuntimeError('Could not set rpath: ' + msg)
+
+
+def remove_CRT_dependencies(dirname, recurse=True):
+ """ remove_CRT_dependencies(path, recurse=True)
+ Check all .dll and .pyd files in the given directory (and its
+ subdirectories if recurse is True), removing the dependency on the
+ Windows C runtime from the embedded manifest.
+ """
+ dllExt = ['.dll', '.pyd']
+ for entry in os.listdir(dirname):
+ p = os.path.join(dirname, entry)
+ if recurse and os.path.isdir(p):
+ remove_CRT_dependencies(p, recurse)
+ elif os.path.isfile(p) and os.path.splitext(p)[1].lower() in dllExt:
+ remove_CRT_dependency(p)
+
+
+def remove_CRT_dependency(filename):
+ """ remove_CRT_dependency(filename)
+ Modify the embedded manifest of a Windows dll (or pyd file),
+ such that it no longer depends on the Windows C runtime.
+ In effect, the dll will fall back to using the C runtime that
+ the executable depends on (and has loaded in memory).
+
+ This function is not necessary for dll's and pyd's that come with
+ Python, because these are build without the CRT dependencies for a
+ while. However, some third party packages (e.g. PySide) do have
+ these dependencies, and they need to be removed in order to work
+ on a system that does not have the C-runtime installed.
+
+ Based on this diff by C. Gohlke:
+ http://bugs.python.org/file15113/msvc9compiler_stripruntimes_regexp2.diff
+ See discussion at: http://bugs.python.org/issue4120
+
+ """
+ if 'QtCore' in filename:
+ 1/0
+
+ # Read the whole file
+ with open(filename, 'rb') as f:
+ try:
+ bb = f.read()
+ except IOError:
+ #raise IOError('Could not read %s'%filename)
+ print('Warning: could not read %s'%filename)
+ return
+
+ # Remove assemblyIdentity tag
+ # This code is different from that in python's distutils/msvc9compiler.py
+ # by removing re.DOTALL and replaceing the second DOT with "(.|\n|\r)",
+ # which means that the first DOT cannot contain newlines. Would we not do
+ # this, the match is too greedy (and causes tk85.dll to break).
+ pattern = r"""<assemblyIdentity.*?name=("|')Microsoft\."""\
+ r"""VC\d{2}\.CRT("|')(.|\n|\r)*?(/>|</assemblyIdentity>)"""
+ pattern = re.compile(pattern.encode('ascii'))
+ bb, hasMatch = _replacePatternWithSpaces(pattern, bb)
+ if hasMatch:
+ # Remove dependentAssembly tag if it's empty
+ pattern = "<dependentAssembly>\s*</dependentAssembly>".encode('ascii')
+ bb, hasMatch = _replacePatternWithSpaces(pattern, bb)
+ # Write back
+ with open(filename, "wb") as f:
+ f.write(bb)
+ print('Removed embedded MSVCR dependency for: %s' % filename)
+
+
+def _replacePatternWithSpaces(pattern, bb):
+ match = re.search(pattern, bb)
+ if match is not None:
+ L = match.end() - match.start()
+ bb = re.sub(pattern, b" "*L, bb)
+ return bb, True
+ else:
+ return bb, False
+
diff --git a/freezeScript.py b/freezeScript.py
index 843ba43..a07354a 100755
--- a/freezeScript.py
+++ b/freezeScript.py
@@ -89,9 +89,6 @@ else:
excludes.extend(PyQtModules)
includes = PySideModules
-# # For Pyzolib dependencies
-includes.extend(['pyzolib.paths', 'pyzolib.path', 'pyzolib.ssdf', 'pyzolib.interpreters'])
-
## Freeze
# Clear first
@@ -246,7 +243,7 @@ with open(os.path.join(distDir, '_settings', 'README.txt'), 'wb') as file:
# Set search path of dynamic libraries
-from pyzolib import dllutils
+import dllutils
if sys.platform.startswith('linux'):
# Exe
dllutils.set_search_path(os.path.join(distDir, 'pyzo'), '', 'lib')
@@ -280,8 +277,8 @@ if sys.platform.startswith('linux'):
# QApplication.setLibraryPaths([]), it does not replace it.
# See issue 138 and issue 198.
with open(os.path.join(distDir, 'qt.conf'), 'wb') as file:
- import pyzolib.qt
- file.write(pyzolib.qt.DEFAULT_QT_CONF_TEXT.encode('utf-8'))
+ from pyzo.util import qt
+ file.write(qt.DEFAULT_QT_CONF_TEXT.encode('utf-8'))
#file.write("[Paths]\nPlugins = '.'\n".encode('utf-8'))
# Write about experimental feature
@@ -357,8 +354,8 @@ if applicationBundle:
#Write qt.conf in the Resources dir
with open(os.path.join(resourcesDir, 'qt.conf'), 'wb') as file:
- import pyzolib.qt
- file.write(pyzolib.qt.DEFAULT_QT_CONF_TEXT.encode('utf-8'))
+ from pyzo.util import qt
+ file.write(qt.DEFAULT_QT_CONF_TEXT.encode('utf-8'))
#Copy the Info.plist file
shutil.copy(baseDir+'Info.plist',contentsDir+'Info.plist')
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/pyzo.git
More information about the debian-science-commits
mailing list