Esempio n. 1
0
def executePostProcessingResources(manifest, onefile):
    """Adding Windows resources to the binary.

    Used for both onefile and not onefile binary, potentially two times.
    """
    result_filename = OutputDirectories.getResultFullpath(onefile=onefile)

    # TODO: Maybe make these different for onefile and not onefile.
    if (Options.shallAskForWindowsAdminRights()
            or Options.shallAskForWindowsUIAccessRights()):
        if manifest is None:
            manifest = getDefaultWindowsExecutableManifest()

        if Options.shallAskForWindowsAdminRights():
            manifest.addUacAdmin()

        if Options.shallAskForWindowsUIAccessRights():
            manifest.addUacUiAccess()

    if manifest is not None:
        manifest.addResourceToFile(result_filename,
                                   logger=postprocessing_logger)

    if (Options.getWindowsVersionInfoStrings()
            or Options.getWindowsProductVersion()
            or Options.getWindowsFileVersion()):
        version_resources.update(
            addVersionInfoResource(
                string_values=Options.getWindowsVersionInfoStrings(),
                product_version=Options.getWindowsProductVersion(),
                file_version=Options.getWindowsFileVersion(),
                file_date=(0, 0),
                is_exe=not Options.shallMakeModule(),
                result_filename=result_filename,
                logger=postprocessing_logger,
            ))

    # Attach icons from template file if given.
    template_exe = Options.getWindowsIconExecutablePath()
    if template_exe is not None:
        res_copied = copyResourcesFromFileToFile(
            template_exe,
            target_filename=result_filename,
            resource_kinds=(RT_ICON, RT_GROUP_ICON),
        )

        if res_copied == 0:
            postprocessing_logger.warning(
                "The specified icon template executable %r didn't contain anything to copy."
                % template_exe)
        else:
            postprocessing_logger.warning("Copied %d icon resources from %r." %
                                          (res_copied, template_exe))
    else:
        _addWindowsIconFromIcons(onefile=onefile)
Esempio n. 2
0
def getPEFileInformation(filename):
    """Return the PE file information of a Windows EXE or DLL

    Args:
        filename - The file to be investigated.

    Notes:
        Use of this is obviously only for Windows, although the module
        will exist on other platforms too. We use the system version
        of pefile in preference, but have an inline copy as a fallback
        too.
    """

    pefile = importFromInlineCopy("pefile", must_exist=True)

    pe = pefile.PE(filename)

    # This is the information we use from the file.
    extracted = {}
    extracted["DLLs"] = []

    for imported_module in getattr(pe, "DIRECTORY_ENTRY_IMPORT", ()):
        extracted["DLLs"].append(imported_module.dll.decode())

    pe_type2arch = {
        pefile.OPTIONAL_HEADER_MAGIC_PE: False,
        pefile.OPTIONAL_HEADER_MAGIC_PE_PLUS: True,
    }

    if pe.PE_TYPE not in pe_type2arch:
        # Support your architecture, e.g. ARM if necessary.
        raise NuitkaAssumptionError("Unknown PE file architecture", filename,
                                    pe.PE_TYPE, pe_type2arch)

    extracted["AMD64"] = pe_type2arch[pe.PE_TYPE]

    python_is_64bit = getArchitecture() == "x86_64"
    if extracted["AMD64"] is not python_is_64bit:
        postprocessing_logger.warning(
            "Python %s bits with %s bits dependencies in '%s'" % (
                ("32" if python_is_64bit else "64"),
                ("64" if extracted["AMD64"] else "32"),
                filename,
            ))

    return extracted
