Exemple #1
0
def main():
    parser = OptionParser()

    _options, positional_args = parser.parse_args()

    if not positional_args:
        sys.exit("No DLLs given.")

    for filename in positional_args:
        my_print("Filename: %s" % filename)
        my_print("Version Information: %s" % getWindowsDLLVersion(filename))

        my_print("SXS information (manifests):")
        sxs = getSxsFromDLL(filename=filename, with_data=True)
        if sxs:
            my_print(sxs)

        my_print("DLLs recursively dependended (depends.exe):")

        with TimerReport(
                message="Finding dependencies for %s took %%.2f seconds" %
                filename):
            r = detectBinaryPathDLLsWindowsDependencyWalker(
                is_main_executable=False,
                source_dir="notexist",
                original_dir=os.path.dirname(filename),
                binary_filename=filename,
                package_name=None,
                use_cache=False,
                update_cache=False,
            )

            for dll_filename in sorted(r):
                my_print("   %s" % dll_filename)

            my_print("Total: %d" % len(r))
Exemple #2
0
def copyUsedDLLs(source_dir, dist_dir, standalone_entry_points):
    # This is terribly complex, because we check the list of used DLLs
    # trying to avoid duplicates, and detecting errors with them not
    # being binary identical, so we can report them. And then of course
    # we also need to handle OS specifics.
    # pylint: disable=too-many-branches,too-many-locals,too-many-statements

    used_dlls = detectUsedDLLs(
        source_dir=source_dir,
        standalone_entry_points=standalone_entry_points,
        use_cache=not Options.shallNotUseDependsExeCachedResults()
        and not Options.getWindowsDependencyTool() == "depends.exe",
        update_cache=not Options.shallNotStoreDependsExeCachedResults()
        and not Options.getWindowsDependencyTool() == "depends.exe",
    )

    removed_dlls = set()
    warned_about = set()

    # Fist make checks and remove some.
    for dll_filename1, sources1 in tuple(iterItems(used_dlls)):
        if dll_filename1 in removed_dlls:
            continue

        for dll_filename2, sources2 in tuple(iterItems(used_dlls)):
            if dll_filename1 == dll_filename2:
                continue

            if dll_filename2 in removed_dlls:
                continue

            # Colliding basenames are an issue to us.
            if os.path.basename(dll_filename1) != os.path.basename(
                    dll_filename2):
                continue

            # May already have been removed earlier
            if dll_filename1 not in used_dlls:
                continue

            if dll_filename2 not in used_dlls:
                continue

            dll_name = os.path.basename(dll_filename1)

            if Options.isShowInclusion():
                inclusion_logger.info(
                    """Colliding DLL names for %s, checking identity of \
'%s' <-> '%s'.""" % (dll_name, dll_filename1, dll_filename2))

            # Check that if a DLL has the same name, if it's identical, then it's easy.
            if haveSameFileContents(dll_filename1, dll_filename2):
                del used_dlls[dll_filename2]
                removed_dlls.add(dll_filename2)

                continue

            # For Win32 we can check out file versions.
            if Utils.isWin32Windows():
                dll_version1 = getWindowsDLLVersion(dll_filename1)
                dll_version2 = getWindowsDLLVersion(dll_filename2)

                if dll_version2 < dll_version1:
                    del used_dlls[dll_filename2]
                    removed_dlls.add(dll_filename2)

                    solved = True
                elif dll_version1 < dll_version2:
                    del used_dlls[dll_filename1]
                    removed_dlls.add(dll_filename1)

                    solved = True
                else:
                    solved = False

                if solved:
                    if dll_name not in warned_about and dll_name not in ms_runtime_dlls:
                        warned_about.add(dll_name)

                        inclusion_logger.warning(
                            "Conflicting DLLs for '%s' in your installation, newest file version used, hoping for the best."
                            % dll_name)

                    continue

            # So we have conflicting DLLs, in which case we do report the fact.
            inclusion_logger.warning("""\
Ignoring non-identical DLLs for '%s'.
%s used by:
   %s
different from
%s used by
   %s""" % (
                dll_name,
                dll_filename1,
                "\n   ".join(sources1),
                dll_filename2,
                "\n   ".join(sources2),
            ))

            del used_dlls[dll_filename2]
            removed_dlls.add(dll_filename2)

    dll_map = []

    for dll_filename, sources in iterItems(used_dlls):
        dll_name = os.path.basename(dll_filename)

        target_path = os.path.join(dist_dir, dll_name)

        shutil.copyfile(dll_filename, target_path)

        dll_map.append((dll_filename, dll_name))

        if Options.isShowInclusion():
            inclusion_logger.info(
                "Included used shared library '%s' (used by %s)." %
                (dll_filename, ", ".join(sources)))

    if Utils.getOS() == "Darwin":
        # For macOS, the binary and the DLLs needs to be changed to reflect
        # the relative DLL location in the ".dist" folder.
        for standalone_entry_point in standalone_entry_points:
            fixupBinaryDLLPathsMacOS(
                binary_filename=standalone_entry_point.dest_path,
                dll_map=dll_map,
                original_location=standalone_entry_point.source_path,
            )

        for original_path, dll_filename in dll_map:
            fixupBinaryDLLPathsMacOS(
                binary_filename=os.path.join(dist_dir, dll_filename),
                dll_map=dll_map,
                original_location=original_path,
            )

        # Remove code signature from CPython installed library
        candidate = os.path.join(
            dist_dir,
            "Python",
        )

        if os.path.exists(candidate):
            removeMacOSCodeSignature(candidate)

    # Remove rpath settings.
    if Utils.getOS() in ("Linux", "Darwin"):
        # For Linux, the "rpath" of libraries may be an issue and must be
        # removed.
        if Utils.getOS() == "Darwin":
            start = 0
        else:
            start = 1

        for standalone_entry_point in standalone_entry_points[start:]:
            removeSharedLibraryRPATH(standalone_entry_point.dest_path)

        for _original_path, dll_filename in dll_map:
            removeSharedLibraryRPATH(os.path.join(dist_dir, dll_filename))

    if Utils.isWin32Windows():
        if python_version < 0x300:
            # For Win32, we might have to remove SXS paths
            for standalone_entry_point in standalone_entry_points[1:]:
                removeSxsFromDLL(standalone_entry_point.dest_path)

            for _original_path, dll_filename in dll_map:
                removeSxsFromDLL(os.path.join(dist_dir, dll_filename))
