New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
autoPatchelfHook: Fixes/improvements for Android SDK emulator #50802
Conversation
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>
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>
Success on x86_64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-darwin (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on aarch64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
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>
First of all, this makes the existing documentation a bit more clear on what autoPatchelfHook is all about, because after discussing with @svanderburg - who wrote a similar implementation - the rationale about autoPatchelfHook wasn't very clear in the documentation. I also added the recent changes around being able to use autoPatchelf manually and the new --no-recurse flag. Signed-off-by: aszlig <aszlig@nix.build>
2c73283
to
503b41b
Compare
Success on x86_64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-darwin (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on aarch64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not tested it, but the code and the documentation make sense to me.
The example from your description would also fit well into the documentation.
Great! I'll try to adjust my androidenv pull request later today and see if it works with the new implementation. I'll report back asap! |
I believe I am still having a practical issue while trying to migrate the Android SDK expressions to the autopatchelf hook implementation. Apparently, to use autoPatchelf, you must refer to the libraries that you want to use (through buildInputs or runtimeDependencies) by providing the Nix store paths of the packages that you want to use. The autopatchelf hook seems to scan the I don't think there is a way to directly refer to library paths (without making an assumption that there is a The autopatchelf implementation that I created uses colon separated library paths (as opposed to white space delimited Nix store paths) and can also inspect library sub folders in the same package. Is there also a way to add this kind of flexibility to the autopatchelf hook? (As a sidenote: my original motivation to use colon separated library paths is that you can use My biggest struggle is to port the expression that patches the Android emulator. It needs external packages, as well as libraries that are bundled with the emulator package itself, as you may probably see while inspecting contents of this file: https://github.com/svanderburg/nix-androidenvtests/blob/nextgen/androidenv/emulator.nix In the expression, I refer to Nix packages (and use Would it also be possible to do something similar with the autoPatchelf command or adjust it in such a way that it can? |
The library subdirectories for the same package are already inspected by autoPatchelfHook: nixpkgs/pkgs/build-support/setup-hooks/auto-patchelf.sh Lines 174 to 177 in 503b41b
However, when running Maybe it makes sense to add shell function like Does that sound good for you? And would such a function then also recurse into subdirectories or even have the same
Seperately specifying |
I don't need the separation, although I would find it nicer to write it separately, but that's just a matter of taste. I can live without it. Basically, the only problem I have is converting this line in the emulator expression: export libs_x86_64=$packageBaseDir/lib64:$packageBaseDir/lib64/qt/lib:$libs_x86_64 I want autopatchelf to inspect these two directories shown above in addition to the packages that I provide as buildInputs. These two paths translate to: If there's any environment variable (or function) allowing me to provide these paths, so that they get added to the RPATH of the right executables, that will basically fix my problem. |
The example you mentioned can be added via: cachedDependencies+=(
$(find "$out/libexec/android-sdk/emulator/lib64" \
\! -type d \( -name '*.so' -o -name '*.so.*' \))
) That's a lot of churn, so that's why I mentioned factoring this out into a dedicated function, but this should work (haven't tested it though). |
@aszlig Would be nice if you could implement a function wrapper so that I can conveniently add these paths |
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>
@svanderburg: Added the mentioned |
Success on x86_64-darwin (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on aarch64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Great now it seems to work a lot better. I have managed to make the basic test cases work (deploying an SDK installation with some plugins, building an APK, and launching the emulator). Unfortunately, when try to compile the
Apparently, it recurses into a directory that provides an object file (python.o). (As a sidenote: it's really stupid of the Android package maintainers to include this file, but this something we have to live with) |
|
Never mind, got the |
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>
Success on aarch64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-darwin (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
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>
@svanderburg: Fixed, thanks. |
@svanderburg: Btw. regarding the ability to run |
Success on aarch64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Success on x86_64-linux (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Timed out, unknown build status on x86_64-darwin (full log) Attempted: autoPatchelfHook Partial log (click to expand)
|
Hi, I just did another test and the good news is: it seems to work. I now managed to successfully compile the |
This change can be integrated into the upstream branch. I probably have to rebase my Android pull request since it's already conflicting with the current Nixpkgs master branch. |
This is related to #50596, which refactors the
androidenv
implementation.For patching various ELF files, a similar implementation to
autoPatchelfHook
was introduced there and after talking with @svanderburg, I went on to improve the hook in a way so that it's possible to be also used forandroidenv
, which also makes it less confusing for users having two things doing roughly the same but are named similarly.Essentially, these changes make it easier to use only the
autoPatchelf
command without automatically patching all the build outputs.For example:
The
--no-recurse
flag here only patches files within thebar
directory but not files in subdirectories likebar/a/b/c
.In order to make sure these changes do not break existing users of this hook, I've tested it using the following Nix expression and looking for symbol lookup errors: