autoPatchelfHook: add keep_libc flag (#332617)

* autoPatchelfHook: add keep_libc flag

- Add keep_libc flag to disable the default libc handling. Intended
to be used by systemd.
- Add autoPatchelfFlags to autoPatchelfHook for passing arguments to
the autoPatchelf script

This reverts part of the change made in #307068 / 80be926.

Fixes #332533

authored by squalus and committed by GitHub 0a3ed67f 1582d762

+29 -6
+24 -6
pkgs/build-support/setup-hooks/auto-patchelf.py
··· 197 197 found: bool = False # Whether it was found somewhere 198 198 199 199 200 - def auto_patchelf_file(path: Path, runtime_deps: list[Path], append_rpaths: list[Path] = [], extra_args: list[str] = []) -> list[Dependency]: 200 + def auto_patchelf_file(path: Path, runtime_deps: list[Path], append_rpaths: list[Path] = [], keep_libc: bool = False, extra_args: list[str] = []) -> list[Dependency]: 201 201 try: 202 202 with open_elf(path) as elf: 203 203 ··· 257 257 # 1. If a candidate is an absolute path, it is already a 258 258 # valid dependency if that path exists, and nothing needs 259 259 # to be done. It should be an error if that path does not exist. 260 - # 2. If a candidate is found in our library dependencies, that 260 + # 2. If a candidate is found within libc, it should be dropped 261 + # and resolved automatically by the dynamic linker, unless 262 + # keep_libc is enabled. 263 + # 3. If a candidate is found in our library dependencies, that 261 264 # dependency should be added to rpath. 262 - # 3. If a candidate is found in libc, it will be correctly 263 - # resolved by the dynamic linker automatically. 265 + # 4. If all of the above fail, libc dependencies should still be 266 + # considered found. This is in contrast to step 2, because 267 + # enabling keep_libc should allow libc to be found in step 3 268 + # if possible to preserve its presence in rpath. 264 269 # 265 270 # These conditions are checked in this order, because #2 266 271 # and #3 may both be true. In that case, we still want to 267 272 # add the dependency to rpath, as the original binary 268 273 # presumably had it and this should be preserved. 274 + 275 + is_libc = (libc_lib / candidate).is_file() 269 276 270 277 if candidate.is_absolute() and candidate.is_file(): 271 278 was_found = True 272 279 break 280 + elif is_libc and not keep_libc: 281 + was_found = True 282 + break 273 283 elif found_dependency := find_dependency(candidate.name, file_arch, file_osabi): 274 284 rpath.append(found_dependency) 275 285 dependencies.append(Dependency(path, candidate, found=True)) 276 286 print(f" {candidate} -> found: {found_dependency}") 277 287 was_found = True 278 288 break 279 - elif (libc_lib / candidate).is_file(): 289 + elif is_libc and keep_libc: 280 290 was_found = True 281 291 break 282 292 ··· 306 316 recursive: bool = True, 307 317 ignore_missing: list[str] = [], 308 318 append_rpaths: list[Path] = [], 319 + keep_libc: bool = False, 309 320 extra_args: list[str] = []) -> None: 310 321 311 322 if not paths_to_patch: ··· 319 330 dependencies = [] 320 331 for path in chain.from_iterable(glob(p, '*', recursive) for p in paths_to_patch): 321 332 if not path.is_symlink() and path.is_file(): 322 - dependencies += auto_patchelf_file(path, runtime_deps, append_rpaths, extra_args) 333 + dependencies += auto_patchelf_file(path, runtime_deps, append_rpaths, keep_libc, extra_args) 323 334 324 335 missing = [dep for dep in dependencies if not dep.found] 325 336 ··· 378 389 help="Paths to append to all runtime paths unconditionally", 379 390 ) 380 391 parser.add_argument( 392 + "--keep-libc", 393 + dest="keep_libc", 394 + action="store_true", 395 + help="Attempt to search for and relink libc dependencies.", 396 + ) 397 + parser.add_argument( 381 398 "--extra-args", 382 399 # Undocumented Python argparse feature: consume all remaining arguments 383 400 # as values for this one. This means this argument should always be passed ··· 398 415 args.recursive, 399 416 args.ignore_missing, 400 417 append_rpaths=args.append_rpaths, 418 + keep_libc=args.keep_libc, 401 419 extra_args=args.extra_args) 402 420 403 421
+3
pkgs/build-support/setup-hooks/auto-patchelf.sh
··· 58 58 local appendRunpathsArray=( "${appendRunpaths[@]}" ) 59 59 local runtimeDependenciesArray=( "${runtimeDependencies[@]}" ) 60 60 local patchelfFlagsArray=( "${patchelfFlags[@]}" ) 61 + local autoPatchelfFlagsArray=( "${autoPatchelfFlags[@]}" ) 61 62 else 62 63 readarray -td' ' ignoreMissingDepsArray < <(echo -n "$autoPatchelfIgnoreMissingDeps") 63 64 local appendRunpathsArray=($appendRunpaths) 64 65 local runtimeDependenciesArray=($runtimeDependencies) 65 66 local patchelfFlagsArray=($patchelfFlags) 67 + local autoPatchelfFlagsArray=($autoPatchelfFlags) 66 68 fi 67 69 68 70 # Check if ignoreMissingDepsArray contains "1" and if so, replace it with ··· 85 87 "${extraAutoPatchelfLibs[@]}" \ 86 88 --runtime-dependencies "${runtimeDependenciesArray[@]/%//lib}" \ 87 89 --append-rpaths "${appendRunpathsArray[@]}" \ 90 + "${autoPatchelfFlagsArray[@]}" \ 88 91 --extra-args "${patchelfFlagsArray[@]}" 89 92 } 90 93
+2
pkgs/os-specific/linux/systemd/default.nix
··· 336 336 ] 337 337 ; 338 338 339 + autoPatchelfFlags = [ "--keep-libc" ]; 340 + 339 341 buildInputs = 340 342 [ 341 343 libxcrypt