Beispiel #1
0
def selectAssemblies(pth, manifest=None):
    """
    Return a binary's dependent assemblies files that should be included.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if not os.path.isfile(pth):
        pth = check_extract_from_egg(pth)[0][0]
    if manifest:
        _depNames = set([dep.name for dep in manifest.dependentAssemblies])
    for assembly in getAssemblies(pth):
        if seen.get(assembly.getid().upper(), 0):
            continue
        if manifest and not assembly.name in _depNames:
            # Add assembly as dependency to our final output exe's manifest
            logger.info("Adding %s to dependent assemblies "
                        "of final executable", assembly.name)
            manifest.dependentAssemblies.append(assembly)
            _depNames.add(assembly.name)
        if not dylib.include_library(assembly.name):
            logger.debug("Skipping assembly %s", assembly.getid())
            continue
        if assembly.optional:
            logger.debug("Skipping optional assembly %s", assembly.getid())
            continue
        files = assembly.find_files()
        if files:
            seen[assembly.getid().upper()] = 1
            for fn in files:
                fname, fext = os.path.splitext(fn)
                if fext.lower() == ".manifest":
                    nm = assembly.name + fext
                else:
                    nm = os.path.basename(fn)
                ftocnm = nm
                if assembly.language not in (None, "", "*", "neutral"):
                    ftocnm = os.path.join(assembly.getlanguage(),
                                          ftocnm)
                nm, ftocnm, fn = [item.encode(sys.getfilesystemencoding())
                                  for item in
                                  (nm,
                                   ftocnm,
                                   fn)]
                if not seen.get(fn.upper(), 0):
                    logger.debug("Adding %s", ftocnm)
                    seen[nm.upper()] = 1
                    seen[fn.upper()] = 1
                    rv.append((ftocnm, fn))
                else:
                    #logger.info("skipping %s part of assembly %s dependency of %s",
                    #            ftocnm, assembly.name, pth)
                    pass
        else:
            logger.error("Assembly %s not found", assembly.getid())
    return rv
Beispiel #2
0
def selectAssemblies(pth, manifest=None):
    """
    Return a binary's dependent assemblies files that should be included.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if not os.path.isfile(pth):
        pth = check_extract_from_egg(pth)[0][0]
    if manifest:
        _depNames = set([dep.name for dep in manifest.dependentAssemblies])
    for assembly in getAssemblies(pth):
        if seen.get(assembly.getid().upper(), 0):
            continue
        if manifest and not assembly.name in _depNames:
            # Add assembly as dependency to our final output exe's manifest
            logger.info(
                "Adding %s to dependent assemblies "
                "of final executable", assembly.name)
            manifest.dependentAssemblies.append(assembly)
            _depNames.add(assembly.name)
        if not dylib.include_library(assembly.name):
            logger.debug("Skipping assembly %s", assembly.getid())
            continue
        if assembly.optional:
            logger.debug("Skipping optional assembly %s", assembly.getid())
            continue
        files = assembly.find_files()
        if files:
            seen[assembly.getid().upper()] = 1
            for fn in files:
                fname, fext = os.path.splitext(fn)
                if fext.lower() == ".manifest":
                    nm = assembly.name + fext
                else:
                    nm = os.path.basename(fn)
                ftocnm = nm
                if assembly.language not in (None, "", "*", "neutral"):
                    ftocnm = os.path.join(assembly.getlanguage(), ftocnm)
                nm, ftocnm, fn = [
                    item.encode(sys.getfilesystemencoding())
                    for item in (nm, ftocnm, fn)
                ]
                if not seen.get(fn.upper(), 0):
                    logger.debug("Adding %s", ftocnm)
                    seen[nm.upper()] = 1
                    seen[fn.upper()] = 1
                    rv.append((ftocnm, fn))
                else:
                    #logger.info("skipping %s part of assembly %s dependency of %s",
                    #            ftocnm, assembly.name, pth)
                    pass
        else:
            logger.error("Assembly %s not found", assembly.getid())
    return rv
