review changes
This commit is contained in:
parent
9d0133a771
commit
fa088e4975
@ -31,6 +31,7 @@
|
|||||||
Skimming this module is a nice way to get acquainted with the types of
|
Skimming this module is a nice way to get acquainted with the types of
|
||||||
calls you can make from within the install() function.
|
calls you can make from within the install() function.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import io
|
import io
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
@ -453,6 +454,35 @@ def optimization_flags(compiler, target):
|
|||||||
return result
|
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):
|
def set_wrapper_variables(pkg, env):
|
||||||
"""Set environment variables used by the Spack compiler wrapper (which have the prefix
|
"""Set environment variables used by the Spack compiler wrapper (which have the prefix
|
||||||
`SPACK_`) and also add the compiler wrappers to PATH.
|
`SPACK_`) and also add the compiler wrappers to PATH.
|
||||||
@ -867,6 +897,7 @@ def effective_deptypes(
|
|||||||
root=True,
|
root=True,
|
||||||
all_edges=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.
|
# Dictionary with "no mode" as default value, so it's easy to write modes[x] |= flag.
|
||||||
use_modes = defaultdict(lambda: UseMode(0))
|
use_modes = defaultdict(lambda: UseMode(0))
|
||||||
@ -1095,10 +1126,7 @@ def load_external_modules(context: SetupContext) -> None:
|
|||||||
|
|
||||||
|
|
||||||
class ProcessHandle:
|
class ProcessHandle:
|
||||||
"""
|
"""Manages and monitors the state of a child process for package installation."""
|
||||||
This class manages and monitors the state of a child process for a task
|
|
||||||
used for the building and installation of a package.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -1108,7 +1136,7 @@ def __init__(
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Parameters:
|
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.
|
process: The child process instance being managed/monitored.
|
||||||
read_pipe: The pipe used for receiving information from the child process.
|
read_pipe: The pipe used for receiving information from the child process.
|
||||||
"""
|
"""
|
||||||
@ -1117,12 +1145,12 @@ def __init__(
|
|||||||
self.read_pipe = read_pipe
|
self.read_pipe = read_pipe
|
||||||
|
|
||||||
def poll(self) -> bool:
|
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()
|
return self.read_pipe.poll()
|
||||||
|
|
||||||
def complete(self):
|
def complete(self):
|
||||||
"""Waits (if needed) for the child process to complete
|
"""Wait (if needed) for child process to complete
|
||||||
and returns its exit status.
|
and return its exit status.
|
||||||
|
|
||||||
See ``complete_build_process()``.
|
See ``complete_build_process()``.
|
||||||
"""
|
"""
|
||||||
@ -1295,13 +1323,13 @@ def start_build_process(
|
|||||||
|
|
||||||
Args:
|
Args:
|
||||||
pkg: package whose environment we should set up the
|
pkg: package whose environment we should set up the
|
||||||
child process for.
|
child process for.
|
||||||
function: argless function to run in the child
|
function: argless function to run in the child
|
||||||
process.
|
process.
|
||||||
kwargs: additional keyword arguments to pass to ``function()``
|
kwargs: additional keyword arguments to pass to ``function()``
|
||||||
timeout: maximum time allowed to finish the execution of function
|
timeout: maximum time allowed to finish the execution of function
|
||||||
|
|
||||||
Usage:
|
Usage::
|
||||||
|
|
||||||
def child_fun():
|
def child_fun():
|
||||||
# do stuff
|
# do stuff
|
||||||
@ -1420,7 +1448,7 @@ def exitcode_msg(process):
|
|||||||
return child_result
|
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):
|
def get_package_context(traceback, context=3):
|
||||||
|
@ -1337,7 +1337,7 @@ def __init__(
|
|||||||
run tests for some
|
run tests for some
|
||||||
use_cache: Install from binary package, if available.
|
use_cache: Install from binary package, if available.
|
||||||
verbose: Display verbose build output (by default, suppresses it)
|
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):
|
if isinstance(explicit, bool):
|
||||||
explicit = {pkg.spec.dag_hash() for pkg in packages} if explicit else set()
|
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."""
|
"""Attempts to start a package installation."""
|
||||||
pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec
|
pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec
|
||||||
install_status.next_pkg(pkg)
|
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}")
|
tty.debug(f"Processing {pkg_id}: task={task}")
|
||||||
|
|
||||||
# Skip the installation if the spec is not being installed locally
|
# 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):
|
if _handle_external_and_upstream(pkg, task.explicit):
|
||||||
term_status.clear()
|
term_status.clear()
|
||||||
self._flag_installed(pkg, task.dependents)
|
self._flag_installed(pkg, task.dependents)
|
||||||
return None
|
return
|
||||||
|
|
||||||
# Flag a failed spec. Do not need an (install) prefix lock since
|
# Flag a failed spec. Do not need an (install) prefix lock since
|
||||||
# assume using a separate (failed) prefix lock file.
|
# assume using a separate (failed) prefix lock file.
|
||||||
@ -2134,7 +2134,7 @@ def start_task(task) -> None:
|
|||||||
if self.fail_fast:
|
if self.fail_fast:
|
||||||
raise spack.error.InstallError(fail_fast_err, pkg=pkg)
|
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
|
# Attempt to get a write lock. If we can't get the lock then
|
||||||
# another process is likely (un)installing the spec or has
|
# 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.
|
# -- failed, installed, or uninstalled -- on the next pass.
|
||||||
if lock is None:
|
if lock is None:
|
||||||
self._requeue_task(task, install_status)
|
self._requeue_task(task, install_status)
|
||||||
return None
|
return
|
||||||
|
|
||||||
term_status.clear()
|
term_status.clear()
|
||||||
|
|
||||||
@ -2163,7 +2163,7 @@ def start_task(task) -> None:
|
|||||||
task.request.overwrite_time = time.time()
|
task.request.overwrite_time = time.time()
|
||||||
|
|
||||||
# Determine state of installation artifacts and adjust accordingly.
|
# 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)
|
self._prepare_for_install(task)
|
||||||
|
|
||||||
# Flag an already installed package
|
# Flag an already installed package
|
||||||
@ -2187,7 +2187,7 @@ def start_task(task) -> None:
|
|||||||
# or uninstalled -- on the next pass.
|
# or uninstalled -- on the next pass.
|
||||||
self.installed.remove(pkg_id)
|
self.installed.remove(pkg_id)
|
||||||
self._requeue_task(task, install_status)
|
self._requeue_task(task, install_status)
|
||||||
return None
|
return
|
||||||
|
|
||||||
# Having a read lock on an uninstalled pkg may mean another
|
# Having a read lock on an uninstalled pkg may mean another
|
||||||
# process completed an uninstall of the software between the
|
# process completed an uninstall of the software between the
|
||||||
@ -2200,16 +2200,15 @@ def start_task(task) -> None:
|
|||||||
if ltype == "read":
|
if ltype == "read":
|
||||||
lock.release_read()
|
lock.release_read()
|
||||||
self._requeue_task(task, install_status)
|
self._requeue_task(task, install_status)
|
||||||
return None
|
return
|
||||||
|
|
||||||
# Proceed with the installation since we have an exclusive write
|
# Proceed with the installation since we have an exclusive write
|
||||||
# lock on the package.
|
# 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}")
|
install_status.set_term_title(f"Installing {task.pkg.name}")
|
||||||
action = self._install_action(task)
|
action = self._install_action(task)
|
||||||
|
|
||||||
if action == InstallAction.INSTALL:
|
if action == InstallAction.INSTALL:
|
||||||
|
# Start a child process for a task that's ready to be installed.
|
||||||
task.start()
|
task.start()
|
||||||
tty.msg(install_msg(pkg_id, self.pid, install_status))
|
tty.msg(install_msg(pkg_id, self.pid, install_status))
|
||||||
active_tasks.append(task)
|
active_tasks.append(task)
|
||||||
@ -2321,7 +2320,6 @@ def complete_task(task) -> None:
|
|||||||
self._clear_removed_tasks()
|
self._clear_removed_tasks()
|
||||||
if self.build_pq:
|
if self.build_pq:
|
||||||
task = self._pop_task()
|
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"
|
assert task.priority != 0, "Found ready task after _peek_ready_task returned None"
|
||||||
# If the spec has uninstalled dependencies
|
# If the spec has uninstalled dependencies
|
||||||
# and no active tasks running, then there must be
|
# 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]
|
left = [dep_id for dep_id in task.uninstalled_deps if dep_id not in self.installed]
|
||||||
if not left:
|
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"
|
dep_str = "dependencies" if task.priority > 1 else "dependency"
|
||||||
|
|
||||||
raise spack.error.InstallError(
|
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)}",
|
f"{dep_str}: {','.join(task.uninstalled_deps)}",
|
||||||
pkg=task.pkg,
|
pkg=task.pkg,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user