def runScons(main_module, quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements options = { "name" : os.path.basename( getTreeFilenameWithSuffix(main_module, "") ), "result_name" : getResultBasepath(main_module), "source_dir" : getSourceDirectoryPath(main_module), "debug_mode" : _asBoolStr(Options.isDebug()), "python_debug" : _asBoolStr(Options.isPythonDebug()), "unstripped_mode" : _asBoolStr(Options.isUnstripped()), "module_mode" : _asBoolStr(Options.shallMakeModule()), "full_compat" : _asBoolStr(Options.isFullCompat()), "experimental" : ','.join(Options.getExperimentalIndications()), "trace_mode" : _asBoolStr(Options.shallTraceExecution()), "python_version" : python_version_str, "target_arch" : Utils.getArchitecture(), "python_prefix" : sys.prefix, "nuitka_src" : SconsInterface.getSconsDataPath(), "nuitka_cache" : getCacheDir(), "module_count" : "%d" % ( 1 + \ len(ModuleRegistry.getDoneUserModules()) + \ len(ModuleRegistry.getUncompiledNonTechnicalModules()) ) } if not Options.shallMakeModule(): options["result_exe"] = getResultFullpath(main_module) # Ask Scons to cache on Windows, except where the directory is thrown # away. On non-Windows you can should use ccache instead. if not Options.isRemoveBuildDir() and Utils.getOS() == "Windows": options["cache_mode"] = "true" if Options.isLto(): options["lto_mode"] = "true" if Options.shallDisableConsoleWindow(): options["win_disable_console"] = "true" if Options.isStandaloneMode(): options["standalone_mode"] = "true" if not Options.isStandaloneMode() and \ not Options.shallMakeModule() and \ isUninstalledPython(): options["uninstalled_python"] = "true" if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules()) ) if Options.isShowScons(): options["show_scons"] = "true" if Options.isMingw64(): options["mingw_mode"] = "true" if Options.getMsvcVersion(): msvc_version = Options.getMsvcVersion() msvc_version = msvc_version.replace("exp", "Exp") if '.' not in msvc_version: msvc_version += ".0" options["msvc_version"] = msvc_version if Options.isClang(): options["clang_mode"] = "true" if Options.getIconPath(): options["icon_path"] = Options.getIconPath() if Options.isProfile(): options["profile_mode"] = "true" if "no_warnings" in getPythonFlags(): options["no_python_warnings"] = "true" if python_version < 300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = "true" if python_version < 300 and (sys.flags.division_warning or sys.flags.py3k_warning): options["python_sysflag_division_warning"] = "true" if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = "true" if int(os.environ.get("NUITKA_SITE_FLAG", "no_site" in Options.getPythonFlags())): options["python_sysflag_no_site"] = "true" if "trace_imports" in Options.getPythonFlags(): options["python_sysflag_verbose"] = "true" if python_version < 300 and sys.flags.unicode: options["python_sysflag_unicode"] = "true" if python_version >= 370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = "true" abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags return SconsInterface.runScons(options, quiet), options
def executePostProcessing(result_filename): if not os.path.exists(result_filename): sys.exit("Error, scons failed to create the expected file '%s'. " % result_filename) if isWin32Windows(): # 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. if python_version < 300 and not Options.shallMakeModule(): copyResourcesFromFileToFile( sys.executable, target_filename=result_filename, resource_kind=RT_MANIFEST, ) assert os.path.exists(result_filename) # Attach the binary blob as a Windows resource. addResourceToFile( target_filename=result_filename, data=ConstantCodes.stream_data.getBytes(), resource_kind=RT_RCDATA, res_name=3, lang_id=0, ) # On macOS, we update the executable path for searching the "libpython" # library. if (getOS() == "Darwin" and not Options.shallMakeModule() and not Options.shallUseStaticLibPython()): python_version_str = ".".join(str(s) for s in sys.version_info[0:2]) python_abi_version = python_version_str + getPythonABI() python_dll_filename = "libpython" + python_abi_version + ".dylib" python_lib_path = os.path.join(sys.prefix, "lib") if os.path.exists(os.path.join(sys.prefix, "conda-meta")): callInstallNameToolAddRPath(result_filename, python_lib_path) callInstallNameTool( filename=result_filename, mapping=(( python_dll_filename, os.path.join(python_lib_path, python_dll_filename), ), ), ) # Modules should not be executable, but Scons creates them like it, fix # it up here. if not isWin32Windows() and Options.shallMakeModule(): old_stat = os.stat(result_filename) mode = old_stat.st_mode mode &= ~(stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) if mode != old_stat.st_mode: os.chmod(result_filename, mode) 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 ".")
def _getSystemStaticLibPythonPath(): # Return driven function with many cases, pylint: disable=too-many-branches,too-many-return-statements sys_prefix = getSystemPrefixPath() python_abi_version = python_version_str + getPythonABI() if isNuitkaPython(): # Nuitka Python has this. if isWin32Windows(): return os.path.join( sys_prefix, "libs", "python" + python_abi_version.replace(".", "") + ".lib", ) else: return os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".a", ) if isWin32Windows(): candidates = [ # Anaconda has this. os.path.join( sys_prefix, "libs", "libpython" + python_abi_version.replace(".", "") + ".dll.a", ), # MSYS2 mingw64 Python has this. os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".dll.a", ), ] for candidate in candidates: if os.path.exists(candidate): return candidate else: candidate = os.path.join( sys_prefix, "lib", "libpython" + python_abi_version + ".a" ) if os.path.exists(candidate): return candidate # For Python2 this works. TODO: Figure out Debian and Python3. if ( python_version < 0x300 and isDebianPackagePython() and isDebianSuitableForStaticLinking() ): candidate = locateStaticLinkLibrary("python" + python_abi_version) else: candidate = None if candidate is not None and os.path.exists(candidate): # Also check libz, can be missing if not locateStaticLinkLibrary("z"): general.warning( "Error, missing libz-dev installation needed for static lib-python." ) return candidate # This is not necessarily only for Python3 on Debian, but maybe others as well, # but that's what's been tested. if python_version >= 0x300 and isDebianPackagePython() and isDebianBasedLinux(): try: import sysconfig candidate = os.path.join( sysconfig.get_config_var("LIBPL"), "libpython" + python_abi_version + "-pic.a", ) if os.path.exists(candidate): return candidate except ImportError: # Cannot detect this properly for Python 2.6, but we don't care much # about that anyway. pass return None
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 ".")
def runSconsBackend(quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=False), "source_dir": OutputDirectories.getSourceDirectoryPath(), "nuitka_python": asBoolStr(isNuitkaPython()), "debug_mode": asBoolStr(Options.is_debug), "python_debug": asBoolStr(Options.isPythonDebug()), "module_mode": asBoolStr(Options.shallMakeModule()), "full_compat": asBoolStr(Options.is_fullcompat), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "python_version": python_version_str, "target_arch": getArchitecture(), "python_prefix": getDirectoryRealPath(getSystemPrefixPath()), "nuitka_src": SconsInterface.getSconsDataPath(), "module_count": "%d" % ( 1 + len(ModuleRegistry.getDoneModules()) + len(ModuleRegistry.getUncompiledNonTechnicalModules()) ), } if Options.isLowMemory(): options["low_memory"] = asBoolStr(True) if not Options.shallMakeModule(): options["result_exe"] = OutputDirectories.getResultFullpath(onefile=False) main_module = ModuleRegistry.getRootTopModule() assert main_module.isMainModule() main_module_name = main_module.getFullName() if main_module_name != "__main__": options["main_module_name"] = main_module_name if Options.shallUseStaticLibPython(): options["static_libpython"] = getSystemStaticLibPythonPath() if isDebianPackagePython(): options["debian_python"] = asBoolStr(True) if isMSYS2MingwPython(): options["msys2_mingw_python"] = asBoolStr(True) if isAnacondaPython(): options["anaconda_python"] = asBoolStr(True) if isApplePython(): options["apple_python"] = asBoolStr(True) if isPyenvPython(): options["pyenv_python"] = asBoolStr(True) if Options.isStandaloneMode(): options["standalone_mode"] = asBoolStr(True) if Options.isOnefileMode(): options["onefile_mode"] = asBoolStr(True) if Options.isOnefileTempDirMode(): options["onefile_temp_mode"] = asBoolStr(True) if Options.getForcedStdoutPath(): options["forced_stdout_path"] = Options.getForcedStdoutPath() if Options.getForcedStderrPath(): options["forced_stderr_path"] = Options.getForcedStderrPath() if Options.shallTreatUninstalledPython(): options["uninstalled_python"] = asBoolStr(True) if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules()) ) if Options.isProfile(): options["profile_mode"] = asBoolStr(True) if hasPythonFlagNoWarnings(): options["no_python_warnings"] = asBoolStr(True) if hasPythonFlagNoAsserts(): options["python_sysflag_optimize"] = asBoolStr(True) if python_version < 0x300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = asBoolStr(True) if python_version < 0x300 and ( sys.flags.division_warning or sys.flags.py3k_warning ): options["python_sysflag_division_warning"] = asBoolStr(True) if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = asBoolStr(True) if int(os.environ.get("NUITKA_NOSITE_FLAG", Options.hasPythonFlagNoSite())): options["python_sysflag_no_site"] = asBoolStr(True) if Options.hasPythonFlagTraceImports(): options["python_sysflag_verbose"] = asBoolStr(True) if Options.hasPythonFlagNoRandomization(): options["python_sysflag_no_randomization"] = asBoolStr(True) if python_version < 0x300 and sys.flags.unicode: options["python_sysflag_unicode"] = asBoolStr(True) if python_version >= 0x370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = asBoolStr(True) if hasPythonFlagUnbuffered(): options["python_sysflag_unbuffered"] = asBoolStr(True) abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags if Options.shallMakeModule(): options["module_suffix"] = getSharedLibrarySuffix(preferred=True) SconsInterface.setCommonOptions(options) if Options.shallCreatePgoInput(): options["pgo_mode"] = "python" result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ) if not result: return result, options # Need to make it usable before executing it. executePostProcessing() _runPythonPgoBinary() return True, options # Need to restart compilation from scratch here. if Options.isPgoMode(): # For C level PGO, we have a 2 pass system. TODO: Make it more global for onefile # and standalone mode proper support, which might need data files to be # there, which currently are not yet there, so it won't run. if Options.isPgoMode(): options["pgo_mode"] = "generate" result = SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ) if not result: return result, options # Need to make it usable before executing it. executePostProcessing() _runCPgoBinary() options["pgo_mode"] = "use" result = ( SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ), options, ) if options.get("pgo_mode") == "use" and _wasMsvcMode(): _deleteMsvcPGOFiles(pgo_mode="use") return result
def executePostProcessing(): """Postprocessing of the resulting binary. These are in part required steps, not usable after failure. """ result_filename = OutputDirectories.getResultFullpath(onefile=False) 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(): 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) else: manifest = None executePostProcessingResources(manifest=manifest, onefile=False) 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, ) # On macOS, we update the executable path for searching the "libpython" # library. if (isMacOS() 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), ), ), id_path=None, rpath=python_lib_path, ) if Options.shallCreateAppBundle(): createPlistInfoFile(logger=postprocessing_logger, onefile=False) # 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) # Might have to create a CMD file, potentially with debugger run. if Options.shallCreateCmdFileForExecution(): dll_directory = getExternalUsePath( os.path.dirname(getTargetPythonDLLPath())) cmd_filename = OutputDirectories.getResultRunFilename(onefile=False) cmd_contents = """ @echo off rem This script was created by Nuitka to execute '%(exe_filename)s' with Python DLL being found. set PATH=%(dll_directory)s;%%PATH%% set PYTHONHOME=%(dll_directory)s %(debugger_call)s"%%~dp0.\\%(exe_filename)s" %%* """ % { "debugger_call": (" ".join(wrapCommandForDebuggerForExec()) + " ") if Options.shallRunInDebugger() else "", "dll_directory": dll_directory, "exe_filename": os.path.basename(result_filename), } putTextFileContents(cmd_filename, cmd_contents) # Create a ".pyi" file for created modules if Options.shallMakeModule() and Options.shallCreatePyiFile(): pyi_filename = OutputDirectories.getResultBasepath() + ".pyi" putTextFileContents( filename=pyi_filename, contents="""\ # This file was generated by Nuitka and describes the types of the # created shared library. # At this time it lists only the imports made and can be used by the # tools that bundle libraries, including Nuitka itself. For instance # standalone mode usage of the created library will need it. # In the future, this will also contain type information for values # in the module, so IDEs will use this. Therefore please include it # when you make software releases of the extension module that it # describes. %(imports)s # This is not Python source even if it looks so. Make it clear for # now. This was decided by PEP 484 designers. __name__ = ... """ % { "imports": "\n".join("import %s" % module_name for module_name in getImportedNames()) }, )
def runSconsBackend(quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=False), "source_dir": OutputDirectories.getSourceDirectoryPath(), "debug_mode": asBoolStr(Options.is_debug), "python_debug": asBoolStr(Options.isPythonDebug()), "unstripped_mode": asBoolStr(Options.isUnstripped()), "module_mode": asBoolStr(Options.shallMakeModule()), "full_compat": asBoolStr(Options.is_fullcompat), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "python_version": python_version_str, "target_arch": Utils.getArchitecture(), "python_prefix": getDirectoryRealPath(sys.prefix), "nuitka_src": SconsInterface.getSconsDataPath(), "module_count": "%d" % ( 1 + len(ModuleRegistry.getDoneModules()) + len(ModuleRegistry.getUncompiledNonTechnicalModules()) ), } if not Options.shallMakeModule(): options["result_exe"] = OutputDirectories.getResultFullpath(onefile=False) if Options.shallUseStaticLibPython(): options["static_libpython"] = asBoolStr(True) if Options.isStandaloneMode(): options["standalone_mode"] = asBoolStr(True) if Options.isOnefileMode(): options["onefile_mode"] = asBoolStr(True) if Options.isWindowsOnefileTempDirMode(): options["onefile_temp_mode"] = asBoolStr(True) if Options.getForcedStdoutPath(): options["forced_stdout_path"] = Options.getForcedStdoutPath() if Options.getForcedStderrPath(): options["forced_stderr_path"] = Options.getForcedStderrPath() if Options.shallTreatUninstalledPython(): options["uninstalled_python"] = asBoolStr(True) if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules()) ) if Utils.getOS() == "Windows": options["noelf_mode"] = asBoolStr(True) if Options.isProfile(): options["profile_mode"] = asBoolStr(True) if "no_warnings" in getPythonFlags(): options["no_python_warnings"] = asBoolStr(True) if "no_asserts" in getPythonFlags(): options["python_sysflag_optimize"] = asBoolStr(True) if python_version < 0x300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = asBoolStr(True) if python_version < 0x300 and ( sys.flags.division_warning or sys.flags.py3k_warning ): options["python_sysflag_division_warning"] = asBoolStr(True) if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = asBoolStr(True) if int(os.environ.get("NUITKA_SITE_FLAG", Options.hasPythonFlagNoSite())): options["python_sysflag_no_site"] = asBoolStr(True) if "trace_imports" in Options.getPythonFlags(): options["python_sysflag_verbose"] = asBoolStr(True) if "no_randomization" in Options.getPythonFlags(): options["python_sysflag_no_randomization"] = asBoolStr(True) if python_version < 0x300 and sys.flags.unicode: options["python_sysflag_unicode"] = asBoolStr(True) if python_version >= 0x370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = asBoolStr(True) abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags if Options.shallMakeModule(): options["module_suffix"] = getSharedLibrarySuffix(preferred=True) SconsInterface.setCommonOptions(options) return ( SconsInterface.runScons( options=options, quiet=quiet, scons_filename="Backend.scons" ), options, )
def executePostProcessing(): """Postprocessing of the resulting binary. These are in part required steps, not usable after failure. """ result_filename = OutputDirectories.getResultFullpath(onefile=False) 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(): 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) else: manifest = None executePostProcessingResources(manifest=manifest, onefile=False) 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, ) # 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 ".")
def runScons(main_module, quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements options = { "name": os.path.basename(getTreeFilenameWithSuffix(main_module, "")), "result_name": getResultBasepath(main_module), "source_dir": getSourceDirectoryPath(main_module), "debug_mode": _asBoolStr(Options.isDebug()), "python_debug": _asBoolStr(Options.isPythonDebug()), "unstripped_mode": _asBoolStr(Options.isUnstripped()), "module_mode": _asBoolStr(Options.shallMakeModule()), "full_compat": _asBoolStr(Options.isFullCompat()), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": _asBoolStr(Options.shallTraceExecution()), "python_version": python_version_str, "target_arch": Utils.getArchitecture(), "python_prefix": sys.prefix, "nuitka_src": SconsInterface.getSconsDataPath(), "nuitka_cache": getCacheDir(), "module_count": "%d" % ( 1 + len(ModuleRegistry.getDoneUserModules()) + len(ModuleRegistry.getUncompiledNonTechnicalModules()) ), } if not Options.shallMakeModule(): options["result_exe"] = getResultFullpath(main_module) # Ask Scons to cache on Windows, except where the directory is thrown # away. On non-Windows you can should use ccache instead. if not Options.isRemoveBuildDir() and Utils.getOS() == "Windows": options["cache_mode"] = "true" if Options.isLto(): options["lto_mode"] = "true" # For AnaConda default to trying static lib python library, which # normally is just not available or if it is even unusable. if "Anaconda" in sys.version: options["static_libpython"] = "true" if Options.shallDisableConsoleWindow(): options["win_disable_console"] = "true" if Options.isStandaloneMode(): options["standalone_mode"] = "true" if ( not Options.isStandaloneMode() and not Options.shallMakeModule() and isUninstalledPython() ): options["uninstalled_python"] = "true" if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules()) ) if Options.isShowScons(): options["show_scons"] = "true" if Options.isMingw64(): options["mingw_mode"] = "true" if Options.getMsvcVersion(): msvc_version = Options.getMsvcVersion() msvc_version = msvc_version.replace("exp", "Exp") if "." not in msvc_version: msvc_version += ".0" options["msvc_version"] = msvc_version if Options.isClang(): options["clang_mode"] = "true" if Options.getIconPath(): options["icon_path"] = Options.getIconPath() if Options.isProfile(): options["profile_mode"] = "true" if "no_warnings" in getPythonFlags(): options["no_python_warnings"] = "true" if "no_asserts" in getPythonFlags(): options["python_sysflag_optimize"] = "true" if python_version < 300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = "true" if python_version < 300 and (sys.flags.division_warning or sys.flags.py3k_warning): options["python_sysflag_division_warning"] = "true" if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = "true" if int(os.environ.get("NUITKA_SITE_FLAG", "no_site" in Options.getPythonFlags())): options["python_sysflag_no_site"] = "true" if "trace_imports" in Options.getPythonFlags(): options["python_sysflag_verbose"] = "true" if python_version < 300 and sys.flags.unicode: options["python_sysflag_unicode"] = "true" if python_version >= 370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = "true" abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags return SconsInterface.runScons(options, quiet), options
def runSconsBackend(quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches and statements, # pylint: disable=too-many-branches,too-many-statements asBoolStr = SconsInterface.asBoolStr options = { "result_name": OutputDirectories.getResultBasepath(onefile=False), "source_dir": OutputDirectories.getSourceDirectoryPath(), "debug_mode": asBoolStr(Options.is_debug), "python_debug": asBoolStr(Options.isPythonDebug()), "unstripped_mode": asBoolStr(Options.isUnstripped()), "module_mode": asBoolStr(Options.shallMakeModule()), "full_compat": asBoolStr(Options.is_fullcompat), "experimental": ",".join(Options.getExperimentalIndications()), "trace_mode": asBoolStr(Options.shallTraceExecution()), "python_version": python_version_str, "target_arch": Utils.getArchitecture(), "python_prefix": getDirectoryRealPath(sys.prefix), "nuitka_src": SconsInterface.getSconsDataPath(), "module_count": "%d" % (1 + len(ModuleRegistry.getDoneModules()) + len(ModuleRegistry.getUncompiledNonTechnicalModules())), } if not Options.shallMakeModule(): options["result_exe"] = OutputDirectories.getResultFullpath() # Ask Scons to cache on Windows, except where the directory is thrown # away. On non-Windows you can should use ccache instead. if not Options.isRemoveBuildDir() and Utils.getOS() == "Windows": options["cache_mode"] = "true" if Options.isLto(): options["lto_mode"] = asBoolStr(True) if Options.shallUseStaticLibPython(): options["static_libpython"] = asBoolStr(True) if Options.shallDisableConsoleWindow(): options["win_disable_console"] = asBoolStr(True) if Options.isStandaloneMode(): options["standalone_mode"] = asBoolStr(True) if Options.shallTreatUninstalledPython(): options["uninstalled_python"] = asBoolStr(True) if ModuleRegistry.getUncompiledTechnicalModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledTechnicalModules())) if Options.isShowScons(): options["show_scons"] = asBoolStr(True) if Options.isMingw64(): options["mingw_mode"] = asBoolStr(True) if Options.getMsvcVersion(): msvc_version = Options.getMsvcVersion() msvc_version = msvc_version.replace("exp", "Exp") if "." not in msvc_version: msvc_version += ".0" options["msvc_version"] = msvc_version if Utils.getOS() == "Windows": options["noelf_mode"] = asBoolStr(True) if Options.isClang(): options["clang_mode"] = asBoolStr(True) if Options.isProfile(): options["profile_mode"] = asBoolStr(True) if "no_warnings" in getPythonFlags(): options["no_python_warnings"] = asBoolStr(True) if "no_asserts" in getPythonFlags(): options["python_sysflag_optimize"] = asBoolStr(True) if python_version < 0x300 and sys.flags.py3k_warning: options["python_sysflag_py3k_warning"] = asBoolStr(True) if python_version < 0x300 and (sys.flags.division_warning or sys.flags.py3k_warning): options["python_sysflag_division_warning"] = asBoolStr(True) if sys.flags.bytes_warning: options["python_sysflag_bytes_warning"] = asBoolStr(True) if int( os.environ.get("NUITKA_SITE_FLAG", "no_site" in Options.getPythonFlags())): options["python_sysflag_no_site"] = asBoolStr(True) if "trace_imports" in Options.getPythonFlags(): options["python_sysflag_verbose"] = asBoolStr(True) if "no_randomization" in Options.getPythonFlags(): options["python_sysflag_no_randomization"] = asBoolStr(True) if python_version < 0x300 and sys.flags.unicode: options["python_sysflag_unicode"] = asBoolStr(True) if python_version >= 0x370 and sys.flags.utf8_mode: options["python_sysflag_utf8"] = asBoolStr(True) abiflags = getPythonABI() if abiflags: options["abiflags"] = abiflags cpp_defines = Plugins.getPreprocessorSymbols() if cpp_defines: options["cpp_defines"] = ",".join( "%s%s%s" % (key, "=" if value else "", value or "") for key, value in cpp_defines.items()) link_libraries = Plugins.getExtraLinkLibraries() if link_libraries: options["link_libraries"] = ",".join(link_libraries) if Options.shallMakeModule(): options["module_suffix"] = getSharedLibrarySuffix(preferred=True) if Options.shallRunInDebugger(): options["full_names"] = asBoolStr(True) if Options.assumeYesForDownloads(): options["assume_yes_for_downloads"] = asBoolStr(True) return ( SconsInterface.runScons(options=options, quiet=quiet, scons_filename="Backend.scons"), options, )