Beispiel #3
0
def selectImports(pth, xtrapath=None):
    """
    Return the dependencies of a binary that should be included.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if xtrapath is None:
        xtrapath = [os.path.dirname(pth)]
    else:
        assert isinstance(xtrapath, list)
        xtrapath = [os.path.dirname(pth)] + xtrapath  # make a copy
    dlls = getImports(pth)
    for lib in dlls:
        if lib.upper() in seen:
            continue
        if not compat.is_win:
            # all other platforms
            npth = lib
            lib = os.path.basename(lib)
        else:
            # plain win case
            npth = getfullnameof(lib, xtrapath)

        # now npth is a candidate lib if found
        # check again for excludes but with regex FIXME: split the list
        if npth:
            candidatelib = npth
        else:
            candidatelib = lib

        if not dylib.include_library(candidatelib):
            if (candidatelib.find('libpython') < 0
                    and candidatelib.find('Python.framework') < 0):
                # skip libs not containing (libpython or Python.framework)
                if npth.upper() not in seen:
                    logger.debug("Skipping %s dependency of %s", lib,
                                 os.path.basename(pth))
                continue
            else:
                pass

        if npth:
            if npth.upper() not in seen:
                logger.debug("Adding %s dependency of %s from %s", lib,
                             os.path.basename(pth), npth)
                rv.append((lib, npth))
        else:
            # Don't spew out false warnings on win 10 and UCRT (see issue
            # #1566).
            if not (compat.is_win_10 and lib.startswith("api-ms-win-crt")):
                logger.warning("lib not found: %s dependency of %s", lib, pth)

    return rv
Beispiel #4
0
def selectImports(pth, xtrapath=None):
    """
    Return the dependencies of a binary that should be included.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if xtrapath is None:
        xtrapath = [os.path.dirname(pth)]
    else:
        assert isinstance(xtrapath, list)
        xtrapath = [os.path.dirname(pth)] + xtrapath  # make a copy
    dlls = getImports(pth)
    for lib in dlls:
        if seen.get(lib.upper(), 0):
            continue
        if not is_win and not is_cygwin:
            # all other platforms
            npth = lib
            lib = os.path.basename(lib)
        else:
            # plain win case
            npth = getfullnameof(lib, xtrapath)

        # now npth is a candidate lib if found
        # check again for excludes but with regex FIXME: split the list
        if npth:
            candidatelib = npth
        else:
            candidatelib = lib

        if not dylib.include_library(candidatelib):
            if (candidatelib.find('libpython') < 0 and
               candidatelib.find('Python.framework') < 0):
                # skip libs not containing (libpython or Python.framework)
                if not seen.get(npth.upper(), 0):
                    logger.debug("Skipping %s dependency of %s",
                                 lib, os.path.basename(pth))
                continue
            else:
                pass

        if npth:
            if not seen.get(npth.upper(), 0):
                logger.debug("Adding %s dependency of %s",
                             lib, os.path.basename(pth))
                rv.append((lib, npth))
        else:
            logger.error("lib not found: %s dependency of %s", lib, pth)

    return rv
