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

Package Themis JNI library in DEB and RPM #553

Merged
merged 5 commits into from
Nov 8, 2019

Conversation

ilammy
Copy link
Collaborator

@ilammy ilammy commented Nov 5, 2019

Let’s provide proper packaging for the JNI library on Linux.

  • Installation targets for libthemis_jni

Introduce two new Makefile targets to install and uninstall Themis JNI library: themis_jni_{install,uninstall}

The library is installed to $(jnidir) which is set to $(libdir) by default, but can be overriden. This is because Java is not required to look into standard system directories for JNI libraries and may have a different opinion about that.

  • Package Themis JNI library in DEB and RPM

Add a separate package called libthemis-jni with Themis JNI library used by JavaThemis wrapper. It depends on Themis Core library against which it is linked. Since we maintain backwards compatibility it should be possible to upgrade Themis Core independently and we allow later versions to satisfy the dependency.

Debian and CentOS systems have different opinions about location of JNI libraries. Use jnidir to adjust for that.

  • Warn the user about path mismatch

Java installations are not required to look into system library directories. While normally OpenJDK and Oracle JDK installations do look into some directory in the /usr hierarchy, none of the systems that we support looks into /usr/local/lib where we install by default when compiling from source.

This is particularly important for macOS where Homebrew cannot (realistically) install into any of the standard directories.

Checklist

  • Change is covered by automated tests
    (CircleCI does not test DEB/RPM, we’ll check with internal build system)
  • Benchmark results are attached (not applicable)
  • The coding guidelines are followed
  • Public API has proper documentation
  • Example projects and code samples are updated (no API changes)
  • Changelog is updated if needed (in case of notable or breaking changes)

Introduce two new Makefile targets to install and uninstall Themis JNI
library: themis_jni_{install,uninstall}

The library is installed to $(jnidir) which is set to $(libdir) by
default, but can be overriden. This is because Java is not required
to look into standard system directories for JNI libraries and may
have a different opinion about that.

Note that libthemis_jni does not have ABI suffix, does not introduce
development symbolic links, and does not define import libraries like
Soter and Themis libraries do. This is because it is not meant to be
used by linkers, only dynamically loaded by JVM. Therefore we can
simply name it "libthemis_jni.so" and that's all: it's going to be
loaded by path anyway, its SONAME does not matter.

Also note that on macOS we invoke install_name_tool only during
installation, not during build. This is in-line with other libraries
and is the correct behavior (so that we do not have to rebuild the
library before installing it into a different place).
Add a separate package called "libthemis-jni" with Themis JNI library
used by JavaThemis wrapper. It depends on Themis Core library against
which it is linked. Since we maintain backwards compatibility it
should be possible to upgrade Themis Core independently and we allow
later versions to satisfy the dependency.

Debian Java policy prescribes that JNI libraries should be placed into
a "jni" subdirectory in the default library directory. Since we support
multilib that's something like /usr/lib/x86_64-linux-gnu/jni for x86_64
architecture. OpenJDK from Debian repositories has this path in its
java.library.path list.

CentOS conventions are to put JNI libraries right into the normal path
like /usr/lib64. That's what we'll do when packaging RPMs.
Let's check Java library search paths and print out a warning if JNI
library is being installed to a locations that's probably unreachable
by default.

Java installations are not required to look into system library
directories. While normally OpenJDK and Oracle JDK installations
do look into some directory in the /usr hierarchy, *none* of the systems
that we support looks into "/usr/local/lib" where we install by default
when compiling from source.

This is unfortunate, but we should not decide for the user how they
should be configuring their system when building from source, and we
should not interfere with system package manager either.

For Linux we provide packages that install JNI library into /usr
subdirectories expected by Java. This is the preferred way to install
Themis Core on Linux. Users that build from source will have to adjust
JNI library location manually after installation.

Unfortunately, on macOS Homebrew is not able to write to any of the
Oracle's Java default paths except for the one in user's home directory:

    $HOME/Library/Java/Extensions
    /Library/Java/Extensions         - requires root acccess
    /Network/Library/Java/Extensions - protected by SIP
    /System/Library/Java/Extensions  - protected by SIP
    /usr/lib/java                    - protected by SIP
    $PWD

Installing into $HOME or the current directory is not really an option
for Homebrew. Thus on macOS we are most likely installing the library
into a directory that's not reachable by default. Homebrew package
should be adjusted to print out a relevant message to the user.
@ilammy ilammy added W-JavaThemis ☕ Wrapper: Java, Java and Kotlin API infrastructure Automated building and packaging labels Nov 5, 2019
@$(PRINT_OK_)
@java_library_path=$$(\
java -XshowSettings:properties -version 2>&1 \
| sed -E 's/^ +[^=]+ =/_&/' \
Copy link
Contributor

Choose a reason for hiding this comment

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

black magic happening here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well, if you'd like it can be replaced with the following Java code:

import java.io.File;

public final class Main {
    public static void main(String[] args) {
        String rawPath = System.getProperty("java.library.path");
        String[] paths = rawPath.split(File.pathSeparator);
        for (String path : paths) {
            System.out.println(path);
        }
    }
}

Just need to compile and run it. Or we can bundle a precompiled *.jar.

Copy link
Contributor

Choose a reason for hiding this comment

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

thank you for explanation, my skills of understanding regex "on the fly" are not perfect

Copy link
Collaborator

@Lagovas Lagovas left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Contributor

@shadinua shadinua left a comment

Choose a reason for hiding this comment

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

Great, thanks!

@ilammy ilammy merged commit 4ebf103 into cossacklabs:master Nov 8, 2019
@ilammy ilammy deleted the jni-package branch November 8, 2019 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
infrastructure Automated building and packaging W-JavaThemis ☕ Wrapper: Java, Java and Kotlin API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants