Using Gradle with native dependencies

2020-02-23 08:35发布

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 ;)

1条回答
走好不送
2楼-- · 2020-02-23 09:25

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
查看更多
登录 后发表回答