Search code examples
javamavenjava-native-interfacenativemaven-install-plugin

Why does Maven trim the "lib" prefix when installing native libraries when Java expects this convention for linking?


I have been reviving two projects lately involving JNI-based (Java with native libraries) code. The build system is legacy (Makefile based, not Maven or Gradle), but that's ok given the age of the projects (their inception predates Maven), and because some significant parts of the code are not written in Java.

There is no plan for replacing the Makefile (or configure) scripts with Maven or Gradle configuration scripts (the build systems I inherited work fine, and would probably not been made simpler with other tools, given the fact that the softwares are not pure Java).

However, deploying the jars (even built with another tool) in the Maven repo is straightforward with the Maven installation plugin, and makes their use by third party code much simpler, so I went this way.

I can make everything work, but I have been unable to figure out why Maven (or more specifically, the Maven install plugin) behaves like it does, that seems to make things more complex than they need to be. Most probably, my understanding of Maven's behaviour or of the Java linking system is lacking.

Here is the issue: for installing a jar and its native library, one can use the following commands.

mvn install:install-file -Dfile=$(jarFile) -DgroupId=$(groupId) -DartifactId=$(artifactId) -Dversion=$(libraryVersion) -Dpackaging=jar

mvn install:install-file -Dfile=$(nativeLibraryFile) -DgroupId=$(groupId) -DartifactId=$(artifactId) -Dversion=$(libraryVersion) -Dpackaging=$(soExtension)

Here soExtension can be dll, so, dylib depending on the operating system. The two files end up in the same location of the Maven local repository, namely .m2/repository/groupId/artifactId/versionId

However, I observed that the native library, initially called, say libmylibrary.so, was systematically renamed by Maven mylibrary.so in the repository. As a consequence, even when java is given the proper library path (the -Djava.library.path option), it issues a link error because it cannot find the right library name (it does expect the "lib" prefix, at least in my available implementations).

The link error can be solved by several means:

  • by renaming the file (trimmed by Maven) back to its correct name
  • by creating a link afterwards (on systems that support links).

The two previous solutions are a rather clumsy way to go, because they assume a knowledge of the internals of the Maven repository (going against the encapsulation principle).

  • another solution is not to rely on Maven, and to install native libraries under the system directories where dynamic libraries are usually expected (LD_LIBRARY_PATH or equivalent). It has been my solution of choice as a last resort, but I find it rather fragile and harder to maintain, since both files (the jar and the native library) are now separated in two different locations. It also makes the uninstallation of the package more difficult.

Does anyone know why the Maven installation system behave the way it does? And if there is a workaround for it?

Thank you


Solution

  • The name of artifacts in a repository is generated out of artifactId and no there is no possibility to change that. If you like or need to change thatyou have to change the artifactId.

    For running that on a particular platform I would create a kind of installation package which contains the correctly named artifacts.