Beispiel #5
0
def getAssemblyFiles(pth, manifest=None, redirects=None):
    """
    Find all assemblies that are dependencies of the given binary and return the files
    that make up the assemblies as (name, fullpath) tuples.

    If a WinManifest object is passed as `manifest`, also updates that manifest to
    reference the returned assemblies. This is done only to update the built app's .exe
    with the dependencies of python.exe

    If a list is passed as `redirects`, and binding redirects in policy files are
    applied when searching for assemblies, BindingRedirect objects are appended to this
    list.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if manifest:
        _depNames = set(dep.name for dep in manifest.dependentAssemblies)
    for assembly in getAssemblies(pth):
        if assembly.getid().upper() in seen:
            continue
        if manifest and assembly.name not in _depNames:
            # Add assembly as dependency to our final output exe's manifest
            logger.info(
                "Adding %s to dependent assemblies "
                "of final executable\n  required by %s", assembly.name, pth)
            manifest.dependentAssemblies.append(assembly)
            _depNames.add(assembly.name)
        if not dylib.include_library(assembly.name):
            logger.debug("Skipping assembly %s", assembly.getid())
            continue
        if assembly.optional:
            logger.debug("Skipping optional assembly %s", assembly.getid())
            continue

        from PyInstaller.config import CONF
        if CONF.get("win_no_prefer_redirects"):
            files = assembly.find_files()
        else:
            files = []
        if not len(files):
            # If no files were found, it may be the case that the required version
            # of the assembly is not installed, and the policy file is redirecting it
            # to a newer version. So, we collect the newer version instead.
            files = assembly.find_files(ignore_policies=False)
            if len(files) and redirects is not None:
                # New version was found, old version was not. Add a redirect in the
                # app configuration
                old_version = assembly.version
                new_version = assembly.get_policy_redirect()
                logger.info("Adding redirect %s version %s -> %s",
                            assembly.name, old_version, new_version)
                redirects.append(
                    BindingRedirect(
                        name=assembly.name,
                        language=assembly.language,
                        arch=assembly.processorArchitecture,
                        publicKeyToken=assembly.publicKeyToken,
                        oldVersion=old_version,
                        newVersion=new_version,
                    ))

        if files:
            seen.add(assembly.getid().upper())
            for fn in files:
                fname, fext = os.path.splitext(fn)
                if fext.lower() == ".manifest":
                    nm = assembly.name + fext
                else:
                    nm = os.path.basename(fn)
                ftocnm = nm
                if assembly.language not in (None, "", "*", "neutral"):
                    ftocnm = os.path.join(assembly.getlanguage(), ftocnm)
                nm, ftocnm, fn = [
                    item.encode(sys.getfilesystemencoding())
                    for item in (nm, ftocnm, fn)
                ]
                if fn.upper() not in seen:
                    logger.debug("Adding %s", ftocnm)
                    seen.add(nm.upper())
                    seen.add(fn.upper())
                    rv.append((ftocnm, fn))
                else:
                    #logger.info("skipping %s part of assembly %s dependency of %s",
                    #            ftocnm, assembly.name, pth)
                    pass
        else:
            logger.error("Assembly %s not found", assembly.getid())

    # Convert items in list from 'bytes' type to 'str' type.
    # NOTE: With Python 3 we somehow get type 'bytes' and it
    #       then causes other issues and failures with PyInstaller.
    new_rv = []
    for item in rv:
        a = item[0].decode('ascii')
        b = item[1].decode('ascii')
        new_rv.append((a, b))
    rv = new_rv

    return rv
Beispiel #6
0
def _resolveCtypesImports(cbinaries):
    """
    Completes ctypes BINARY entries for modules with their full path.

    Input is a list of c-binary-names (as found by `scan_code_instruction_for_ctypes`). Output is a list of tuples
    ready to be appended to the ``binaries`` of a modules.

    This function temporarily extents PATH, LD_LIBRARY_PATH or DYLD_LIBRARY_PATH (depending on the plattform) by
    CONF['pathex'] so shared libs will be search there, too.

    Example:
    >>> _resolveCtypesImports(['libgs.so'])
    [(libgs.so', ''/usr/lib/libgs.so', 'BINARY')]
    """
    from ctypes.util import find_library

    from PyInstaller.config import CONF

    if compat.is_unix:
        envvar = "LD_LIBRARY_PATH"
    elif compat.is_darwin:
        envvar = "DYLD_LIBRARY_PATH"
    else:
        envvar = "PATH"

    def _setPaths():
        path = os.pathsep.join(CONF['pathex'])
        old = compat.getenv(envvar)
        if old is not None:
            path = os.pathsep.join((path, old))
        compat.setenv(envvar, path)
        return old

    def _restorePaths(old):
        if old is None:
            compat.unsetenv(envvar)
        else:
            compat.setenv(envvar, old)

    ret = []

    # Try to locate the shared library on the disk. This is done by calling ctypes.util.find_library with
    # ImportTracker's local paths temporarily prepended to the library search paths (and restored after the call).
    old = _setPaths()
    for cbin in cbinaries:
        try:
            # There is an issue with find_library() where it can run into errors trying to locate the library. See
            # #5734.
            cpath = find_library(os.path.splitext(cbin)[0])
        except FileNotFoundError:
            # In these cases, find_library() should return None.
            cpath = None
        if compat.is_unix:
            # CAVEAT: find_library() is not the correct function. ctype's documentation says that it is meant to resolve
            # only the filename (as a *compiler* does) not the full path. Anyway, it works well enough on Windows and
            # Mac OS. On Linux, we need to implement more code to find out the full path.
            if cpath is None:
                cpath = cbin
            # "man ld.so" says that we should first search LD_LIBRARY_PATH and then the ldcache.
            for d in compat.getenv(envvar, '').split(os.pathsep):
                if os.path.isfile(os.path.join(d, cpath)):
                    cpath = os.path.join(d, cpath)
                    break
            else:
                if LDCONFIG_CACHE is None:
                    load_ldconfig_cache()
                if cpath in LDCONFIG_CACHE:
                    cpath = LDCONFIG_CACHE[cpath]
                    assert os.path.isfile(cpath)
                else:
                    cpath = None
        if cpath is None:
            # Skip warning message if cbin (basename of library) is ignored. This prevents messages like:
            # 'W: library kernel32.dll required via ctypes not found'
            if not include_library(cbin):
                continue
            logger.warning("Library %s required via ctypes not found", cbin)
        else:
            if not include_library(cpath):
                continue
            ret.append((cbin, cpath, "BINARY"))
    _restorePaths(old)
    return ret
Beispiel #7
0
def getAssemblyFiles(pth, manifest=None, redirects=None):
    """
    Find all assemblies that are dependencies of the given binary and return the files
    that make up the assemblies as (name, fullpath) tuples.

    If a WinManifest object is passed as `manifest`, also updates that manifest to
    reference the returned assemblies. This is done only to update the built app's .exe
    with the dependencies of python.exe

    If a list is passed as `redirects`, and binding redirects in policy files are
    applied when searching for assemblies, BindingRedirect objects are appended to this
    list.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if manifest:
        _depNames = set(dep.name for dep in manifest.dependentAssemblies)
    for assembly in getAssemblies(pth):
        if assembly.getid().upper() in seen:
            continue
        if manifest and assembly.name not in _depNames:
            # Add assembly as dependency to our final output exe's manifest
            logger.info("Adding %s to dependent assemblies "
                        "of final executable\n  required by %s",
                        assembly.name, pth)
            manifest.dependentAssemblies.append(assembly)
            _depNames.add(assembly.name)
        if not dylib.include_library(assembly.name):
            logger.debug("Skipping assembly %s", assembly.getid())
            continue
        if assembly.optional:
            logger.debug("Skipping optional assembly %s", assembly.getid())
            continue

        from ..config import CONF
        if CONF.get("win_no_prefer_redirects"):
            files = assembly.find_files()
        else:
            files = []
        if not len(files):
            # If no files were found, it may be the case that the required version
            # of the assembly is not installed, and the policy file is redirecting it
            # to a newer version. So, we collect the newer version instead.
            files = assembly.find_files(ignore_policies=False)
            if len(files) and redirects is not None:
                # New version was found, old version was not. Add a redirect in the
                # app configuration
                old_version = assembly.version
                new_version = assembly.get_policy_redirect()
                logger.info("Adding redirect %s version %s -> %s",
                            assembly.name, old_version, new_version)
                redirects.append(BindingRedirect(
                    name=assembly.name,
                    language=assembly.language,
                    arch=assembly.processorArchitecture,
                    publicKeyToken=assembly.publicKeyToken,
                    oldVersion=old_version,
                    newVersion=new_version,
                ))

        if files:
            seen.add(assembly.getid().upper())
            for fn in files:
                fname, fext = os.path.splitext(fn)
                if fext.lower() == ".manifest":
                    nm = assembly.name + fext
                else:
                    nm = os.path.basename(fn)
                ftocnm = nm
                if assembly.language not in (None, "", "*", "neutral"):
                    ftocnm = os.path.join(assembly.getlanguage(),
                                          ftocnm)
                nm, ftocnm, fn = [item.encode(sys.getfilesystemencoding())
                                  for item in
                                  (nm,
                                   ftocnm,
                                   fn)]
                if fn.upper() not in seen:
                    logger.debug("Adding %s", ftocnm)
                    seen.add(nm.upper())
                    seen.add(fn.upper())
                    rv.append((ftocnm, fn))
                else:
                    #logger.info("skipping %s part of assembly %s dependency of %s",
                    #            ftocnm, assembly.name, pth)
                    pass
        else:
            logger.error("Assembly %s not found", assembly.getid())

    # Convert items in list from 'bytes' type to 'str' type.
    # NOTE: With Python 3 we somehow get type 'bytes' and it
    #       then causes other issues and failures with PyInstaller.
    new_rv = []
    for item in rv:
        a = item[0].decode('ascii')
        b = item[1].decode('ascii')
        new_rv.append((a, b))
    rv = new_rv

    return rv
