Simplify native library resolution using os-maven-plugin

Motivation:

So far, we used a very simple platform string such as linux64 and
linux32.  However, this is far from perfection because it does not
include anything about the CPU architecture.

Also, the current build tries to put multiple versions of .so files into
a single JAR.  This doesn't work very well when we have to ship for many
different platforms.  Think about shipping .so/.dynlib files for both
Linux and Mac OS X.

Modification:

- Use os-maven-plugin as an extension to determine the current OS and
  CPU architecture reliable at build time
- Use Maven classifier instead of trying to put all shared libraries
  into a single JAR
- NativeLibraryLoader does not guess the OS and bit mode anymore and it
  always looks for the same location regardless of platform, because the
  Maven classifier does the job instead.

Result:

Better scalable native library deployment and retrieval
This commit is contained in:
Trustin Lee 2014-05-01 19:26:51 +09:00
parent 93fab1d5a3
commit 6c1af9036f
4 changed files with 30 additions and 100 deletions

View File

@ -24,8 +24,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Locale;
import java.util.regex.Pattern;
/**
* Helper class to load JNI resources.
@ -35,7 +33,6 @@ public final class NativeLibraryLoader {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(NativeLibraryLoader.class);
private static final Pattern REPLACE = Pattern.compile("\\W+");
private static final File WORKDIR;
static {
@ -67,7 +64,7 @@ public final class NativeLibraryLoader {
*/
public static void load(String name, ClassLoader loader) {
String libname = System.mapLibraryName(name);
String path = "META-INF/native/" + osIdentifier() + PlatformDependent.bitMode() + '/' + libname;
String path = "META-INF/native/" + libname;
URL url = loader.getResource(path);
if (url == null) {
@ -128,21 +125,6 @@ public final class NativeLibraryLoader {
}
}
private static String osIdentifier() {
String name = SystemPropertyUtil.get("os.name", "unknown").toLowerCase(Locale.US).trim();
if (name.startsWith("win")) {
return "windows";
}
if (name.startsWith("mac os x")) {
return "osx";
}
if (name.startsWith("linux")) {
return "linux";
}
return REPLACE.matcher(name).replaceAll("_");
}
private NativeLibraryLoader() {
// Utility
}

13
pom.xml
View File

@ -362,6 +362,14 @@
</dependencies>
<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.1.1</version>
</extension>
</extensions>
<plugins>
<plugin>
<artifactId>maven-enforcer-plugin</artifactId>
@ -805,6 +813,11 @@
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
</plugin>
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<version>1.10</version>
</plugin>
<!-- Workaround for the 'M2E plugin execution not covered' problem.
See: http://wiki.eclipse.org/M2E_plugin_execution_not_covered -->

View File

@ -60,39 +60,16 @@
<plugin>
<groupId>org.fusesource.hawtjni</groupId>
<artifactId>maven-hawtjni-plugin</artifactId>
<version>1.10</version>
<executions>
<execution>
<id>build-linux64</id>
<id>build-native-lib</id>
<configuration>
<name>${project.artifactId}</name>
<buildDirectory>${project.build.directory}/linux64</buildDirectory>
<nativeSourceDirectory>${nativeSourceDirectory}</nativeSourceDirectory>
<libDirectory>${libDirectory}</libDirectory>
<configureArgs>
<arg>--with-arch=x86_64</arg>
</configureArgs>
<platform>linux64</platform>
<forceConfigure>true</forceConfigure>
<forceAutogen>true</forceAutogen>
</configuration>
<goals>
<goal>generate</goal>
<goal>build</goal>
</goals>
<phase>compile</phase>
</execution>
<execution>
<id>build-linux32</id>
<configuration>
<buildDirectory>${project.build.directory}/linux32</buildDirectory>
<nativeSourceDirectory>${nativeSourceDirectory}</nativeSourceDirectory>
<libDirectory>${libDirectory}</libDirectory>
<name>${project.artifactId}</name>
<configureArgs>
<arg>--with-arch=i386</arg>
</configureArgs>
<platform>linux32</platform>
<nativeSourceDirectory>${project.basedir}/src/main/c</nativeSourceDirectory>
<libDirectory>${project.build.outputDirectory}</libDirectory>
<!-- We use Maven's artifact classifier instead.
This hack will make the hawtjni plugin to put the native library
under 'META-INF/native' rather than 'META-INF/native/${platform}'. -->
<platform>.</platform>
<forceConfigure>true</forceConfigure>
<forceAutogen>true</forceAutogen>
</configuration>
@ -104,10 +81,15 @@
</execution>
</executions>
</plugin>
<!-- Because the generated JAR is platform dependent, use the platform as a classifier. -->
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<classifier>${os.detected.classifier}</classifier>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<nativeSourceDirectory>${basedir}/src/main/c</nativeSourceDirectory>
<libDirectory>${basedir}/target/classes/</libDirectory>
</properties>
</project>

View File

@ -1,47 +0,0 @@
dnl ---------------------------------------------------------------------------
dnl Copyright 2014 The Netty Project
dnl
dnl Licensed under the Apache License, Version 2.0 (the "License");
dnl you may not use this file except in compliance with the License.
dnl You may obtain a copy of the License at
dnl
dnl http://www.apache.org/licenses/LICENSE-2.0
dnl
dnl Unless required by applicable law or agreed to in writing, software
dnl distributed under the License is distributed on an "AS IS" BASIS,
dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
dnl See the License for the specific language governing permissions and
dnl limitations under the License.
dnl ---------------------------------------------------------------------------
AC_DEFUN([CUSTOM_M4_SETUP],
[
AC_MSG_CHECKING(which arch to build for)
AC_ARG_WITH([arch],
[AS_HELP_STRING([--with-arch@<:@=ARCH@:>@],
[Build for the specified architecture. Pick from: i386, x86_64.])],
[
AS_IF(test -n "$withval", [
ARCH="$withval"
AC_MSG_RESULT([yes, archs: $ARCH])
])
],[
ARCH=""
AC_MSG_RESULT([no])
])
AS_IF(test "$ARCH" = "i386", [
FLAGS="-m32"
], test "ARCH" = "x86_64", [
FLAGS="-m64"
], [
FLAGS=""
])
AS_IF(test -n "$FLAGS", [
CFLAGS="$FLAGS $CFLAGS"
CXXFLAGS="$FLAGS $CXXFLAGS"
LDFLAGS="$FLAGS $ARCH $LDFLAGS"
AC_SUBST(CFLAGS)
AC_SUBST(CXXFLAGS)
AC_SUBST(LDFLAGS)
])
])