Commit Graph

41 Commits

Author SHA1 Message Date
Qyriad
2ad2295bb3 autoPatchelfHook: move multiline hook into a function
In NixOS/nixpkgs#290081 it came to attention that autoPatchelfHook is
one of if not the only hook in Nixpkgs that is a multiline string
expression. Almost all hooks are functions, which guard with something
like `if [ -z "${dontDoTheThing-}" ]; then ...` in the function, or
single-line strings which include that guard inline and then call the
real function, e.g. `if [ -z "${dontDoTheThing-} ]; then doTheThing; fi`.

This commit moves autoPatchelfHook to the former, which seems to be the
most common style now.
2024-03-17 09:48:43 -06:00
Connor Baker
45901c42fc auto-patchelf: improve deprecation check by searching all elements 2023-12-14 16:53:34 +00:00
Connor Baker
9faad7fb0b auto-patchelf: add support for __structuredAttrs 2023-12-14 16:32:29 +00:00
K900
10cb2bd443 autoPatchelfHook: add patchelfFlags option
This may be useful. Eventually. Maybe.
2023-09-30 10:26:35 +03:00
Someone Serge
b612fe36b2
autoPatchelfHook: add appendRunpaths argument 2023-04-13 19:12:37 +03:00
Artturin
af70ba03d3 build-support/setup-hooks: change shebang to shellcheck directive 2022-12-13 00:24:33 +02:00
Artturin
238a6053c4 stdenv: support opt-in __structuredAttrs
Co-authored-by: Robin Gloster <mail@glob.in>

stdenv: print message if structuredAttrs is enabled

stdenv: add _append

reduces the chance of a user doing it wrong

fix nix develop issue

output hooks don't work yet in nix develop though

making $outputs be the same on non-structuredAttrs and structuredAttrs
is too much trouble.

lets instead make a function that gets the output names

reading environment file '/nix/store/2x7m69a2sm2kh0r6v0q5s9z1dh41m4xf-xz-5.2.5-env-bin'
nix: src/nix/develop.cc:299: std::string Common::makeRcScript(nix::ref<nix::Store>, const BuildEnvironment&, const Path&): Assertion `outputs != buildEnvironment.vars.end()' failed.

use a function to get all output names instead of using $outputs

copy env functionality from https://github.com/NixOS/nixpkgs/pull/76732/commits
2022-12-08 06:13:19 +02:00
adisbladis
41c09640e7 autoPatchelfHook: fix turning [ "*" ] into bash array
Previously globs were incorrectly handled and expanded by bash into the files in the temporary build directory.
2022-10-10 17:55:11 +13:00
Lin Yinfeng
bedc267a78
autoPatchelfHook: fix precise dependency ignorance
This commit fixes precise dependency ignorance by converting the
environment variable `autoPatchelfIgnoreMissingDeps` into a bash array
`ignoreMissingDepsArray`, passing `"${ignoreMissingDepsArray[@]}"`
instead of `"${autoPatchelfIgnoreMissingDeps[@]}"` to the python
script.

The original implementation does not work when
`autoPatchelfIgnoreMissingDeps` contains multiple dependency names.
Because it mistakenly passes `"${autoPatchelfIgnoreMissingDeps[@]}"`
to the python script. According to the Nix manual
(https://nixos.org/manual/nix/stable/expressions/derivations.html),
lists of strings are concatenated into whitespace-separated strings,
then passed to the builder as environment variables. So, if
`autoPatchelfIgnoreMissingDeps = [ "dep1" "dep2" "dep3" ]`,
`"${autoPatchelfIgnoreMissingDeps[@]}"` will be expanded to a single
argument `"dep1 dep2 dep3"`, which is not the intended behavior,
because the python script takes the long argument as a dependency
name.

With this commit, `"${ignoreMissingDepsArray[@]}"` will be expanded to
three arguments `"dep1" "dep2" "dep3"` arguments as expected, fixing
the issue.
2022-04-15 10:35:11 +08:00
Samuel Ainsworth
a7fc2f6392 autoPatchelfHook: more precise dependency ignorance 2022-04-11 01:28:55 +00:00
Guillaume Maudoux
7b9fd5d1c9
rewrite autoPatchelfHook in python (#149731)
* rewrite autoPatchelfHook in python

* Update pkgs/build-support/setup-hooks/auto-patchelf.py

Co-authored-by: aszlig <aszlig@redmoonstudios.org>

* Update pkgs/build-support/setup-hooks/auto-patchelf.py

Co-authored-by: aszlig <aszlig@redmoonstudios.org>

* Apply suggestions from code review

Co-authored-by: aszlig <aszlig@redmoonstudios.org>

* Fix issues discovered during tests

* Apply suggestions from code review

Co-authored-by: aszlig <aszlig@redmoonstudios.org>

* fixup line wrapping

* autoPatchelfHook: Improve compatibility with bash version

* autoPatchelfHook: Fix symlink-reated issues

* autoPatchelfHook: Revert dubious patchelf invocation test

* autoPatchelfHook: Untangle the executable detection logic

* fixup! autoPatchelfHook: Untangle the executable detection logic

* autoPatchelfHook: Fix invalid borrow issue

* autoPatchelfHook: Handle runtimeDependencies as the bare string it is

* autoPatchelfHook: add bintools dependency

For the very rare cases where it is not included by default.

* autoPatchelfHook: replace old hook with the rewrite

* autoPatchelfHook: get rid of the old hook content

* autoPatchelfHook: fix wrong ordering of debug info

* autoPatchelfHook: persist extra search path across incovations

* autoPatchelfHook: fix wrong usage of global variables

* Update auto-patchelf.py

PEP8: ignoreMissing -> ignore_missing

* Apply suggestions from code review

Co-authored-by: aszlig <aszlig@redmoonstudios.org>

* autoPatchelfHook: remove imprecise and incorrect warning

* Apply explicit types from code review

Co-authored-by: Jörg Thalheim <Mic92@users.noreply.github.com>

* Complement and polish types and snake_casing

Co-authored-by: aszlig <aszlig@redmoonstudios.org>
Co-authored-by: Jörg Thalheim <Mic92@users.noreply.github.com>
2022-02-04 10:08:27 +01:00
Noah Fontes
a7f5e8321e
autoPatchelfHook: fix packages that use stdenvNoCC
autoPatchelfHook actually doesn't depend on stdenv and only needs
bintools (with its wrapper). This change uses $NIX_BINTOOLS instead of
$NIX_CC and makes the dependency on bintools explicit.
2021-09-18 21:58:02 -07:00
Noah Fontes
4765a3e153
autoPatchelfHook: improve arch/ABI compatibility
Fully enabling crossSystem support for autoPatchelfHook came with some
perhaps unintended consequences of being a bit more aggressive about
patching ELF files from architectures/ABIs that differ from the target
(previously, those files would be ignored because ldd usually couldn't
handle them).

This change adds architecture and rough OS ABI detection to the script
so that it doesn't try to blindly replace the interpreter of files that
can't possibly use that interpreter, and also makes sure it doesn't
accidentally use libraries of other architectures/ABIs.
2021-09-18 21:57:08 -07:00
Noah Fontes
b79483d2b7
autoPatchelfHook: fix detection under crossSystem
In #84415, autoPatchelfHook was taught to use the correct path to the
readelf binary when a crossSystem is specified. Unfortunately, the
remainder of the functionality in the script depended on ldd, which only
reads ELF files of its own architecture. It has the further unfortunate
quality of not reporting any useful error, but rather that the file is
not a dynamic executable.

This change uses patchelf to directly analyze the DT_NEEDED tags in the
target files instead, which correctly works across architectures. It
also updates the use of objdump to be prefix-aware $OBJDUMP (which would
have been required in the PR mentioned above, but we never made it that
far into the script execution).
2021-09-12 15:07:15 -07:00
happysalada
f3d9711f05 stdenv: add link to clarify 2021-07-19 14:50:01 +09:00
DavHau
2efcf6dc26 autoPatchelf: add comment why ignore failing ldd/sed 2020-12-25 12:13:03 +01:00
DavHau
2fde1e63ba autoPatchelfHook: fix shellcheck errors 2020-12-25 12:13:03 +01:00
DavHau
4ac5d22654 autoPatchelfHook: fix bug introduced by #101142 2020-12-25 12:13:03 +01:00
DavHau
05fa0f1a2e improve things shellcheck complains about 2020-11-07 18:08:48 +07:00
DavHau
112f275f4d
autoPatchelfHook: fix typos in comments 2020-10-26 17:17:07 +07:00
DavHau
b9d2541a37
autoPatchelfHook: store dependant for dependency 2020-10-23 13:21:08 +07:00
DavHau
f833f0406f
autoPatchelfHook: print dependant for missing deps 2020-10-23 13:16:23 +07:00
DavHau
11a08bcfad
Apply suggestions from code review
Co-authored-by: symphorien <symphorien@users.noreply.github.com>
Co-authored-by: Sandro <sandro.jaeckel@gmail.com>
2020-10-22 10:15:42 +07:00
DavHau
5c382b7f0e autoPatchelfHook: optimize performance, better error handling 2020-10-20 19:09:32 +07:00
DavHau
c8c09b7dda add autoPatchelfIgnoreMissingDeps to auto-patchelf.sh 2020-06-22 10:41:35 +02:00
Matthew Bauer
433d5178ca setup-hooks/auto-patchelf.sh: get prefixed readelf 2020-04-06 16:36:29 -04:00
John Ericson
2811b032d6 treewide: Make still dont* Variables are optional in most cases
Go beyond the obvious setup hooks now, with a bit of sed, with a skipped case:

 - cc-wrapper's `dontlink`, because it already is handled.

Also, in nix files escaping was manually added.

EMP
2019-11-01 14:44:44 -04:00
Danylo Hlynskyi
de0612c46c
auto-patchelf: don't use grep -q, as it causes Broken pipe (#56958)
This rare sitation was caught when building zoom-us package:
```
automatically fixing dependencies for ELF files
/nix/store/71d65fplq44y9yn2fvkpn2d3hrszracd-auto-patchelf-hook/nix-support/setup-hook: line 213: echo: write error: Broken pipe
/nix/store/71d65fplq44y9yn2fvkpn2d3hrszracd-auto-patchelf-hook/nix-support/setup-hook: line 210: echo: write error: Broken pipe
```

The worst is that derivation continued and resulted into broken package:
https://github.com/NixOS/nixpkgs/pull/55566#issuecomment-470065690

I hope, replacing `grep -q` with `grep` will remove this race condition.
2019-03-20 14:57:59 +02:00
aszlig
4a6e3e4185
autoPatchelfHook: Skip on missing segment headers
If the file in question is not a shared object file but an ELF, we
really want to skip the file, because we won't have anything to patch
there.

For example if the file is created via "gcc -c -o foo.o foo.c", we don't
get a segment header and so far autoPatchelf was trying to patch such a
file.

By checking for missing segment headers, we're now no longer going to
attempt patching such a file.

Signed-off-by: aszlig <aszlig@nix.build>
Reported-by: Sander van der Burg <svanderburg@gmail.com>
2018-11-26 01:58:36 +01:00
aszlig
9f23a63f79
autoPatchelfHook: Fix type of norecurse variable
While declaring it as an array doesn't do any harm in our usage, it
might be a bit confusing when reading the code.

Signed-off-by: aszlig <aszlig@nix.build>
2018-11-26 01:13:59 +01:00
aszlig
2faf905f98
autoPatchelfHook: Add addAutoPatchelfSearchPath
This function is useful if autoPatchelf is invoked during some of the
phases of a build and allows to add arbitrary shared objects to the
search path.

So far the same functionality was in autoPatchelf itself, but not
available as a separate function, so when adding shared objects to the
dependency cache one would have to do so manually.

The function also has the --no-recurse flag, which prevents recursing
into subdirectories.

Signed-off-by: aszlig <aszlig@nix.build>
2018-11-25 16:22:32 +01:00
aszlig
3ca35ce0b2
autoPatchelfHook: Add --no-recurse flag
This is to be used with the autoPatchelf command and allows to only
patch a specific file or directory without recursing into
subdirectories.

Apart from being able to run the command in a standalone way, as
detailled in the previous commit this is also needed for the Android SDK
emulator, because according to @svanderburg there are subdirectories we
don't want to patch.

The reason why I didn't use GNU getopt is that it might not be available
on all operating systems and the getopts bash builtin doesn't support
long arguments. Apart from that, the implementation for recognizing the
flag is pretty trivial and it's also using bash builtins only, so if we
want to do something really fancy someday, we can still change it.

Signed-off-by: aszlig <aszlig@nix.build>
2018-11-20 00:11:29 +01:00
aszlig
e4fbb244ee
autoPatchelfHook: Allow to prevent automatic run
If you want to only run autoPatchelf on a specific path and leave
everything else alone, we now have a $dontAutoPatchelf environment
variable, which causes the postFixup hook to not run at all.

The name "dontAutoPatchelf" probably is a bit weird in conjunction with
putting "autoPatchelfHook" in nativeBuildInputs, but unless someone
comes up with a better name I keep it that way because it's consistent
with all the other dontStrip, dontPatchShebangs, dontPatchELF and
whatnot.

A specific example where this is needed is when building the Android SDK
emulator, which contains a few ARM binaries in subdirectories that
should not be patched. If we were to run autoPatchelf on all outputs
unconditionally we'd run into errors because some ARM libraries couldn't
be found.

Signed-off-by: aszlig <aszlig@nix.build>
2018-11-20 00:07:38 +01:00
aszlig
d03e4ffdbf
autoPatchelfHook: Make easier to run autoPatchelf
The autoPatchelf main function which is run against all of the outputs
was pretty much tailored towards this specific setup-hook and was
relying on $prefix to be set globally.

So if you wanted to run autoPatchelf manually - let's say during
buildPhase - you would have needed to run it like this:

  prefix=/some/directory autoPatchelf

This is now more intuitive and all you need to do is run the following:

  autoPatchelf /some/directory

Signed-off-by: aszlig <aszlig@nix.build>
2018-11-19 17:18:27 +01:00
aszlig
c64624b843
autoPatchelfHook: Correctly detect PIE binaries
I originally thought it would just be enough to just check for an INTERP
section in isExecutable, however this would mean that we don't detect
statically linked ELF files, which would break our recent improvement to
gracefully handle those.

In theory, we are only interested in ELF files that have an INTERP
section, so checking for INTERP would be enough. Unfortunately the
isExecutable function is already used outside of autoPatchelfHook, so we
can't easily get rid of it now, so let's actually strive for more
correctness and make isExecutable actually match ELF files that are
executable.

So what we're doing instead now is to check whether either the ELF type
is EXEC *or* we have an INTERP section and if one of them is true we
should have an ELF executable, even if it's statically linked.

Along the way I also set LANG=C for the invocations of readelf, just to
be sure we don't get locale-dependent output.

Tested this with the following command (which contains almost[1] all the
packages using autoPatchelfHook), checking whether we run into any
library-related errors:

  nix-build -E 'with import ./. { config.allowUnfree = true; };
    runCommand "test-executables" {
      drvs = [
        anydesk cups-kyodialog3 elasticsearch franz gurobi
        masterpdfeditor oracle-instantclient powershell reaper
        sourcetrail teamviewer unixODBCDrivers.msodbcsql17 virtlyst
        vk-messenger wavebox zoom-us
      ];
    } ("for i in $drvs; do for b in $i/bin/*; do " +
       "[ -x \"$b\" ] && timeout 10 \"$b\" || :; done; done")
  '

Apart from testing against library-related errors I also compared the
resulting store paths against the ones prior to this commit. Only
anydesk and virtlyst had the same as they didn't have self-references,
everything else differed only because of self-references, except
elasticsearch, which had the following PIE binaries:

  * modules/x-pack/x-pack-ml/platform/linux-x86_64/bin/autoconfig
  * modules/x-pack/x-pack-ml/platform/linux-x86_64/bin/autodetect
  * modules/x-pack/x-pack-ml/platform/linux-x86_64/bin/categorize
  * modules/x-pack/x-pack-ml/platform/linux-x86_64/bin/controller
  * modules/x-pack/x-pack-ml/platform/linux-x86_64/bin/normalize

These binaries were now patched, which is what this commit is all about.

[1]: I didn't include the "maxx" package (MaXX Interactive Desktop)
     because the upstream URLs are no longer existing and I couldn't
     find them elsewhere on the web.

Signed-off-by: aszlig <aszlig@nix.build>
Fixes: https://github.com/NixOS/nixpkgs/issues/48330
Cc: @gnidorah (for MaXX Interactive Desktop)
2018-11-03 08:07:42 +01:00
aszlig
b4526040a2
autoPatchelfHook: Silence errors in isExecutable
The "maxx" package recursively runs isExecutable on a bunch of files and
since the change to use "readelf" instead of "file" a lot of errors like
this one are printed during build:

  readelf: Error: Not an ELF file - it has the wrong magic bytes at the
  start

While the isExecutable was never meant to be used outside of the
autoPatchelfHook, it's still a good idea to silence the errors because
whenever readelf fails, it clearly indicates that the file in question
is not a valid ELF file.

Signed-off-by: aszlig <aszlig@nix.build>
2018-09-25 04:48:12 +02:00
aszlig
9920215d00
autoPatchelfHook: Only check PT_INTERP on execs
If the ELF file is not an executable, we do not get a PT_INTERP section,
because after all, it's a *shared* library.

So instead of checking for PT_INTERP (to avoid statically linked
executables) for all ELF files, we add another check to see if it's an
executable and *only* skip it when it is and there's no PT_INTERP.

Signed-off-by: aszlig <aszlig@nix.build>
2018-09-25 04:42:34 +02:00
Jörg Thalheim
58a97dfb49 autoPatchelfHook: do not patch statically linked files
Also speed up quite significantly due less forking.
2018-09-23 21:33:43 +01:00
aszlig
f1fbf818c4
autoPatchelfHook: Run after patchelf's setup hook
So far the runtimeDependencies variable has been rather useless unless
you also set dontPatchelf, because the patchelf setup hook ran *after*
the autoPatchelfHook and thus stripped off the additional RPATHs added
using runtimeDependencies.

I did this by moving the autoPatchelfHook to be run in postFixup instead
of fixupOutput, however I needed to replicate the for loop that runs the
hook on all outputs.

Until we have a way to influence order of execution for hooks I've
marked this with an XXX so that we can use fixupOutput again.

Tested this against all packages that use autoPatchelfHook using the
following and checking whether the output contains any errors concerning
shared libraries:

nix-build -E 'with import ./. { config.allowUnfree = true; };
  runCommand "test-executables" {
    drvs = [
      masterpdfeditor franz zoom-us anydesk teamviewer maxx
      oracle-instantclient cups-kyodialog3 virtlyst powershell
    ];
  } "for i in $drvs; do for b in $i/bin/*; do \"$b\" || :; done; done"
'

Signed-off-by: aszlig <aszlig@nix.build>
Fixes: https://github.com/NixOS/nixpkgs/issues/43082
Cc: @Ericson2314
2018-07-16 01:52:28 +02:00
aszlig
ff5cecf821
autoPatchelfHook: Patch PIC exes/libs as well
If there is a shared object or executable that's using
position-independent code, the file's mime type is
"application/x-pie-executable", so until this change its dependencies
wouldn't be patched.

This simply adds the mime type to the search loop.

Signed-off-by: aszlig <aszlig@nix.build>
2018-06-08 00:27:31 +02:00
aszlig
1cba74dfc1
setup-hooks: Add autoPatchelfHook
I originally wrote this for packaging proprietary games in Vuizvui[1]
but I thought it would be generally useful as we have a fair amount of
proprietary software lurking around in nixpkgs, which are a bit tedious
to maintain, especially when the library dependencies change after an
update.

So this setup hook searches for all ELF executables and libraries in the
resulting output paths after install phase and uses patchelf to set the
RPATH and interpreter according to what dependencies are available
inside the builder.

For example consider something like this:

stdenv.mkDerivation {
  ...
  nativeBuildInputs = [ autoPatchelfHook ];
  buildInputs = [ mesa zlib ];
  ...
}

Whenever for example an executable requires mesa or zlib, the RPATH will
automatically be set to the lib dir of the corresponding dependency.

If the library dependency is required at runtime, an attribute called
runtimeDependencies can be used to list dependencies that are added to
all executables that are discovered unconditionally.

Beside this, it also makes initial packaging of proprietary software
easier, because one no longer has to manually figure out the
dependencies in the first place.

[1]: https://github.com/openlab-aux/vuizvui

Signed-off-by: aszlig <aszlig@nix.build>
Closes: #34506
2018-02-10 00:27:24 +05:30