Beispiel #8
0
def selectAssemblies(pth, manifest=None):
    """
    Return a binary's dependent assemblies files that should be included.

    Return a list of pairs (name, fullpath)
    """
    rv = []
    if manifest:
        _depNames = set([dep.name for dep in manifest.dependentAssemblies])
    for assembly in getAssemblies(pth):
        if seen.get(assembly.getid().upper(), 0):
            continue
        if manifest and not assembly.name in _depNames:
            # Add assembly as dependency to our final output exe's manifest
            logger.info("Adding %s to dependent assemblies "
                        "of final executable\n  required by %s",
                        assembly.name, pth)
            manifest.dependentAssemblies.append(assembly)
            _depNames.add(assembly.name)
        if not dylib.include_library(assembly.name):
            logger.debug("Skipping assembly %s", assembly.getid())
            continue
        if assembly.optional:
            logger.debug("Skipping optional assembly %s", assembly.getid())
            continue
        files = assembly.find_files()
        if files:
            seen[assembly.getid().upper()] = 1
            for fn in files:
                fname, fext = os.path.splitext(fn)
                if fext.lower() == ".manifest":
                    nm = assembly.name + fext
                else:
                    nm = os.path.basename(fn)
                ftocnm = nm
                if assembly.language not in (None, "", "*", "neutral"):
                    ftocnm = os.path.join(assembly.getlanguage(),
                                          ftocnm)
                nm, ftocnm, fn = [item.encode(sys.getfilesystemencoding())
                                  for item in
                                  (nm,
                                   ftocnm,
                                   fn)]
                if not seen.get(fn.upper(), 0):
                    logger.debug("Adding %s", ftocnm)
                    seen[nm.upper()] = 1
                    seen[fn.upper()] = 1
                    rv.append((ftocnm, fn))
                else:
                    #logger.info("skipping %s part of assembly %s dependency of %s",
                    #            ftocnm, assembly.name, pth)
                    pass
        else:
            logger.error("Assembly %s not found", assembly.getid())

    # Convert items in list from 'bytes' type to 'str' type.
    # NOTE: With Python 3 we somehow get type 'bytes' and it
    #       then causes other issues and failures with PyInstaller.
    new_rv = []
    for item in rv:
        a = item[0].decode('ascii')
        b = item[1].decode('ascii')
        new_rv.append((a, b))
    rv = new_rv

    return rv