Esempio n. 3
0
def executePostProcessing():
    # These is a bunch of stuff to consider, pylint: disable=too-many-branches

    result_filename = OutputDirectories.getResultFullpath()

    if not os.path.exists(result_filename):
        postprocessing_logger.sysexit(
            "Error, scons failed to create the expected file %r. " %
            result_filename)

    if isWin32Windows():
        if not Options.shallMakeModule():
            needs_manifest = False
            manifest = None

            if python_version < 0x300:
                # Copy the Windows manifest from the CPython binary to the created
                # executable, so it finds "MSCRT.DLL". This is needed for Python2
                # only, for Python3 newer MSVC doesn't hide the C runtime.
                manifest = getWindowsExecutableManifest(sys.executable)

                if manifest is not None:
                    needs_manifest = True

            if (Options.shallAskForWindowsAdminRights()
                    or Options.shallAskForWindowsUIAccessRights()):
                needs_manifest = True

                if manifest is None:
                    manifest = getDefaultWindowsExecutableManifest()

                if Options.shallAskForWindowsAdminRights():
                    manifest.addUacAdmin()

                if Options.shallAskForWindowsUIAccessRights():
                    manifest.addUacUiAccess()

            if needs_manifest:
                manifest.addResourceToFile(result_filename,
                                           logger=postprocessing_logger)

        if (Options.getWindowsVersionInfoStrings()
                or Options.getWindowsProductVersion()
                or Options.getWindowsFileVersion()):
            version_resources.update(
                addVersionInfoResource(
                    string_values=Options.getWindowsVersionInfoStrings(),
                    product_version=Options.getWindowsProductVersion(),
                    file_version=Options.getWindowsFileVersion(),
                    file_date=(0, 0),
                    is_exe=not Options.shallMakeModule(),
                    result_filename=result_filename,
                    logger=postprocessing_logger,
                ))

        source_dir = OutputDirectories.getSourceDirectoryPath()

        # Attach the binary blob as a Windows resource.
        addResourceToFile(
            target_filename=result_filename,
            data=getFileContents(getConstantBlobFilename(source_dir), "rb"),
            resource_kind=RT_RCDATA,
            res_name=3,
            lang_id=0,
            logger=postprocessing_logger,
        )

        # Attach icons from template file if given.
        template_exe = Options.getWindowsIconExecutablePath()
        if template_exe is not None:
            res_copied = copyResourcesFromFileToFile(
                template_exe,
                target_filename=result_filename,
                resource_kinds=(RT_ICON, RT_GROUP_ICON),
            )

            if res_copied == 0:
                postprocessing_logger.warning(
                    "The specified icon template executable %r didn't contain anything to copy."
                    % template_exe)
            else:
                postprocessing_logger.warning(
                    "Copied %d icon resources from %r." %
                    (res_copied, template_exe))
        else:
            addWindowsIconFromIcons()

    # On macOS, we update the executable path for searching the "libpython"
    # library.
    if (getOS() == "Darwin" and not Options.shallMakeModule()
            and not Options.shallUseStaticLibPython()):
        python_abi_version = python_version_str + getPythonABI()
        python_dll_filename = "libpython" + python_abi_version + ".dylib"
        python_lib_path = os.path.join(sys.prefix, "lib")

        # Note: For CPython and potentially others, the rpath for the Python
        # library needs to be set.

        callInstallNameTool(
            filename=result_filename,
            mapping=(
                (
                    python_dll_filename,
                    os.path.join(python_lib_path, python_dll_filename),
                ),
                (
                    "@rpath/Python3.framework/Versions/%s/Python3" %
                    python_version_str,
                    os.path.join(python_lib_path, python_dll_filename),
                ),
            ),
            rpath=python_lib_path,
        )

    # Modules should not be executable, but Scons creates them like it, fix
    # it up here.
    if not isWin32Windows() and Options.shallMakeModule():
        removeFileExecutablePermission(result_filename)

    if isWin32Windows() and Options.shallMakeModule():
        candidate = os.path.join(
            os.path.dirname(result_filename),
            "lib" + os.path.basename(result_filename)[:-4] + ".a",
        )

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

    if isWin32Windows() and Options.shallTreatUninstalledPython():
        shutil.copy(getTargetPythonDLLPath(),
                    os.path.dirname(result_filename) or ".")