Skip to content
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

Refactor library lookup #968

Merged
merged 2 commits into from Dec 11, 2022
Merged

Conversation

eregon
Copy link
Collaborator

@eregon eregon commented Jul 17, 2022

  • Try every prefix, not just the first one where the file exists.
    The first existing file might be for the wrong architecture or have
    other issues and cannot be loaded.
  • Show which directories were searched in error message.
  • Only consider /opt/homebrew/lib on darwin-aarch64.
  • Only rescue LoadError and RuntimeError, not Exception.
  • Refactor in smaller methods to improve readability.
  • Fixes Could not open library 'sodium': dlopen(sodium, 5): image not found. (LoadError) on Apple Silicon M1 #880.
  • Example error message:
    Could not open library 'notexist': notexist: cannot open shared object file: No such file or directory. (LoadError)
    Could not open library 'libnotexist.so': libnotexist.so: cannot open shared object file: No such file or directory.
    Searched in <system library path>, /usr/lib, /usr/local/lib, /opt/local/lib

* Try every prefix, not just the first one where the file exists.
  The first existing file might be for the wrong architecture or have
  other issues and cannot be loaded.
* Show which directories were searched in error message.
* Only consider /opt/homebrew/lib on darwin-aarch64.
* Only rescue LoadError and RuntimeError, not Exception.
* Refactor in smaller functions to improve readability.
* Fixes ffi#880.
* Example error message:
  Could not open library 'notexist': notexist: cannot open shared object file: No such file or directory. (LoadError)
  Could not open library 'libnotexist.so': libnotexist.so: cannot open shared object file: No such file or directory.
  Searched in <system library path>, /usr/lib, /usr/local/lib, /opt/local/lib
* The keys are not used, and the paths are typically already part of the error message.
* Makes it possible to just use a recursive call instead of retry.
@eregon
Copy link
Collaborator Author

eregon commented Jul 17, 2022

@larskanis Could you review this?
I think it basically solves the # TODO better library lookup logic that was in there, and makes the code much easier to read and maintain.

@eregon
Copy link
Collaborator Author

eregon commented Aug 6, 2022

@larskanis Could you take a look?
I could also merge this myself (I'm confident about the change), but we'd still need a release.

Comment on lines +33 to +36
SEARCH_PATH = %w[/usr/lib /usr/local/lib /opt/local/lib]
if FFI::Platform::ARCH == 'aarch64' && FFI::Platform.mac?
SEARCH_PATH << '/opt/homebrew/lib'
end
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this is something you want to handle (and I wouldn't blame you if you don't):

Some Homebrew users install brew to a path that is neither /usr/local nor /opt/homebrew (e.g. they have no sudo access so use their $HOME). For these cases, one approach that works is to check if brew is in PATH and then check the output of brew --prefix.

Copy link
Collaborator Author

@eregon eregon Aug 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems an orthogonal issue to me.
Shelling out to brew --prefix seems quite expensive (e.g. while loading the ffi gem), maybe there should be a standard HOMEBREW_PREFIX env var exported by default or so, so we could read it without the cost of a subprocess.
Could you file a separate issue if you need that? (or maybe there is already one?)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@eregon brew --prefix is the correct way to detect the homebrew location. or we need a configure flag for prepending an include dir to the initial build of the gem so that people can set their own configurations appropriately. /opt/homebrew and /usr/local are standard locations, but not the only options. However, this shouldn't be a blocker to get the standard fix out to the majority. people have been waiting for months and months. this is a serious breakage for rosetta and arm users.

Fix the easy standard way for the majority of users first, then we can come up with a way for the people who are in the outliers

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree this is not a blocker. I think brew --prefix is too much of a cost on require, but maybe it's OK to compute it once lazily on ffi_lib on macOS.

What we need is @larskanis to review this PR and then make a release.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking more about it, it sounds really complicated to support Homebrew not in a default location.
For instance if Homebrew is installed both in amd64 and aarch64, how do we even call the "right" brew executable? It all sounds extremely messy and easy to mess up.
Anyway, if someone needs this they can make a PR.

@eregon
Copy link
Collaborator Author

eregon commented Aug 13, 2022

@larskanis Gentle ping

@jasl
Copy link

jasl commented Nov 15, 2022

@larskanis sorry to disturb you, but could you take a look? this is break people especially for non Ruby developers

Copy link
Member

@larskanis larskanis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late response! This looks all good. The recursive processing makes it more readable than the iterative approach we had before.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Could not open library 'sodium': dlopen(sodium, 5): image not found. (LoadError) on Apple Silicon M1
5 participants