Exemple #3
0
def copyUsedDLLs(source_dir, dist_dir, standalone_entry_points):
    # This is terribly complex, because we check the list of used DLLs
    # trying to avoid duplicates, and detecting errors with them not
    # being binary identical, so we can report them. And then of course
    # we also need to handle OS specifics.
    # pylint: disable=too-many-branches,too-many-locals,too-many-statements

    used_dlls = detectUsedDLLs(source_dir, standalone_entry_points)

    removed_dlls = set()

    # Fist make checks and remove some.
    for dll_filename1, sources1 in tuple(iterItems(used_dlls)):
        if dll_filename1 in removed_dlls:
            continue

        for dll_filename2, sources2 in tuple(iterItems(used_dlls)):
            if dll_filename1 == dll_filename2:
                continue

            if dll_filename2 in removed_dlls:
                continue

            # Colliding basenames are an issue to us.
            if os.path.basename(dll_filename1) != os.path.basename(
                    dll_filename2):
                continue

            # May already have been removed earlier
            if dll_filename1 not in used_dlls:
                continue

            if dll_filename2 not in used_dlls:
                continue

            dll_name = os.path.basename(dll_filename1)

            if Options.isShowInclusion():
                info("""Colliding DLL names for %s, checking identity of \
'%s' <-> '%s'.""" % (dll_name, dll_filename1, dll_filename2))

            # Check that if a DLL has the same name, if it's identical,
            # happens at least for OSC and Fedora 20.
            import filecmp

            if filecmp.cmp(dll_filename1, dll_filename2):
                del used_dlls[dll_filename2]
                removed_dlls.add(dll_filename2)

                continue

            # For Win32 we can check out file versions.
            if Utils.isWin32Windows():
                dll_version1 = getWindowsDLLVersion(dll_filename1)
                dll_version2 = getWindowsDLLVersion(dll_filename2)

                if dll_version2 < dll_version1:
                    del used_dlls[dll_filename2]
                    removed_dlls.add(dll_filename2)

                    solved = True
                elif dll_version1 < dll_version2:
                    del used_dlls[dll_filename1]
                    removed_dlls.add(dll_filename1)

                    solved = True
                else:
                    solved = False

                if solved:
                    warning(
                        "Ignoring conflicting DLLs for '%s' and using newest file version."
                        % dll_name)
                    continue

            # So we have conflicting DLLs, in which case we do not proceed.
            warning("""Ignoring non-identical DLLs for '%s'.
%s used by:
   %s
different from
%s used by
   %s""" % (
                dll_name,
                dll_filename1,
                "\n   ".join(sources1),
                dll_filename2,
                "\n   ".join(sources2),
            ))

            del used_dlls[dll_filename2]
            removed_dlls.add(dll_filename2)

    dll_map = []

    for dll_filename, sources in iterItems(used_dlls):
        dll_name = os.path.basename(dll_filename)

        target_path = os.path.join(dist_dir, dll_name)

        shutil.copyfile(dll_filename, target_path)

        dll_map.append((dll_filename, dll_name))

        if Options.isShowInclusion():
            info("Included used shared library '%s' (used by %s)." %
                 (dll_filename, ", ".join(sources)))

    if Utils.getOS() == "Darwin":
        # For macOS, the binary and the DLLs needs to be changed to reflect
        # the relative DLL location in the ".dist" folder.
        for standalone_entry_point in standalone_entry_points:
            fixupBinaryDLLPaths(
                binary_filename=standalone_entry_point[1],
                is_exe=standalone_entry_point is standalone_entry_points[0],
                dll_map=dll_map,
            )

        for _original_path, dll_filename in dll_map:
            fixupBinaryDLLPaths(
                binary_filename=os.path.join(dist_dir, dll_filename),
                is_exe=False,
                dll_map=dll_map,
            )

    if Utils.getOS() == "Linux":
        # For Linux, the "rpath" of libraries may be an issue and must be
        # removed.
        for standalone_entry_point in standalone_entry_points[1:]:
            removeSharedLibraryRPATH(standalone_entry_point[1])

        for _original_path, dll_filename in dll_map:
            removeSharedLibraryRPATH(os.path.join(dist_dir, dll_filename))
    elif Utils.isWin32Windows():
        if python_version < 300:
            # For Win32, we might have to remove SXS paths
            for standalone_entry_point in standalone_entry_points[1:]:
                removeSxsFromDLL(standalone_entry_point[1])

            for _original_path, dll_filename in dll_map:
                removeSxsFromDLL(os.path.join(dist_dir, dll_filename))
