Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Gradle with native dependencies

I am trying to use Sigar in a Gradle project. Sigar distribution is by default provided with 2 types of files:

  • a JAR that contains classes
  • some native files (.so, dylib, .dll)

My purpose is to repackage these files so that I can use them as dependencies deployed and downloaded on-demand from a personal Maven repository.

My first try was to define dependencies as files in order to check that my application is working as expected before to repackage. Below is the Gradle code I used for my first test that works:

dependencies {
  compile files("${rootDir}/lib/sigar/sigar.jar")
  runtime fileTree(dir: "${rootDir}/lib/sigar/", exclude: "*.jar")
}

Then, I have repackaged Sigar native files into a JAR and renamed the other one to match rules for maven artifacts since I want to deploy them in a Maven repository. Below is what I get:

  • sigar-1.6.4.jar (contains .class files)
  • sigar-1.6.4-native.jar (contains .dylib, .so, and .dll files at the root)

The next step was to deploy these files in my custom repository. Then, I have updated my build.gradle as follows:

dependencies {
  compile 'sigar:sigar:1.6.4'
  runtime 'sigar:sigar:1.6.4:native'
}

Unfortunately, when I do a gradle clean build, new dependencies are fetched but native libraries can no longer be found at runtime since now I get the following exception:

Error thrown in postRegister method: rethrowing <java.lang.UnsatisfiedLinkError: org.hyperic.sigar.Sigar.getCpuInfoList()[Lorg/hyperic/sigar/CpuInfo;>

Consequently, I am looking for a solution to fetch and to link native files to my Java app like for other dependencies. Any advice, comment, suggestion, help, solution, etc. are welcome ;)

like image 574
Laurent Avatar asked Apr 03 '15 18:04

Laurent


People also ask

Does Gradle handle transitive dependencies?

Transitive dependencyBy default, Gradle resolves transitive dependencies automatically. The version selection for transitive dependencies can be influenced by declaring dependency constraints.

Can Gradle use Maven dependency?

Gradle can consume dependencies available in the local Maven repository. Declaring this repository is beneficial for teams that publish to the local Maven repository with one project and consume the artifacts by Gradle in another project. Gradle stores resolved dependencies in its own cache.

Does Gradle use Ivy?

A published Ivy module can be consumed by Gradle (see Declaring Dependencies) and other tools that understand the Ivy format. You can learn about the fundamentals of publishing in Publishing Overview.


1 Answers

A solution is to define a new gradle configuration that unzips JAR files at the desired location:

project.ext.set('nativeLibsDir', "$buildDir/libs/natives")

configurations {
    nativeBundle
}

dependencies {
    nativeBundle 'sigar:sigar:1.6.4:native'
}

task extractNativeBundle(type: Sync) {
    from {
        configurations.nativeBundle.collect { zipTree(it) }
    }
    into file(project.nativeLibsDir)
}

dist.dependsOn extractNativeBundle

Then, this location must be put in java.library.path for tasks that depend on native libraries:

systemProperty "java.library.path", project.nativeLibsDir
like image 192
Laurent Avatar answered Nov 15 '22 07:11

Laurent