Merge pull request #167397 from samuela/samuela/autopatchelf

autoPatchelfHook: more precise dependency ignorance

authored by

Samuel Ainsworth and committed by
GitHub
263292cb 1aba4dff

+34 -21
+1 -1
doc/stdenv/stdenv.chapter.md
··· 1043 1043 1044 1044 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. 1045 1045 1046 - 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. 1046 + 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. 1047 1047 1048 1048 The `autoPatchelf` command also recognizes a `--no-recurse` command line flag, which prevents it from recursing into subdirectories. 1049 1049
+23 -17
pkgs/build-support/setup-hooks/auto-patchelf.py
··· 1 1 #!/usr/bin/env python3 2 2 3 - from collections import defaultdict 4 - from contextlib import contextmanager 5 - from dataclasses import dataclass 6 - from elftools.common.exceptions import ELFError # type: ignore 7 - from elftools.elf.dynamic import DynamicSection # type: ignore 8 - from elftools.elf.elffile import ELFFile # type: ignore 9 - from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI # type: ignore 10 - from itertools import chain 11 - from pathlib import Path, PurePath 12 - 13 - from typing import Tuple, Optional, Iterator, List, DefaultDict, Set 14 - 15 3 import argparse 16 4 import os 17 5 import pprint 18 6 import subprocess 19 7 import sys 8 + from collections import defaultdict 9 + from contextlib import contextmanager 10 + from dataclasses import dataclass 11 + from itertools import chain 12 + from pathlib import Path, PurePath 13 + from typing import DefaultDict, Iterator, List, Optional, Set, Tuple 20 14 15 + from elftools.common.exceptions import ELFError # type: ignore 16 + from elftools.elf.dynamic import DynamicSection # type: ignore 17 + from elftools.elf.elffile import ELFFile # type: ignore 18 + from elftools.elf.enums import ENUM_E_TYPE, ENUM_EI_OSABI # type: ignore 21 19 22 20 23 21 @contextmanager ··· 246 244 lib_dirs: List[Path], 247 245 runtime_deps: List[Path], 248 246 recursive: bool =True, 249 - ignore_missing: bool =False) -> None: 247 + ignore_missing: List[str] = []) -> None: 250 248 251 249 if not paths_to_patch: 252 250 sys.exit("No paths to patch, stopping.") ··· 264 262 missing = [dep for dep in dependencies if not dep.found] 265 263 266 264 # Print a summary of the missing dependencies at the end 265 + print(f"auto-patchelf: {len(missing)} dependencies could not be satisfied") 266 + failure = False 267 267 for dep in missing: 268 - print(f"auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}") 268 + if dep.name.name in ignore_missing or "*" in ignore_missing: 269 + print(f"warn: auto-patchelf ignoring missing {dep.name} wanted by {dep.file}") 270 + else: 271 + print(f"error: auto-patchelf could not satisfy dependency {dep.name} wanted by {dep.file}") 272 + failure = True 269 273 270 - if missing and not ignore_missing: 274 + if failure: 271 275 sys.exit('auto-patchelf failed to find all the required dependencies.\n' 272 - 'Add the missing dependencies to --libs or use --ignore-missing.') 276 + 'Add the missing dependencies to --libs or use ' 277 + '`--ignore-missing="foo.so.1 bar.so etc.so"`.') 273 278 274 279 275 280 def main() -> None: ··· 280 285 'libraries in the provided paths.') 281 286 parser.add_argument( 282 287 "--ignore-missing", 283 - action="store_true", 288 + nargs="*", 289 + type=str, 284 290 help="Do not fail when some dependencies are not found.") 285 291 parser.add_argument( 286 292 "--no-recurse",
+8 -1
pkgs/build-support/setup-hooks/auto-patchelf.sh
··· 53 53 esac 54 54 done 55 55 56 + if [ "${autoPatchelfIgnoreMissingDeps[*]}" == "1" ]; then 57 + echo "autoPatchelf: WARNING: setting 'autoPatchelfIgnoreMissingDeps" \ 58 + "= true;' is deprecated and will be removed in a future release." \ 59 + "Use 'autoPatchelfIgnoreMissingDeps = [ \"*\" ];' instead." >&2 60 + autoPatchelfIgnoreMissingDeps=( "*" ) 61 + fi 62 + 56 63 local runtimeDependenciesArray=($runtimeDependencies) 57 64 @pythonInterpreter@ @autoPatchelfScript@ \ 58 65 ${norecurse:+--no-recurse} \ 59 - ${autoPatchelfIgnoreMissingDeps:+--ignore-missing} \ 66 + --ignore-missing "${autoPatchelfIgnoreMissingDeps[@]}" \ 60 67 --paths "$@" \ 61 68 --libs "${autoPatchelfLibs[@]}" \ 62 69 "${extraAutoPatchelfLibs[@]}" \
+1 -1
pkgs/development/libraries/openvino/default.nix
··· 90 90 cd ../build 91 91 ''; 92 92 93 - autoPatchelfIgnoreMissingDeps = true; 93 + autoPatchelfIgnoreMissingDeps = [ "libngraph_backend.so" ]; 94 94 95 95 nativeBuildInputs = [ 96 96 cmake
+1 -1
pkgs/tools/games/opentracker/default.nix
··· 52 52 xinput 53 53 ]; 54 54 55 - autoPatchelfIgnoreMissingDeps = true; # Attempts to patchelf unneeded SOs 55 + autoPatchelfIgnoreMissingDeps = [ "libc.musl-x86_64.so.1" ]; # Attempts to patchelf unneeded SOs 56 56 57 57 meta = with lib; { 58 58 description = "A tracking application for A Link to the Past Randomizer";