-
Notifications
You must be signed in to change notification settings - Fork 109
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
Add support for dynamically loaded libraries #138
Conversation
(My use case for this is loading Oculus's implementation of OpenXR on Oculus Quest) |
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.
Thanks! That looks simple enough!
Don't forget to add this feature to the relevant cargo-apk/ndk-build changelogs, please :)
Ok, done the requested changes. |
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.
Looks ok. Although maybe you want a custom build.rs that uses cargo-apk as a library instead?
@dvc94ch What exactly do you mean with this? |
but you could add an additional library to the apk, we even have an api for it https://github.com/rust-windowing/android-ndk-rs/blob/master/ndk-build/src/apk.rs#L136 |
It doesn't look possible to do this with the public API currently exposed by cargo-apk. I would need a hook to perform operations on the unaligned apk to make it possible. But maybe I'm missing something? |
@dvc94ch That is exactly the function called by this PR from The current caller of |
@dvc94ch Ah, you want to call However: it might be a good idea to make this behaviour configurable. If we add this path as an optional configuration option to |
my point is that someone has to manually copy them in to the libs folder which isn't a cargo recognized folder as far as I know. So maybe setting an env variable OCULUS_SDK and using a build.rs would be more convenient (my distro wouldn't install it in a cargo target folder anyway). I do see that the current ApkBuilder exposed by cargo-apk isn't very convenient for this use case, but maybe we can add a constructor that doesn't require cargo-subcommand to work? I'd certainly favor making the cargo-apk api more user friendly than adding "hacks". But I'm also not opposed to this PR. |
That's what I originally intended to do, but one problem I see with that is that the |
I don't think it'd install them in any easily accessible location anyway, assuming you're running the SDK and development on an x86 PC and the libraries likely available for the common mobile processors (arm and aarch64).
@dvc94ch has a good point: it'd be nice if we could support system locations as well, ie. In the end we might want to settle on a more generic way to include extra files, as we already do for resources and assets. |
For my specific use-case there would be a manual step in any case, as I don't think I can freely distribute the shared library (as part of a published crate or otherwise) anyway. It has to be manually downloaded from the Oculus Developper website as far as I know. I understand that loading dynamic libraries at runtime may not be a common enough use-case to justify direct support in cargo-apk, so I'm open to discussing the alternative (providing a finer-grained API). |
well that won't work since it's os/distro specific. that's why I suggested a build.rs that uses an env variable to find the right
It's not that I think it's not common enough, but that I think it would be a better solution as manually keeping stuff in sync is annoying. Also as a (not really) maintainer I want to keep the codebase as small as possible. |
@agrande FWIW APKs are just ZIPs, it doesn't seem to bad to me to just have some option in |
Oh, right, I didn't see it before, my bad.
Agreed with that. |
@dvc94ch Exactly, it's just an example and we might want to expand globs, walk symlinks and resolve environment variables to make it so.
APKs support multiple architectures so it shouldn't be a problem to add them all? It is of course cleaner to use just the architectures listed in EDIT: I don't remember if we actually generate a unique APK per architecture instead of one that contains libraries for all targets. |
Let's please not add a dsl for this use-case. I don't understand why a build.rs isn't ok. I guess one problem is that the build.rs would have to be in the binary. But you could have an |
I guess I'm a little biased. cargo-apk and ndk-build were ment to be libraries so that you could build more sophisticated things like cargo-flutter for example. But cargo-flutter died anyway, so maybe there are not that many usecases left for a more flexible api. |
Hehe of course not, we have to settle on something that is common and generic.
The only reason is that I don't see an example of how to use this from |
I'm pretty sad that for example Perhaps we should just add and release a thing like that and see how it goes, as mentioned in the other issue. |
Let's not forget that cargo-ndk happened before ndk-build existed ;) the old cargo-apk and cargo-ndk were inspiration for this cargo-apk |
That sums it up pretty well for me.
I think this is the best way to handle my use-case without being too specific. |
Made a more generic PR: #141 |
@agrande Yup it looks like you have about everything now. We ended up merging #106 as that was already scheduled around the weekend, and has some overlap in the struct changes you did here. Apologies for the conflicts, but they should be easier to solve here than to conflate and delay that significant change even further. I hope that's okay for you to resolve. I don't think you need to store |
Furthermore I briefly mentioned potential slowness/overhead in repeatedly calling |
@MarijnS95 no problem, I'll resolve the conflicts. |
ndk-build/src/apk.rs
Outdated
search_paths: &[&Path], | ||
) -> Result<(), NdkError> { | ||
let abi_dir = path.join(target.android_abi()); | ||
if abi_dir.is_dir() { |
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.
an error message would be good if this condition fails
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.
Just printing a warning, or do you think I should return an error (such as NdkError::PathNotFound
)?
That would stop the process. I'm not sure that's what we want here.
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.
It definitely needs to be an error since the user explicitly configures this path and should be told when it doesn't exist instead of silently going unnoticed (ie. typo, capitalization mismatch in the name).
You don't really need to do anything though - just remove if abi_dir.is_dir()
and let fs::read_dir(abi_dir)?
boil up the error if the path is invalid.
Though OTOH io::Error
doesn't include the path leading to usual generic "file not found" message without any context. We should add a new error message expanding Io(#[from] IoError)
with something like IoPath(#[source] IoError, String)
and .map_err(|io| IoError(io, path)
, but that's something for a different PR and to be applied globally! I can take care of this later unless you feel like adding it.
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 removed if abi_dir.is_dir()
for now.
I don't mind making a PR for the error mapping at a later time if needed.
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.
In hindsight I don't see much if any applicable error unwraps (comment out IoError
and follow all compiler errors for missing From implementations), feel free to add this for just this case in this PR.
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'm not sure exactly how to do that, to be honest (still very much new to Rust), but I'll look into it.
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.
It's a fairly trivial thing to do. Instead of explaining I pushed another commit to this PR showing how :)
The error string isn't all too pretty but it's hard to provide a proper string when we have no idea what error occurred; just that we know it happened while interacting with the specified path.
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.
Thanks! 😀
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.
Yw! Any suggestions for a better string name though? And we could apply this to a few other locations but I'll reconsider where in a future PR.
Co-authored-by: Marijn Suijten <[email protected]>
This is to make sure an error is returned when abi_dir is invalid.
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.
Cool!
I think we're done here now? Nice little change to get in 🙂
@dvc94ch @msiglreith Ping 🙂 This is blocking progress on openxrs and bevy. |
Sometimes we need to add .so libraries to the apk that are not linked against the binary, with the intent of loading them dynamically with
dlopen()
.This commit allows to do that by placing those libraries at the root of the local package, in a
lib/${androideabi}
folder.The build command now scans for those folders and adds the found .so files to the apk with
aapt
.