def shallUseStaticLibPython(): """*bool* = "--static-libpython=yes|auto" Notes: Currently only Anaconda on non-Windows can do this and MSYS2. """ if options.static_libpython == "auto": if isWin32Windows() and os.path.exists( os.path.join(sys.prefix, "etc/config.site")): return True # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. if (os.path.exists(os.path.join(sys.prefix, "conda-meta")) and not isWin32Windows() and not getOS() == "Darwin"): return True options.static_libpython = "no" if getSystemStaticLibPythonPath() is not None: Tracing.options_logger.info( "Detected static libpython as existing, consider using '--static-libpython=yes'." ) return options.static_libpython == "yes"
def executePostProcessing(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, ) # 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)
def getNumpyCoreBinaries(module): """Return any binaries in numpy/core and/or numpy/.libs. Notes: This covers the special cases like MKL binaries. Returns: tuple of abspaths of binaries. """ numpy_dir = module.getCompileTimeDirectory() numpy_core_dir = os.path.join(numpy_dir, "core") base_prefix = getSystemPrefixPath() binaries = [] # first look in numpy/.libs for binaries libdir = os.path.join(numpy_dir, ".libs" if getOS() != "Darwin" else ".dylibs") suffix_start = len(libdir) + 1 if os.path.isdir(libdir): dlls_pkg = os.listdir(libdir) binaries += [[os.path.join(libdir, f), suffix_start] for f in dlls_pkg] # then look for libraries in numpy.core package path # should already return the MKL files in ordinary cases re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_pkg = [f for f in os.listdir(numpy_core_dir) if re_anylib.match(f)] binaries += [[os.path.join(numpy_core_dir, f), suffix_start] for f in dlls_pkg] # Also look for MKL libraries in folder "above" numpy. # This should meet the layout of Anaconda installs. if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") suffix_start = len(lib_dir) + 1 else: lib_dir = os.path.join(base_prefix, "lib") suffix_start = len(lib_dir) + 1 if not os.path.isdir(lib_dir): return binaries re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) for f in os.listdir(lib_dir): if isWin32Windows(): if not (f.startswith( ("libi", "libm", "mkl")) and f.endswith(".dll")): continue else: if not re_mkllib.match(f): continue binaries.append([os.path.join(lib_dir, f), suffix_start]) return binaries
def get_numpy_core_binaries(): """ Return any binaries in numpy/core and/or numpy/.libs, whether or not actually used by our script. Notes: This covers the special cases like MKL binaries, which cannot be detected by dependency managers. Returns: tuple of abspaths of binaries """ base_prefix = get_sys_prefix() suffix_start = len(base_prefix) + 1 binaries = [] # first look in numpy/.libs for binaries _, pkg_dir = get_package_paths("numpy") libdir = os.path.join(pkg_dir, ".libs") suffix_start = len(libdir) + 1 if os.path.isdir(libdir): dlls_pkg = [f for f in os.listdir(libdir)] binaries += [[os.path.join(libdir, f), suffix_start] for f in dlls_pkg] # then look for libraries in numpy.core package path # should already return the MKL files in ordinary cases _, pkg_dir = get_package_paths("numpy.core") re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_pkg = [f for f in os.listdir(pkg_dir) if re_anylib.match(f)] binaries += [[os.path.join(pkg_dir, f), suffix_start] for f in dlls_pkg] # Also look for MKL libraries in folder "above" numpy. # This should meet the layout of Anaconda installs. if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") suffix_start = len(lib_dir) + 1 else: lib_dir = os.path.join(base_prefix, "lib") suffix_start = len(lib_dir) + 1 if not os.path.isdir(lib_dir): return binaries re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) for f in os.listdir(lib_dir): if isWin32Windows(): if not (f.startswith( ("libi", "libm", "mkl")) and f.endswith(".dll")): continue else: if not re_mkllib.match(f): continue binaries.append([os.path.join(lib_dir, f), suffix_start]) return binaries
def _getNumpyCoreBinaries(numpy_dir): """Return any binaries in numpy package. Notes: This covers the special cases like MKL binaries. Returns: tuple of abspaths of binaries. """ numpy_core_dir = os.path.join(numpy_dir, "core") # first look in numpy/.libs for binaries libdir = os.path.join(numpy_dir, ".libs" if not isMacOS() else ".dylibs") if os.path.isdir(libdir): for full_path, filename in listDir(libdir): yield full_path, filename # Then look for libraries in numpy.core package path # should already return the MKL files in ordinary cases re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) for full_path, filename in listDir(numpy_core_dir): if not re_anylib.match(filename): continue yield full_path, filename # Also look for MKL libraries in folder "above" numpy. # This should meet the layout of Anaconda installs. base_prefix = getSystemPrefixPath() if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") else: lib_dir = os.path.join(base_prefix, "lib") if os.path.isdir(lib_dir): re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) for full_path, filename in listDir(lib_dir): if isWin32Windows(): if not ( filename.startswith(("libi", "libm", "mkl")) and filename.endswith(".dll") ): continue else: if not re_mkllib.match(filename): continue yield full_path, filename
def shallUseStaticLibPython(): """*bool* = derived from `sys.prefix` and `os.name` Notes: Currently only Anaconda on non-Windows can do this. """ if isWin32Windows() and os.path.exists( os.path.join(sys.prefix, "etc/config.site")): return True # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. return (os.path.exists(os.path.join(sys.prefix, "conda-meta")) and not isWin32Windows() and not getOS() == "Darwin")
def _wasMsvcMode(): if not isWin32Windows(): return False return (getSconsReportValue( source_dir=OutputDirectories.getSourceDirectoryPath(), key="msvc_mode") == "True")
def isMSYS2MingwPython(): if not isWin32Windows() or "GCC" not in sys.version: return False import sysconfig return "-mingw_" in sysconfig.get_config_var("SO")
def createPreModuleLoadCode(module): """Method called when a module is being imported. Notes: If full name equals "PyQt?" we insert code to include the dist folder in the 'PATH' environment variable (on Windows only). Args: module: the module object Returns: Code to insert and descriptive text (tuple), or (None, None). """ if not isWin32Windows(): # we are only relevant on Windows return None, None if module.getFullName() not in ("PyQt4", "PyQt5"): return None, None # not for us code = """import os path = os.environ.get("PATH", "") if not path.startswith(__nuitka_binary_dir): os.environ["PATH"] = __nuitka_binary_dir + ";" + path """ return ( code, "Adding binary folder to runtime 'PATH' environment variable for proper loading.", )
def runValgrind(descr, tool, args, include_startup, save_logfilename=None): # Many cases to deal with, pylint: disable=too-many-branches if isWin32Windows(): sys.exit("Error, valgrind is not available on Windows.") if descr: my_print(descr, tool, file=sys.stderr, end="... ") with withTemporaryFile() as log_file: log_filename = log_file.name command = ["valgrind", "-q"] if tool == "callgrind": command += ("--tool=callgrind", "--callgrind-out-file=%s" % log_filename) elif tool == "massif": command += ("--tool=massif", "--massif-out-file=%s" % log_filename) else: sys.exit("Error, no support for tool '%s' yet." % tool) # Do not count things before main module starts its work. if not include_startup: command += ( "--zero-before=init__main__()", "--zero-before=init__main__", "--zero-before=PyInit___main__", "--zero-before=PyInit___main__()", ) command.extend(args) _stdout_valgrind, stderr_valgrind, exit_valgrind = executeProcess( command) assert exit_valgrind == 0, stderr_valgrind if descr: my_print("OK", file=sys.stderr) if save_logfilename is not None: copyFile(log_filename, save_logfilename) max_mem = None for line in getFileContentByLine(log_filename): if tool == "callgrind" and line.startswith("summary:"): return int(line.split()[1]) elif tool == "massif" and line.startswith("mem_heap_B="): mem = int(line.split("=")[1]) if max_mem is None: max_mem = 0 max_mem = max(mem, max_mem) if tool == "massif" and max_mem is not None: return max_mem sys.exit("Error, didn't parse Valgrind log file successfully.")
def createPreModuleLoadCode(module): """ This method is called with a module that will be imported. Notes: If the word "tkinter" occurs in its full name, we know that the correct setting of the TCL environment must be ensured before this happens. Args: module: the module object Returns: Code to insert and None (tuple) """ if not isWin32Windows(): # we are only relevant on Windows return None, None # only insert code for tkinter related modules if not _isTkInterModule(module): return None, None # The following code will be executed before importing the module. # If required we set the respective environment values. code = """import os if not os.environ.get("TCL_LIBRARY", None): os.environ["TCL_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tcl") os.environ["TK_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tk")""" return code, "Need to make sure we set environment variables for TCL."
def _shallUseStaticLibPython(): # return driven, pylint: disable=too-many-return-statements if shallMakeModule(): return False, "not used in module mode" if options.static_libpython == "auto": # Nuitka-Python is good to to static linking. if isNuitkaPython(): return True, "Nuitka-Python is broken." # Debian packages with are usable if the OS is new enough from nuitka.utils.StaticLibraries import ( isDebianSuitableForStaticLinking, ) if (isDebianBasedLinux() and isDebianPackagePython() and isDebianSuitableForStaticLinking() and not isPythonDebug()): return True, "Nuitka on Debian-Python needs package '%s' installed." % ( "python2-dev" if str is bytes else "python3-dev") if isMSYS2MingwPython(): return True, "Nuitka on MSYS2 needs package 'python-devel' installed." # For Anaconda default to trying static lib python library, which # normally is just not available or if it is even unusable. if isAnacondaPython() and not isMacOS() and not isWin32Windows(): return True, "Nuitka on Anaconda needs package 'libpython' installed." if isPyenvPython(): return True, "Nuitka on pyenv should not use '--enable-shared'." return options.static_libpython == "yes", None
def enableProgressBar(): global use_progress_bar # singleton, pylint: disable=global-statement global tqdm # singleton, pylint: disable=global-statement if isWin32Windows(): colorama = importFromInlineCopy("colorama", must_exist=True) colorama.init() tqdm = importFromInlineCopy("tqdm", must_exist=False) if tqdm is None: try: # Cannot use import tqdm due to pylint bug. import tqdm as tqdm_installed # pylint: disable=I0021,import-error tqdm = tqdm_installed except ImportError: # We handle the case without inline copy too, but it may be removed, e.g. on # Debian it's only a recommended install, and not included that way. pass # Tolerate the absence ignore the progress bar if tqdm is not None: tqdm = tqdm.tqdm tqdm.set_lock(RLock()) use_progress_bar = True
def shallCreateCmdFileForExecution(): """*bool* = derived from Python installation and modes Notes: Most for accerated mode on Windows with uninstalled python, to make sure they find their Python DLL. """ return isWin32Windows() and shallTreatUninstalledPython()
def packDistFolderToOnefileBootstrap(onefile_output_filename, dist_dir): postprocessing_logger.info( "Creating single file from dist folder, this may take a while.") onefile_logger.info("Running bootstrap binary compilation via Scons.") # Now need to append to payload it, potentially compressing it. compressor_python = getCompressorPython() # First need to create the bootstrap binary for unpacking. _runOnefileScons( quiet=not Options.isShowScons(), onefile_compression=compressor_python is not None, ) if isWin32Windows(): executePostProcessingResources(manifest=None, onefile=True) Plugins.onBootstrapBinary(onefile_output_filename) if isMacOS(): addMacOSCodeSignature(filenames=[onefile_output_filename]) runOnefileCompressor( compressor_python=compressor_python, dist_dir=dist_dir, onefile_output_filename=onefile_output_filename, start_binary=getResultFullpath(onefile=False), )
def onModuleEncounter(self, module_filename, module_name, module_kind): # Make sure if module_name.isBelowNamespace("webview.platforms"): if isWin32Windows(): result = module_name in ( "webview.platforms.winforms", "webview.platforms.edgechromium", "webview.platforms.edgehtml", "webview.platforms.mshtml", "webview.platforms.cef", ) reason = "Platforms package of webview used on '%s'." % getOS() elif isMacOS(): result = module_name == "webview.platforms.cocoa" reason = "Platforms package of webview used on '%s'." % getOS() elif getActiveQtPlugin() is not None: result = module_name = "webview.platforms.qt" reason = ("Platforms package of webview used due to '%s'." % getActiveQtPlugin()) else: result = module_name = "webview.platforms.gtk" reason = ( "Platforms package of webview used on '%s' without Qt plugin enabled." % getOS()) return result, reason
def createPreModuleLoadCode(self, module): """Method called when a module is being imported. Notes: If full name equals to the binding we insert code to include the dist folder in the 'PATH' environment variable (on Windows only). Args: module: the module object Returns: Code to insert and descriptive text (tuple), or (None, None). """ # This isonly relevant on standalone mode for Windows if not isWin32Windows() or not Options.isStandaloneMode(): return None full_name = module.getFullName() if full_name == self.binding_name: code = """import os path = os.environ.get("PATH", "") if not path.startswith(__nuitka_binary_dir): os.environ["PATH"] = __nuitka_binary_dir + ";" + path """ return ( code, "Adding binary folder to runtime 'PATH' environment variable for proper loading.", )
def getResultRunFilename(onefile): result = getResultFullpath(onefile=onefile) if isWin32Windows() and Options.shallTreatUninstalledPython(): result = getResultBasepath(onefile=onefile) + ".cmd" return result
def isRelevant(): """ This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation on Windows, else False. """ return Options.isStandaloneMode() and isWin32Windows()
def _openBinaryFileForAppending(onefile_output_filename): max_attempts = 5 # TODO: This is code duplication with resource handling, should be unified # and with as a context manager. for attempt in range(1, max_attempts + 1): try: with open(onefile_output_filename, "ab") as output_file: yield output_file return except OSError as e: # Only for Windows at this time, other platforms don't have the issue. if not isWin32Windows() and not isPosixWindows(): raise if e.errno in (110, 13): onefile_logger.warning(""" Failed to open binary for payload attachment in attempt %d. Disable Anti-Virus, e.g. Windows Defender for build folders. Retrying after a second of delay.""" % attempt) else: onefile_logger.warning(""" Failed to open binary for payload attachment in attempt %d with error code %d. Disable Anti-Virus, e.g. Windows Defender for build folders. Retrying after a second of delay.""" % (attempt, e.errno)) time.sleep(1) continue else: if attempt != 1: onefile_logger.warning( "Succeeded to open binary for payload attachment in attempt %d." % attempt) break
def createPreModuleLoadCode(module): """ This method is called with a module that will be imported. Notes: If the word "tkinter" occurs in its full name, we know that the correct setting of the TCL environment must be ensured before this happens. Args: module: the module object Returns: Code to insert and None (tuple) """ if not isWin32Windows(): # we are only relevant on Windows return None, None # only insert code for tkinter related modules if not _isTkInterModule(module): return None, None # The following code will be executed before importing the module. # If required we set the respective environment values. code = """import os if not os.environ.get("TCL_LIBRARY", None): os.environ["TCL_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tcl") os.environ["TK_LIBRARY"] = os.path.join(__nuitka_binary_dir, "tk")""" return code, "Need to make sure we set environment variables for TCL."
def isRelevant(): """ This method is called one time only to check, whether the plugin might make sense at all. Returns: True if this is a standalone compilation on Windows, else False. """ return Options.isStandaloneMode() and isWin32Windows()
def considerExtraDlls(self, dist_dir, module): """ Copy TCL libraries to the dist folder. Notes: We will copy the TCL/TK directories to the program's root directory. The general intention is that we return a tuple of file names. We need however two subdirectories inserted, and therefore do the copy ourselves and return an empty tuple. Args: dist_dir: the name of the program's dist folder module: the module object (not used here) Returns: None """ if not _isTkInterModule(module): return () if not isWin32Windows(): # if not Windows notify wrong usage once info("tkinter plugin supported on Windows only") return () if python_version < 340: # last tk/tcl qualifyers Py 2 tk_lq = "tk8.5" tcl_lq = "tcl8.5" else: # last tk/tcl qualifyers Py 3+ tk_lq = "tk8.6" tcl_lq = "tcl8.6" # check possible locations of the dirs sys_tcl = os.path.join(os.path.dirname(sys.executable), "tcl") tk = os.path.join(sys_tcl, tk_lq) tcl = os.path.join(sys_tcl, tcl_lq) # if this was not the right place, try this: if not (os.path.exists(tk) and os.path.exists(tcl)): tk = os.environ.get("TK_LIBRARY", None) tcl = os.environ.get("TCL_LIBRARY", None) if not (tk and tcl): info(" Could not find TK / TCL libraries") sys.exit("aborting standalone generation.") # survived the above, now do the copying to following locations tar_tk = os.path.join(dist_dir, "tk") tar_tcl = os.path.join(dist_dir, "tcl") info(" Now copying tk libraries from %r." % tk) # just to entertain shutil.copytree(tk, tar_tk) info(" Now copying tkinter libraries from %r." % tcl) # just to entertain shutil.copytree(tcl, tar_tcl) # Definitely don't need the demos, so remove them again. # TODO: Anything else? shutil.rmtree(os.path.join(tar_tk, "demos"), ignore_errors=True) return ()
def enableProgressBar(): global use_progress_bar # singleton, pylint: disable=global-statement if _getTqdmModule() is not None: use_progress_bar = True if isWin32Windows(): colorama = importFromInlineCopy("colorama", must_exist=True) colorama.init()
def _getClcacheGuessedPaths(python_prefix): assert isWin32Windows() # Search the compiling Python, the Scons Python (likely the same, but not necessarily) # and then Anaconda, if an environment variable present from activated, or installed in # CI like Github actions. for python_dir in _getPythonDirCandidates(python_prefix): yield os.path.join(python_dir, "scripts", "clcache.exe") yield os.path.join(python_dir, "bin", "clcache.exe")
def considerExtraDlls(self, dist_dir, module): """ Copy TCL libraries to the dist folder. Notes: We will copy the TCL/TK directories to the program's root directory. The general intention is that we return a tuple of file names. We need however two subdirectories inserted, and therefore do the copy ourselves and return an empty tuple. Args: dist_dir: the name of the program's dist folder module: the module object (not used here) Returns: None """ if not _isTkInterModule(module): return () if not isWin32Windows(): # if not Windows notify wrong usage once info("tkinter plugin supported on Windows only") return () if python_version < 340: # last tk/tcl qualifyers Py 2 tk_lq = "tk8.5" tcl_lq = "tcl8.5" else: # last tk/tcl qualifyers Py 3+ tk_lq = "tk8.6" tcl_lq = "tcl8.6" # check possible locations of the dirs sys_tcl = os.path.join(os.path.dirname(sys.executable), "tcl") tk = os.path.join(sys_tcl, tk_lq) tcl = os.path.join(sys_tcl, tcl_lq) # if this was not the right place, try this: if not (os.path.exists(tk) and os.path.exists(tcl)): tk = os.environ.get("TK_LIBRARY", None) tcl = os.environ.get("TCL_LIBRARY", None) if not (tk and tcl): info(" Could not find TK / TCL libraries") sys.exit("aborting standalone generation.") # survived the above, now do the copying to following locations tar_tk = os.path.join(dist_dir, "tk") tar_tcl = os.path.join(dist_dir, "tcl") info(" Now copying tk libraries from %r." % tk) # just to entertain shutil.copytree(tk, tar_tk) info(" Now copying tkinter libraries from %r." % tcl) # just to entertain shutil.copytree(tcl, tar_tcl) # Definitely don't need the demos, so remove them again. # TODO: Anything else? shutil.rmtree(os.path.join(tar_tk, "demos"), ignore_errors=True) return ()
def executePostProcessing(result_filename): # 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: if isWin32Windows() and not Options.shallMakeModule(): copyResourcesFromFileToFile(sys.executable, result_filename, RT_MANIFEST) # 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)
def executePostProcessing(result_filename): # 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: if isWin32Windows() and not Options.shallMakeModule(): copyResourcesFromFileToFile(sys.executable, result_filename, RT_MANIFEST) # 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)
def _getCcacheGuessedPaths(python_prefix): if isWin32Windows(): # Search the compiling Python, the Scons Python (likely the same, but not necessarily) # and then Anaconda, if an environment variable present from activated, or installed in # CI like Github actions. for python_dir in _getPythonDirCandidates(python_prefix): yield os.path.join(python_dir, "bin", "ccache.exe") yield os.path.join(python_dir, "scripts", "ccache.exe") elif getOS() == "Darwin": # For macOS, we might find Homebrew ccache installed but not in PATH. yield "/usr/local/opt/ccache"
def get_numpy_core_binaries(): """ Return any binaries in numpy/core and/or numpy/.libs, whether or not actually used by our script. Notes: This covers the special cases like MKL binaries, which cannot be detected by dependency managers. Returns: tuple of abspaths of binaries """ # covers/unifies cases, where sys.base_prefix does not deliver # everything we need and/or is not an abspath. base_prefix = getattr(sys, "real_prefix", getattr(sys, "base_prefix", sys.prefix)) base_prefix = os.path.abspath(base_prefix) binaries = [] # first look in numpy/.libs for binaries _, pkg_dir = get_package_paths("numpy") libdir = os.path.join(pkg_dir, ".libs") if os.path.isdir(libdir): dlls_pkg = [f for f in os.listdir(libdir)] binaries += [(os.path.join(libdir, f), ".") for f in dlls_pkg] # then look for libraries in numpy.core package path # should already return the MKL DLLs in ordinary cases _, pkg_dir = get_package_paths("numpy.core") re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_pkg = [f for f in os.listdir(pkg_dir) if re_anylib.match(f)] binaries += [(os.path.join(pkg_dir, f), ".") for f in dlls_pkg] # Also look for MKL libraries in Python's lib directory if present. # Anything found here will have to land in the dist folder, because there # just is no logical other place, and hope for the best ... # TODO: not supported yet! if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") else: lib_dir = os.path.join(base_prefix, "lib") if os.path.isdir(lib_dir): re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_mkl = [f for f in os.listdir(lib_dir) if re_mkllib.match(f)] if dlls_mkl: info(" Additional MKL libraries found.") info(" Not copying MKL binaries in '%s' for numpy!" % libdir) # binaries += [(os.path.join(lib_dir, f), '.') for f in dlls_mkl] return binaries
def compileTree(main_module): source_dir = OutputDirectories.getSourceDirectoryPath() if not Options.shallOnlyExecCCompilerCall(): if Options.isShowProgress() or Options.isShowMemory(): info( "Total memory usage before generating C code: {memory}:".format( memory=MemoryUsage.getHumanReadableProcessMemoryUsage() ) ) # Now build the target language code for the whole tree. makeSourceDirectory(main_module=main_module) frozen_code = generateBytecodeFrozenCode() if frozen_code is not None: writeSourceCode( filename=os.path.join(source_dir, "__frozen.c"), source_code=frozen_code ) if not isWin32Windows(): writeBinaryData( filename=os.path.join(source_dir, "__constants.bin"), binary_data=ConstantCodes.stream_data.getBytes(), ) else: source_dir = OutputDirectories.getSourceDirectoryPath() if not os.path.isfile(os.path.join(source_dir, "__helpers.h")): sys.exit("Error, no previous build directory exists.") if Options.isShowProgress() or Options.isShowMemory(): info( "Total memory usage before running scons: {memory}:".format( memory=MemoryUsage.getHumanReadableProcessMemoryUsage() ) ) if Options.isShowMemory(): InstanceCounters.printStats() if Options.isDebug(): Reports.doMissingOptimizationReport() if Options.shallNotDoExecCCompilerCall(): return True, {} # Run the Scons to build things. result, options = runScons(main_module=main_module, quiet=not Options.isShowScons()) return result, options
def get_numpy_core_binaries(): """ Return any binaries in numpy/core and/or numpy/.libs, whether or not actually used by our script. Notes: This covers the special cases like MKL binaries, which cannot be detected by dependency managers. Returns: tuple of abspaths of binaries """ # covers/unifies cases, where sys.base_prefix does not deliver # everything we need and/or is not an abspath. base_prefix = getattr(sys, "real_prefix", getattr(sys, "base_prefix", sys.prefix)) base_prefix = os.path.abspath(base_prefix) binaries = [] # first look in numpy/.libs for binaries _, pkg_dir = get_package_paths("numpy") libdir = os.path.join(pkg_dir, ".libs") if os.path.isdir(libdir): dlls_pkg = [f for f in os.listdir(libdir)] binaries += [(os.path.join(libdir, f), ".") for f in dlls_pkg] # then look for libraries in numpy.core package path # should already return the MKL DLLs in ordinary cases _, pkg_dir = get_package_paths("numpy.core") re_anylib = re.compile(r"\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_pkg = [f for f in os.listdir(pkg_dir) if re_anylib.match(f)] binaries += [(os.path.join(pkg_dir, f), ".") for f in dlls_pkg] # Also look for MKL libraries in Python's lib directory if present. # Anything found here will have to land in the dist folder, because there # just is no logical other place, and hope for the best ... # TODO: not supported yet! if isWin32Windows(): lib_dir = os.path.join(base_prefix, "Library", "bin") else: lib_dir = os.path.join(base_prefix, "lib") if os.path.isdir(lib_dir): re_mkllib = re.compile(r"^(?:lib)?mkl\w+\.(?:dll|so|dylib)", re.IGNORECASE) dlls_mkl = [f for f in os.listdir(lib_dir) if re_mkllib.match(f)] if dlls_mkl: info(" Additional MKL libraries found.") info(" Not copying MKL binaries in '%s' for numpy!" % libdir) # binaries += [(os.path.join(lib_dir, f), '.') for f in dlls_mkl] return binaries
def considerExtraDlls(self, dist_dir, module): module_name = module.getFullName() if module_name == "zmq.libzmq" and isWin32Windows(): # TODO: Very strange thing for zmq on Windows, needs the .pyd file in wrong dir too. Have # this done in a dedicated form somewhere. shutil.copyfile( os.path.join(dist_dir, "zmq\\libzmq.pyd"), os.path.join(dist_dir, "libzmq" + getSharedLibrarySuffix(preferred=True)), ) return NuitkaPluginBase.considerExtraDlls(self, dist_dir=dist_dir, module=module)
def _getResourcesTargetDir(self): """Where does the Qt bindings package expect the resources files.""" if isMacOS(): return "Content/Resources" elif isWin32Windows(): if self.binding_name in ("PySide2", "PyQt5"): return "resources" else: # While PyQt6/PySide6 complains about these, they are not working # return os.path.join(self.binding_name, "resources") return "." else: if self.binding_name in ("PySide2", "PySide6", "PyQt6"): return "." elif self.binding_name == "PyQt5": return "resources" else: assert False
def get_scipy_core_binaries(): """ Return binaries from the extra-dlls folder (Windows only). """ binaries = [] if not isWin32Windows(): return binaries extra_dll = os.path.join( os.path.dirname(get_module_file_attribute("scipy")), "extra-dll") if not os.path.isdir(extra_dll): return binaries netto_bins = os.listdir(extra_dll) for f in netto_bins: if not f.endswith(".dll"): continue binaries.append((os.path.join(extra_dll, f), ".")) return binaries
def get_scipy_core_binaries(): """ Return binaries from the extra-dlls folder (Windows only). """ binaries = [] if not isWin32Windows(): return binaries extra_dll = os.path.join( os.path.dirname(get_module_file_attribute("scipy")), "extra-dll" ) if not os.path.isdir(extra_dll): return binaries netto_bins = os.listdir(extra_dll) for f in netto_bins: if not f.endswith(".dll"): continue binaries.append((os.path.join(extra_dll, f), ".")) return binaries