autoPatchelfHook: more precise dependency ignorance

main
Samuel Ainsworth 2 years ago
parent f22dc92e9f
commit a7fc2f6392
  1. 2
      doc/stdenv/stdenv.chapter.md
  2. 40
      pkgs/build-support/setup-hooks/auto-patchelf.py
  3. 9
      pkgs/build-support/setup-hooks/auto-patchelf.sh

@ -1043,7 +1043,7 @@ You can also specify a `runtimeDependencies` variable which lists dependencies t
In certain situations you may want to run the main command (`autoPatchelf`) of the setup hook on a file or a set of directories instead of unconditionally patching all outputs. This can be done by setting the `dontAutoPatchelf` environment variable to a non-empty value.
By default `autoPatchelf` will fail as soon as any ELF file requires a dependency which cannot be resolved via the given build inputs. In some situations you might prefer to just leave missing dependencies unpatched and continue to patch the rest. This can be achieved by setting the `autoPatchelfIgnoreMissingDeps` environment variable to a non-empty value.
By default `autoPatchelf` will fail as soon as any ELF file requires a dependency which cannot be resolved via the given build inputs. In some situations you might prefer to just leave missing dependencies unpatched and continue to patch the rest. This can be achieved by setting the `autoPatchelfIgnoreMissingDeps` environment variable to a non-empty value. `autoPatchelfIgnoreMissingDeps` can be set to a list like `autoPatchelfIgnoreMissingDeps = [ "libcuda.so.1" "libcudart.so.1" ];` or to simply `[ "*" ]` to ignore all missing dependencies.
The `autoPatchelf` command also recognizes a `--no-recurse` command line flag, which prevents it from recursing into subdirectories.

@ -1,23 +1,21 @@
#!/usr/bin/env python3
from collections import defaultdict
from contextlib import contextmanager
from dataclasses import dataclass
from elftools.common.exceptions import ELFError # type: ignore
from elftools.elf.dynamic import DynamicSection # type: ignore
from elftools.elf.elffile import ELFFile # type: ignore
from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI # type: ignore
from itertools import chain
from pathlib import Path, PurePath
from typing import Tuple, Optional, Iterator, List, DefaultDict, Set
import argparse
import os
import pprint
import subprocess
import sys
from collections import defaultdict
from contextlib import contextmanager
from dataclasses import dataclass
from itertools import chain
from pathlib import Path, PurePath
from typing import DefaultDict, Iterator, List, Optional, Set, Tuple
from elftools.common.exceptions import ELFError # type: ignore
from elftools.elf.dynamic import DynamicSection # type: ignore
from elftools.elf.elffile import ELFFile # type: ignore
from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI # type: ignore
@contextmanager
@ -246,7 +244,7 @@ def auto_patchelf(
lib_dirs: List[Path],
runtime_deps: List[Path],
recursive: bool =True,
ignore_missing: bool =False) -> None:
ignore_missing: List[str] = []) -> None:
if not paths_to_patch:
sys.exit("No paths to patch, stopping.")
@ -264,12 +262,19 @@ def auto_patchelf(
missing = [dep for dep in dependencies if not dep.found]
# Print a summary of the missing dependencies at the end
print(f"auto-patchelf: {len(missing)} dependencies could not be satisfied")
failure = False
for dep in missing:
print(f"auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}")
if dep.name.name in ignore_missing or "*" in ignore_missing:
print(f"warn: auto-patchelf ignoring missing {dep.name} wanted by {dep.file}")
else:
print(f"error: auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}")
failure = True
if missing and not ignore_missing:
if failure:
sys.exit('auto-patchelf failed to find all the required dependencies.\n'
'Add the missing dependencies to --libs or use --ignore-missing.')
'Add the missing dependencies to --libs or use '
'`--ignore-missing="foo.so.1 bar.so etc.so"`.')
def main() -> None:
@ -280,7 +285,8 @@ def main() -> None:
'libraries in the provided paths.')
parser.add_argument(
"--ignore-missing",
action="store_true",
nargs="*",
type=str,
help="Do not fail when some dependencies are not found.")
parser.add_argument(
"--no-recurse",

@ -53,10 +53,17 @@ autoPatchelf() {
esac
done
if [ "${autoPatchelfIgnoreMissingDeps[*]}" == "1" ]; then
echo "autoPatchelf: WARNING: setting 'autoPatchelfIgnoreMissingDeps" \
"= true;' is deprecated and will be removed in a future release." \
"Use 'autoPatchelfIgnoreMissingDeps = [ \"*\" ];' instead." >&2
autoPatchelfIgnoreMissingDeps=( "*" )
fi
local runtimeDependenciesArray=($runtimeDependencies)
@pythonInterpreter@ @autoPatchelfScript@ \
${norecurse:+--no-recurse} \
${autoPatchelfIgnoreMissingDeps:+--ignore-missing} \
--ignore-missing "${autoPatchelfIgnoreMissingDeps[@]}" \
--paths "$@" \
--libs "${autoPatchelfLibs[@]}" \
"${extraAutoPatchelfLibs[@]}" \

Loading…
Cancel
Save