def getClass(self, name, cls): if in_system_path(name): return ExcludedMachO for base in self.excludes: if name.startswith(base): return ExcludedMachO return cls
def match_func(pth): """ For system libraries is still used absolute path. It is unchanged. """ # Leave system dynamic libraries unchanged if util.in_system_path(pth): return None # The older python.org builds that use system Tcl/Tk framework # have their _tkinter.cpython-*-darwin.so library linked against # /Library/Frameworks/Tcl.framework/Versions/8.5/Tcl and # /Library/Frameworks/Tk.framework/Versions/8.5/Tk, although the # actual frameworks are located in /System/Library/Frameworks. # Therefore, they slip through the above in_system_path() check, # and we need to exempt them manually. _exemptions = [ '/Library/Frameworks/Tcl.framework/', '/Library/Frameworks/Tk.framework/' ] if any([x in pth for x in _exemptions]): return None # Use relative path to dependent dynamic libraries based on the # location of the executable. return os.path.join('@loader_path', parent_dir, os.path.basename(pth))
def search(self, libname): # First try global exclude list. If it matches, return its result; otherwise continue with other check. result = self._exclude_list.search(libname) if result: return result else: return util.in_system_path(libname)
def search(self, libname): # First try global exclude list. If it matches then # return it's result otherwise continue with other check. result = self._exclude_list.search(libname) if result: return result else: return util.in_system_path(libname)
def _warn_if_activetcl_or_teapot_installed(tcl_root, tcltree): """ If the current Tcl installation is a Teapot-distributed version of ActiveTcl *and* the current platform is OS X, log a non-fatal warning that the resulting executable will (probably) fail to run on non-host systems. PyInstaller does *not* freeze all ActiveTcl dependencies -- including Teapot, which is typically ignorable. Since Teapot is *not* ignorable in this case, this function warns of impending failure. See Also ------- https://github.com/pyinstaller/pyinstaller/issues/621 """ from macholib import util # System libraries do not experience this problem. if util.in_system_path(tcl_root): return # Absolute path of the "init.tcl" script. try: init_resource = [r[1] for r in tcltree if r[1].endswith("init.tcl")][0] # If such script could not be found, silently return. except IndexError: return mentions_activetcl = False mentions_teapot = False # TCL/TK reads files using the `system encoding <https://www.tcl.tk/doc/howto/i18n.html#system_encoding>`_. with open_file( init_resource, text_read_mode, encoding=locale.getpreferredencoding() ) as init_file: for line in init_file.readlines(): line = line.strip().lower() if line.startswith("#"): continue if "activetcl" in line: mentions_activetcl = True if "teapot" in line: mentions_teapot = True if mentions_activetcl and mentions_teapot: break if mentions_activetcl and mentions_teapot: logger.warning( """ You appear to be using an ActiveTcl build of Tcl/Tk, which PyInstaller has difficulty freezing. To fix this, comment out all references to "teapot" in: %s See https://github.com/pyinstaller/pyinstaller/issues/621 for more information. """ % init_resource )
def match_func(pth): """ For system libraries is still used absolute path. It is unchanged. """ # Match non system dynamic libraries. if not util.in_system_path(pth): # Use relative path to dependend dynamic libraries bases on # location of the executable. return os.path.join('@loader_path', parent_dir, os.path.basename(pth))
def _warn_if_activetcl_or_teapot_installed(tcl_root, tcltree): """ If the current Tcl installation is a Teapot-distributed version of ActiveTcl *and* the current platform is OS X, log a non-fatal warning that the resulting executable will (probably) fail to run on non-host systems. PyInstaller does *not* freeze all ActiveTcl dependencies -- including Teapot, which is typically ignorable. Since Teapot is *not* ignorable in this case, this function warns of impending failure. See Also ------- https://github.com/pyinstaller/pyinstaller/issues/621 """ from macholib import util # System libraries do not experience this problem. if util.in_system_path(tcl_root): return # Absolute path of the "init.tcl" script. try: init_resource = [r[1] for r in tcltree if r[1].endswith('init.tcl')][0] # If such script could not be found, silently return. except IndexError: return mentions_activetcl = False mentions_teapot = False with open(init_resource, 'r') as init_file: for line in init_file.readlines(): line = line.strip().lower() if line.startswith('#'): continue if 'activetcl' in line: mentions_activetcl = True if 'teapot' in line: mentions_teapot = True if mentions_activetcl and mentions_teapot: break if mentions_activetcl and mentions_teapot: logger.warning( """ You appear to be using an ActiveTcl build of Tcl/Tk, which PyInstaller has difficulty freezing. To fix this, comment out all references to "teapot" in: %s See https://github.com/pyinstaller/pyinstaller/issues/621 for more information. """ % init_resource)
def locate(self, filename): if in_system_path(filename): return filename if filename.startswith(self.base): return filename for base in self.excludes: if filename.startswith(base): return filename if filename in self.changemap: return self.changemap[filename] info = framework_info(filename) if info is None: res = self.copy_dylib(filename) self.changemap[filename] = res return res else: res = self.copy_framework(info) self.changemap[filename] = res return res
def _getImports_macholib(pth): """ Find the binary dependencies of PTH. This implementation is for Mac OS X and uses library macholib. """ from macholib.MachO import MachO from macholib.mach_o import LC_RPATH from macholib.dyld import dyld_find from macholib.util import in_system_path rslt = set() seen = set() # Libraries read from binary headers. ## Walk through mach binary headers. m = MachO(pth) for header in m.headers: for idx, name, lib in header.walkRelocatables(): # Sometimes some libraries are present multiple times. if lib not in seen: seen.add(lib) # Walk through mach binary headers and look for LC_RPATH. # macholib can't handle @rpath. LC_RPATH has to be read # from the MachO header. # TODO Do we need to remove LC_RPATH from MachO load commands? # Will it cause any harm to leave them untouched? # Removing LC_RPATH should be implemented when getting # files from the bincache if it is necessary. run_paths = set() for header in m.headers: for command in header.commands: # A command is a tupple like: # (<macholib.mach_o.load_command object at 0x>, # <macholib.mach_o.rpath_command object at 0x>, # '../lib\x00\x00') cmd_type = command[0].cmd if cmd_type == LC_RPATH: rpath = command[2].decode('utf-8') # Remove trailing '\x00' characters. # e.g. '../lib\x00\x00' rpath = rpath.rstrip('\x00') # Replace the @executable_path and @loader_path keywords # with the actual path to the binary. executable_path = os.path.dirname(pth) rpath = re.sub('^@(executable_path|loader_path|rpath)(/|$)', executable_path + r'\2', rpath) # Make rpath absolute. According to Apple doc LC_RPATH # is always relative to the binary location. rpath = os.path.normpath(os.path.join(executable_path, rpath)) run_paths.update([rpath]) else: # Frameworks that have this structure Name.framework/Versions/N/Name # need to to search at the same level as the framework dir. # This is specifically needed so that the QtWebEngine dependencies # can be found. if '.framework' in pth: run_paths.update(['../../../']) # for distributions like Anaconda, all of the dylibs are stored in the lib directory # of the Python distribution, not alongside of the .so's in each module's subdirectory. run_paths.add(os.path.join(base_prefix, 'lib')) ## Try to find files in file system. # In cases with @loader_path or @executable_path # try to look in the same directory as the checked binary is. # This seems to work in most cases. exec_path = os.path.abspath(os.path.dirname(pth)) for lib in seen: # Suppose that @rpath is not used for system libraries and # using macholib can be avoided. # macholib can't handle @rpath. if lib.startswith('@rpath'): lib = lib.replace('@rpath', '.') # Make path relative. final_lib = None # Absolute path to existing lib on disk. # Try multiple locations. for run_path in run_paths: # @rpath may contain relative value. Use exec_path as # base path. if not os.path.isabs(run_path): run_path = os.path.join(exec_path, run_path) # Stop looking for lib when found in first location. if os.path.exists(os.path.join(run_path, lib)): final_lib = os.path.abspath(os.path.join(run_path, lib)) rslt.add(final_lib) break # Log error if no existing file found. if not final_lib: logger.error('Can not find path %s (needed by %s)', lib, pth) # Macholib has to be used to get absolute path to libraries. else: # macholib can't handle @loader_path. It has to be # handled the same way as @executable_path. # It is also replaced by 'exec_path'. if lib.startswith('@loader_path'): lib = lib.replace('@loader_path', '@executable_path') try: lib = dyld_find(lib, executable_path=exec_path) rslt.add(lib) except ValueError: # Starting with Big Sur, system libraries are hidden. And # we do not collect system libraries on any macOS version # anyway, so suppress the corresponding error messages. if not in_system_path(lib): logger.error('Can not find path %s (needed by %s)', lib, pth) return rslt
def not_system_filter(module): """ Return False if the module is located in a system directory """ return not in_system_path(module.filename)
def not_system_filter(module: modulegraph.Node) -> bool: """ Return False if the module is located in a system directory """ return not in_system_path(module.filename)