Native jni build (#5)

* Each native library is in its own jar. Got rid of cross compilation. The project is `secp256k1` and not `secp256k1-kmp`.

* Updated CI to use all 3 OS VMs

Co-authored-by: Salomon BRYS <salomon@kodein.net>
This commit is contained in:
Salomon BRYS
2020-07-09 15:54:34 +03:00
committed by GitHub
parent c5dbc42496
commit 6c850eb2c4
20 changed files with 393 additions and 694 deletions

View File

@@ -0,0 +1,20 @@
plugins {
`java-library`
// `maven-publish`
id("ru.vyarus.pom") version "2.1.0"
}
dependencies {
api(project(":jni:jvm:darwin"))
api(project(":jni:jvm:linux"))
api(project(":jni:jvm:mingw"))
}
publishing {
publications {
create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm"
from(components["java"])
}
}
}

View File

@@ -3,8 +3,27 @@ plugins {
`maven-publish`
}
kotlin {
explicitApi()
val currentOs = org.gradle.internal.os.OperatingSystem.current()
val bash = if (currentOs.isWindows) "bash.exe" else "bash"
val buildNativeHost by tasks.creating(Exec::class) {
group = "build"
dependsOn(":jni:generateHeaders")
dependsOn(":native:buildSecp256k1Host")
val target = when {
currentOs.isLinux -> "linux"
currentOs.isMacOsX -> "darwin"
currentOs.isWindows -> "mingw"
else -> error("Unsupported OS $currentOs")
}
inputs.files(projectDir.resolve("build.sh"))
outputs.dir(buildDir.resolve(target))
workingDir = projectDir
environment("TARGET", target)
commandLine(bash, "build.sh")
}
dependencies {
@@ -12,26 +31,17 @@ dependencies {
implementation(kotlin("stdlib-jdk8"))
}
val copyJni by tasks.creating(Sync::class) {
dependsOn(":jni:buildNativeJni")
from(rootDir.resolve("jni/build/jni/linux/libsecp256k1-jni.so")) { rename { "libsecp256k1-jni-linux-x86_64.so" } }
from(rootDir.resolve("jni/build/jni/darwin/libsecp256k1-jni.dylib")) { rename { "libsecp256k1-jni-darwin-x86_64.dylib" } }
from(rootDir.resolve("jni/build/jni/mingw/secp256k1-jni.dll")) { rename { "secp256k1-jni-mingw-x86_64.dll" } }
into(buildDir.resolve("jniResources/fr/acinq/secp256k1/jni/native"))
}
(tasks["processResources"] as ProcessResources).apply {
dependsOn("copyJni")
from(buildDir.resolve("jniResources"))
}
java.withSourcesJar()
publishing {
publications {
create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm"
artifactId = "secp256k1-jni-jvm-extract"
from(components["java"])
}
}
}
afterEvaluate {
tasks["clean"].doLast {
delete("$buildDir/build/cmake")
}
}

33
jni/jvm/build.sh Executable file
View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -e
[[ -z "$TARGET" ]] && echo "Please set the TARGET variable" && exit 1
if [ "$(id -u)" == "0" ]; then
[[ -z "$TO_UID" ]] && echo "Please set the TO_UID variable" && exit 1
fi
cd "$(dirname "$0")"
CC=gcc
JNI_HEADERS=$TARGET
if [ "$TARGET" == "linux" ]; then
OUTFILE=libsecp256k1-jni.so
ADD_LIB=-lgmp
CC_OPTS="-fPIC"
elif [ "$TARGET" == "darwin" ]; then
OUTFILE=libsecp256k1-jni.dylib
ADD_LIB=-lgmp
elif [ "$TARGET" == "mingw" ]; then
OUTFILE=secp256k1-jni.dll
CC=x86_64-w64-mingw32-gcc
fi
mkdir -p build/jni/$TARGET
$CC -shared $CC_OPTS -o build/$TARGET/$OUTFILE ../c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c -I../c/headers/ -I../c/headers/java -I../c/headers/$JNI_HEADERS/ -I../../native/secp256k1/ -lsecp256k1 -L../../native/build/$TARGET/ $ADD_LIB
[[ ! -z "$TO_UID" ]] && chown -R $TO_UID:$TO_UID .
echo "Build done for $TARGET"

View File

@@ -0,0 +1,33 @@
plugins {
kotlin("jvm")
`maven-publish`
}
dependencies {
implementation(project(":jni:jvm"))
}
val copyJni by tasks.creating(Sync::class) {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
dependsOn(":jni:jvm:buildNativeHost")
from(rootDir.resolve("jni/jvm/build/darwin/libsecp256k1-jni.dylib"))
into(buildDir.resolve("jniResources/fr/acinq/secp256k1/jni/native/darwin-x86_64"))
}
(tasks["processResources"] as ProcessResources).apply {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isMacOsX }
dependsOn(copyJni)
from(buildDir.resolve("jniResources"))
}
publishing {
publications {
val pub = create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm-darwin"
from(components["java"])
}
if (!org.gradle.internal.os.OperatingSystem.current().isMacOsX) {
tasks.withType<AbstractPublishToMaven>().all { onlyIf { publication != pub } }
}
}
}

