From fa088e4975efcd5960140f331864dee4336ed2dd Mon Sep 17 00:00:00 2001 From: kshea21 Date: Tue, 7 Jan 2025 15:13:23 -0800 Subject: [PATCH] review changes --- lib/spack/spack/build_environment.py | 50 ++++++++++++++++++++++------ lib/spack/spack/installer.py | 24 ++++++------- 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py index 02a629da9e2..7e66a04d31b 100644 --- a/lib/spack/spack/build_environment.py +++ b/lib/spack/spack/build_environment.py @@ -31,6 +31,7 @@ Skimming this module is a nice way to get acquainted with the types of calls you can make from within the install() function. """ + import inspect import io import multiprocessing @@ -453,6 +454,35 @@ def optimization_flags(compiler, target): return result +class FilterDefaultDynamicLinkerSearchPaths: + """Remove rpaths to directories that are default search paths of the dynamic linker.""" + + def __init__(self, dynamic_linker: Optional[str]) -> None: + # Identify directories by (inode, device) tuple, which handles symlinks too. + self.default_path_identifiers: Set[Tuple[int, int]] = set() + if not dynamic_linker: + return + for path in spack.util.libc.default_search_paths_from_dynamic_linker(dynamic_linker): + try: + s = os.stat(path) + if stat.S_ISDIR(s.st_mode): + self.default_path_identifiers.add((s.st_ino, s.st_dev)) + except OSError: + continue + + def is_dynamic_loader_default_path(self, p: str) -> bool: + try: + s = os.stat(p) + return (s.st_ino, s.st_dev) in self.default_path_identifiers + except OSError: + return False + + def __call__(self, dirs: List[str]) -> List[str]: + if not self.default_path_identifiers: + return dirs + return [p for p in dirs if not self.is_dynamic_loader_default_path(p)] + + def set_wrapper_variables(pkg, env): """Set environment variables used by the Spack compiler wrapper (which have the prefix `SPACK_`) and also add the compiler wrappers to PATH. @@ -867,6 +897,7 @@ def effective_deptypes( root=True, all_edges=True, ) + traverse.traverse_depth_first_with_visitor(traverse.with_artificial_edges(specs), visitor) # Dictionary with "no mode" as default value, so it's easy to write modes[x] |= flag. use_modes = defaultdict(lambda: UseMode(0)) @@ -1095,10 +1126,7 @@ def load_external_modules(context: SetupContext) -> None: class ProcessHandle: - """ - This class manages and monitors the state of a child process for a task - used for the building and installation of a package. - """ + """Manages and monitors the state of a child process for package installation.""" def __init__( self, @@ -1108,7 +1136,7 @@ def __init__( ): """ Parameters: - pkg: The package to be built and installed through the child process. + pkg: The package to be built and installed by the child process. process: The child process instance being managed/monitored. read_pipe: The pipe used for receiving information from the child process. """ @@ -1117,12 +1145,12 @@ def __init__( self.read_pipe = read_pipe def poll(self) -> bool: - """Checks if there is data available to receive from the read pipe""" + """Check if there is data available to receive from the read pipe.""" return self.read_pipe.poll() def complete(self): - """Waits (if needed) for the child process to complete - and returns its exit status. + """Wait (if needed) for child process to complete + and return its exit status. See ``complete_build_process()``. """ @@ -1295,13 +1323,13 @@ def start_build_process( Args: pkg: package whose environment we should set up the - child process for. + child process for. function: argless function to run in the child process. kwargs: additional keyword arguments to pass to ``function()`` timeout: maximum time allowed to finish the execution of function - Usage: + Usage:: def child_fun(): # do stuff @@ -1420,7 +1448,7 @@ def exitcode_msg(process): return child_result -CONTEXT_BASES = (spack.package_base.PackageBase, spack.builder.Builder) +CONTEXT_BASES = (spack.package_base.PackageBase, spack.build_systems._checks.BaseBuilder) def get_package_context(traceback, context=3): diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 2e90be882d3..77bbc9a7b66 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -1337,7 +1337,7 @@ def __init__( run tests for some use_cache: Install from binary package, if available. verbose: Display verbose build output (by default, suppresses it) - concurrent_packages: Number of pkgs that could be concurrently built (using n procs) + concurrent_packages: Max packages to be built concurrently """ if isinstance(explicit, bool): explicit = {pkg.spec.dag_hash() for pkg in packages} if explicit else set() @@ -2113,7 +2113,7 @@ def start_task(task) -> None: """Attempts to start a package installation.""" pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec install_status.next_pkg(pkg) - install_status.set_term_title(f"Processing {task.pkg.name}") + # install_status.set_term_title(f"Processing {task.pkg.name}") tty.debug(f"Processing {pkg_id}: task={task}") # Skip the installation if the spec is not being installed locally @@ -2122,7 +2122,7 @@ def start_task(task) -> None: if _handle_external_and_upstream(pkg, task.explicit): term_status.clear() self._flag_installed(pkg, task.dependents) - return None + return # Flag a failed spec. Do not need an (install) prefix lock since # assume using a separate (failed) prefix lock file. @@ -2134,7 +2134,7 @@ def start_task(task) -> None: if self.fail_fast: raise spack.error.InstallError(fail_fast_err, pkg=pkg) - return None + return # Attempt to get a write lock. If we can't get the lock then # another process is likely (un)installing the spec or has @@ -2153,7 +2153,7 @@ def start_task(task) -> None: # -- failed, installed, or uninstalled -- on the next pass. if lock is None: self._requeue_task(task, install_status) - return None + return term_status.clear() @@ -2163,7 +2163,7 @@ def start_task(task) -> None: task.request.overwrite_time = time.time() # Determine state of installation artifacts and adjust accordingly. - install_status.set_term_title(f"Preparing {task.pkg.name}") + # install_status.set_term_title(f"Preparing {task.pkg.name}") self._prepare_for_install(task) # Flag an already installed package @@ -2187,7 +2187,7 @@ def start_task(task) -> None: # or uninstalled -- on the next pass. self.installed.remove(pkg_id) self._requeue_task(task, install_status) - return None + return # Having a read lock on an uninstalled pkg may mean another # process completed an uninstall of the software between the @@ -2200,16 +2200,15 @@ def start_task(task) -> None: if ltype == "read": lock.release_read() self._requeue_task(task, install_status) - return None + return # Proceed with the installation since we have an exclusive write # lock on the package. - # Start a child process for a task that's ready to be installed. - install_status.set_term_title(f"Installing {task.pkg.name}") action = self._install_action(task) if action == InstallAction.INSTALL: + # Start a child process for a task that's ready to be installed. task.start() tty.msg(install_msg(pkg_id, self.pid, install_status)) active_tasks.append(task) @@ -2321,7 +2320,6 @@ def complete_task(task) -> None: self._clear_removed_tasks() if self.build_pq: task = self._pop_task() - pkg, pkg_id = task.pkg, task.pkg_id assert task.priority != 0, "Found ready task after _peek_ready_task returned None" # If the spec has uninstalled dependencies # and no active tasks running, then there must be @@ -2335,11 +2333,11 @@ def complete_task(task) -> None: ) left = [dep_id for dep_id in task.uninstalled_deps if dep_id not in self.installed] if not left: - tty.warn(f"{pkg_id} does NOT actually have any uninstalled deps left") + tty.warn(f"{task.pkg_id} does NOT actually have any uninstalled deps left") dep_str = "dependencies" if task.priority > 1 else "dependency" raise spack.error.InstallError( - f"Cannot proceed with {pkg_id}: {task.priority} uninstalled " + f"Cannot proceed with {task.pkg_id}: {task.priority} uninstalled " f"{dep_str}: {','.join(task.uninstalled_deps)}", pkg=task.pkg, )