def main():
    parser = OptionParser()

    parser.add_option(
        "--verbose",
        action="store_true",
        dest="verbose",
        default=False,
        help="""\
Be verbose in output. Default is %default.""",
    )

    parser.add_option(
        "--pefile",
        action="store_true",
        dest="pefile",
        default=False,
        help="""\
Use pefile dependencies. Default is %default.""",
    )

    options, positional_args = parser.parse_args()

    if not positional_args:
        sys.exit("No DLLs given.")

    for filename in positional_args:
        print("Filename:", filename)
        print("Version Information:", getWindowsDLLVersion(filename))
        print("DLLs directly dependended (pefile):",
              getPEFileInformation(filename))

        print("SXS information (manifests):")
        sxs = getSxsFromDLL(filename=filename, with_data=True)
        if sxs:
            print(sxs)

        print("DLLs recursively dependended (pefile):")

        if options.pefile:
            with TimerReport(
                    message="Finding dependencies for %s took %%.2f seconds" %
                    filename):
                from nuitka import Options

                Options.options.dependency_tool = "pefile"

                r = detectBinaryPathDLLsWindowsPE(
                    is_main_executable=False,
                    source_dir="notexist",
                    original_dir=os.path.dirname(filename),
                    binary_filename=filename,
                    package_name=None,
                    use_cache=False,
                    update_cache=True,
                )
                Options.options.dependency_tool = "depends.exe"

                for dll_filename in sorted(r):
                    print("  ", dll_filename)

                print("Total: %d" % len(r))

        print("DLLs recursively dependended (depends.exe):")

        with TimerReport(
                message="Finding dependencies for %s took %%.2f seconds" %
                filename):
            r = detectBinaryPathDLLsWindowsDependencyWalker(
                is_main_executable=False,
                source_dir="notexist",
                original_dir=os.path.dirname(filename),
                binary_filename=filename,
                package_name=None,
                use_cache=False,
                update_cache=False,
            )

            for dll_filename in sorted(r):
                print("  ", dll_filename)

            print("Total: %d" % len(r))