View File

@@ -0,0 +1,33 @@
plugins {
kotlin("jvm")
`maven-publish`
}
dependencies {
implementation(project(":jni:jvm"))
}
val copyJni by tasks.creating(Sync::class) {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
dependsOn(":jni:jvm:buildNativeHost")
from(rootDir.resolve("jni/jvm/build/linux/libsecp256k1-jni.so"))
into(buildDir.resolve("jniResources/fr/acinq/secp256k1/jni/native/linux-x86_64"))
}
(tasks["processResources"] as ProcessResources).apply {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isLinux }
dependsOn(copyJni)
from(buildDir.resolve("jniResources"))
}
publishing {
publications {
val pub = create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm-linux"
from(components["java"])
}
if (!org.gradle.internal.os.OperatingSystem.current().isLinux) {
tasks.withType<AbstractPublishToMaven>().all { onlyIf { publication != pub } }
}
}
}

View File

@@ -0,0 +1,33 @@
plugins {
kotlin("jvm")
`maven-publish`
}
dependencies {
implementation(project(":jni:jvm"))
}
val copyJni by tasks.creating(Sync::class) {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows }
dependsOn(":jni:jvm:buildNativeHost")
from(rootDir.resolve("jni/jvm/build/mingw/secp256k1-jni.dll"))
into(buildDir.resolve("jniResources/fr/acinq/secp256k1/jni/native/mingw-x86_64"))
}
(tasks["processResources"] as ProcessResources).apply {
onlyIf { org.gradle.internal.os.OperatingSystem.current().isWindows }
dependsOn(copyJni)
from(buildDir.resolve("jniResources"))
}
publishing {
publications {
val pub = create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm-mingw"
from(components["java"])
}
if (!org.gradle.internal.os.OperatingSystem.current().isWindows) {
tasks.withType<AbstractPublishToMaven>().all { onlyIf { publication != pub } }
}
}
}

View File

@@ -187,7 +187,7 @@ public object NativeSecp256k1Loader {
// Try loading library from fr.acinq.secp256k1.lib.path library path */
val libraryPath = System.getProperty("fr.acinq.secp256k1.lib.path")
val libraryName = System.getProperty("fr.acinq.secp256k1.lib.name") ?: System.mapLibraryName("secp256k1-jni-${OSInfo.nativeSuffix}")
val libraryName = System.getProperty("fr.acinq.secp256k1.lib.name") ?: System.mapLibraryName("secp256k1-jni")
if (libraryPath != null) {
if (loadNativeLibrary(libraryPath, libraryName)) {
extracted = true
@@ -197,7 +197,7 @@ public object NativeSecp256k1Loader {
// Load the os-dependent library from the jar file
val packagePath = NativeSecp256k1Loader::class.java.getPackage().name.replace("\\.".toRegex(), "/")
val embeddedLibraryPath = "/$packagePath/native"
val embeddedLibraryPath = "/$packagePath/native/${OSInfo.nativeSuffix}"
val hasNativeLib = NativeSecp256k1Loader::class.java.getResource("$embeddedLibraryPath/$libraryName") != null
if (!hasNativeLib) {
error("No native library found: at $embeddedLibraryPath/$libraryName")