-
Notifications
You must be signed in to change notification settings - Fork 149
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
pythemis: Extra effort to locate Themis Core library #915
Conversation
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 pretty well :)
Instead of each submodule figuring out where the native library is, just initialize it one place and pull it from there.
Rebased with no changes, swizzled out the first commit which got already merged into |
That is, "libthemis" ABI version 0. First of all, this makes it possible for users to avoid installing development package of Themis on Linux. That is, only "libthemis", without "libthemis-dev" or "libthemis-devel". Second, it makes sure that if Themis 0.XX and Themis 2.YY are co-installed, then this PyThemis will load Themis 0.XX library. By default, find_library() favors the latest version, and that could cause ABI mismatches. On Linux, this is how 'real' binaries load libraries via run-time dynamic linker-loader: they remember "libthemis.so.0" soname, ask ld to load that, and if it fails then your binary fails to start. On macOS, applications typically remember absolute path to the library, which would be something like this for default Homebrew install: /usr/local/opt/libthemis/lib/libthemis.0.dylib However, Homebrew on Apple Silicon installs libraries in /opt/homebrew instead of /usr/local, so look there as well. Existing behavior of using find_library('themis') is used as a fallback on Linux and macOS. For now, this is a genuine fallback with a warning. PyThemis 0.15 will be a test-bed for this change, and if it works fine then some later version might load *only* versioned libraries, assuming libthemis.so.2 would be an actual risk. Other systems -- like Windows -- keep using find_library(). I'm not quite sure with the story about ABI versioning on Windows specifically. The recommended approach there is to use absolute paths, partly because of how easy DLL hijacking is there. Anyhow, ignore this issue for now, and just keep using whatever we were using.
Turns out, if find_library() cannot find a library it simply returns None and then LoadLibrary() does not raise an exception for that, instead loading a "None" library, lol. That won't do. We had people run into situations where native library could not be found and then the interpreter reports errors like AttributeError: dlsym(RTLD_DEFAULT, themis_gen_sym_key): symbol not found which confusingly *look like* some issues with library symbols.
Updated the last couple of commits to follow #917's approach. |
Not at all 👍 |
Put in some extra effort to locate the right native library.
Look for
libthemis.so.0
orlibthemis.0.dylib
first.Instead of looking for some Themis Core, look for the one with the proper ABI version in it. First of all, this finally allows users to install only
libthemis
package, withoutlibthemis-dev
. Second, this prevents PyThemis from accidentally loading Themis 1.x or 2.x libraries, should they ever be co-installed in the system.find_library('themis')
code path remains as a fallback on Linux and macOS, and it's also used on Windows by default. No idea whether PyThemis works there, but this PR should at least not make it worse.Look in some "standard" search paths as well.
PyThemis expects Themis Core to be installed in one of the paths dynamic linker would be looking in. Normally, it all works out, but
on some 🌈 special 🦄 systemsHomebrew on Apple M1 installs libraries into/opt/homebrew
, which – surprise! – is not in standard search paths when non-Homebrew Python is used.While arguably it's the user environment issue, Python developers are not very fond of debugging native library loading and that's PyThemis fault for requiring a native library in the first place, so let's at least attempt to make things "just work" before giving up.
So on both Linux and macOS we'd be looking in
/usr/local/lib
wheremake install
puts Themis Core, and on macOS we'd be looking in/opt/homebrew/lib
just in case (on Intel CPUs Homebrew installs to/usr/local/lib
).Related issues:
Checklist