Exemple #5
0
def _removeDuplicateDlls(used_dlls):
    # Many things to consider, pylint: disable=too-many-branches
    removed_dlls = set()
    warned_about = set()

    # Identical DLLs are interesting for DLL resolution on macOS at least.
    duplicate_dlls = {}

    # Fist make checks and remove some, in loops we copy the items so we can remove
    # the used_dll list freely.
    for dll_filename1, (_package_name1,
                        sources1) in tuple(iterItems(used_dlls)):
        if dll_filename1 in removed_dlls:
            continue

        for dll_filename2, (_package_name1,
                            sources2) in tuple(iterItems(used_dlls)):
            if dll_filename1 == dll_filename2:
                continue

            if dll_filename2 in removed_dlls:
                continue

            # Colliding basenames are an issue to us.
            if os.path.basename(dll_filename1) != os.path.basename(
                    dll_filename2):
                continue

            # May already have been removed earlier
            if dll_filename1 not in used_dlls:
                continue

            if dll_filename2 not in used_dlls:
                continue

            dll_name = os.path.basename(dll_filename1)

            if Options.isShowInclusion():
                inclusion_logger.info(
                    """Colliding DLL names for %s, checking identity of \
'%s' <-> '%s'.""" % (dll_name, dll_filename1, dll_filename2))

            # Check that if a DLL has the same name, if it's identical, then it's easy.
            if haveSameFileContents(dll_filename1, dll_filename2):
                del used_dlls[dll_filename2]
                removed_dlls.add(dll_filename2)

                duplicate_dlls.setdefault(dll_filename1,
                                          []).append(dll_filename2)
                duplicate_dlls.setdefault(dll_filename2,
                                          []).append(dll_filename1)

                continue

            # For Win32 we can check out file versions.
            if Utils.isWin32Windows():
                dll_version1 = getWindowsDLLVersion(dll_filename1)
                dll_version2 = getWindowsDLLVersion(dll_filename2)

                if dll_version2 < dll_version1:
                    del used_dlls[dll_filename2]
                    removed_dlls.add(dll_filename2)

                    solved = True
                elif dll_version1 < dll_version2:
                    del used_dlls[dll_filename1]
                    removed_dlls.add(dll_filename1)

                    solved = True
                else:
                    solved = False

                if solved:
                    if dll_name not in warned_about and dll_name not in ms_runtime_dlls:
                        warned_about.add(dll_name)

                        inclusion_logger.warning(
                            "Conflicting DLLs for '%s' in your installation, newest file version used, hoping for the best."
                            % dll_name)

                    continue

            # So we have conflicting DLLs, in which case we do report the fact.
            inclusion_logger.warning("""\
Ignoring non-identical DLLs for '%s'.
%s used by:
   %s
different from
%s used by
   %s""" % (
                dll_name,
                dll_filename1,
                "\n   ".join(sources1),
                dll_filename2,
                "\n   ".join(sources2),
            ))

            del used_dlls[dll_filename2]
            removed_dlls.add(dll_filename2)

    return duplicate_dlls