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:
@@ -3,8 +3,6 @@ plugins {
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
val currentOs = org.gradle.internal.os.OperatingSystem.current()
|
||||
|
||||
kotlin {
|
||||
explicitApi()
|
||||
}
|
||||
@@ -14,7 +12,7 @@ dependencies {
|
||||
implementation(kotlin("stdlib-jdk8"))
|
||||
}
|
||||
|
||||
val generateJniHeaders by tasks.creating(JavaCompile::class) {
|
||||
val generateHeaders by tasks.creating(JavaCompile::class) {
|
||||
group = "build"
|
||||
classpath = sourceSets["main"].compileClasspath
|
||||
destinationDir = file("${buildDir}/generated/jni")
|
||||
@@ -29,52 +27,6 @@ val generateJniHeaders by tasks.creating(JavaCompile::class) {
|
||||
}
|
||||
}
|
||||
|
||||
sealed class Cross {
|
||||
abstract fun cmd(target: String, project: Project): List<String>
|
||||
class DockCross(val cross: String) : Cross() {
|
||||
override fun cmd(target: String, project: Project): List<String> = listOf("${project.rootDir}/cross-scripts/dockcross-$cross", "bash", "-c", "CROSS=1 TARGET=$target jni/build.sh")
|
||||
}
|
||||
class MultiArch(val crossTriple: String) : Cross() {
|
||||
override fun cmd(target: String, project: Project): List<String> {
|
||||
val uid = Runtime.getRuntime().exec("id -u").inputStream.use { it.reader().readText() }.trim().toInt()
|
||||
return listOf(
|
||||
"docker", "run", "--rm", "-v", "${project.rootDir.absolutePath}:/workdir",
|
||||
"-e", "CROSS_TRIPLE=$crossTriple", "-e", "TARGET=$target", "-e", "TO_UID=$uid", "-e", "CROSS=1",
|
||||
"multiarch/crossbuild", "jni/build.sh"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val buildNativeJni by tasks.creating {
|
||||
group = "build"
|
||||
}
|
||||
val noCrossCompile: String? by project
|
||||
fun creatingBuildNativeJni(target: String, cross: Cross?) = tasks.creating(Exec::class) {
|
||||
group = "build"
|
||||
dependsOn(generateJniHeaders)
|
||||
dependsOn(":native:buildSecp256k1${target.capitalize()}")
|
||||
buildNativeJni.dependsOn(this)
|
||||
|
||||
if (noCrossCompile == "true") onlyIf { cross == null }
|
||||
|
||||
inputs.files(projectDir.resolve("build.sh"))
|
||||
outputs.dir(buildDir.resolve("build/cmake/$target"))
|
||||
|
||||
workingDir = rootDir
|
||||
environment("TARGET", target)
|
||||
commandLine((cross?.cmd(target, project) ?: emptyList()) + "jni/build.sh")
|
||||
}
|
||||
val buildNativeJniDarwin by creatingBuildNativeJni("darwin", if (currentOs.isMacOsX) null else Cross.MultiArch("x86_64-apple-darwin"))
|
||||
val buildNativeJniLinux by creatingBuildNativeJni("linux", if (currentOs.isLinux) null else Cross.DockCross("linux-x64"))
|
||||
val buildNativeJniMingw by creatingBuildNativeJni("mingw", if (currentOs.isWindows) null else Cross.DockCross("windows-x64"))
|
||||
|
||||
afterEvaluate {
|
||||
tasks["clean"].doLast {
|
||||
delete(buildDir.resolve("build/cmake"))
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("jvm") {
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#define JNIIMPORT __declspec(dllimport)
|
||||
#define JNICALL __stdcall
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef long jint;
|
||||
typedef int64_t jlong;
|
||||
typedef signed char jbyte;
|
||||
|
||||
20
jni/jvm/all/build.gradle.kts
Normal file
20
jni/jvm/all/build.gradle.kts
Normal 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"])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ JNI_HEADERS=$TARGET
|
||||
|
||||
if [ "$TARGET" == "linux" ]; then
|
||||
OUTFILE=libsecp256k1-jni.so
|
||||
[ "$CROSS" == "1" ] && sudo apt -y install libgmp-dev
|
||||
ADD_LIB=-lgmp
|
||||
CC_OPTS="-fPIC"
|
||||
elif [ "$TARGET" == "darwin" ]; then
|
||||
@@ -22,14 +21,12 @@ elif [ "$TARGET" == "darwin" ]; then
|
||||
ADD_LIB=-lgmp
|
||||
elif [ "$TARGET" == "mingw" ]; then
|
||||
OUTFILE=secp256k1-jni.dll
|
||||
CC=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.static-gcc
|
||||
JNI_HEADERS=linux
|
||||
CC_OPTS="-fPIC"
|
||||
CC=x86_64-w64-mingw32-gcc
|
||||
fi
|
||||
|
||||
mkdir -p build/jni/$TARGET
|
||||
|
||||
$CC -shared $CC_OPTS -o build/jni/$TARGET/$OUTFILE c/src/fr_acinq_secp256k1_Secp256k1CFunctions.c -Ic/headers/ -Ic/headers/java -Ic/headers/$JNI_HEADERS/ -I../native/secp256k1/ -lsecp256k1 -L../native/build/$TARGET/ $ADD_LIB
|
||||
$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 .
|
||||
|
||||
33
jni/jvm/darwin/build.gradle.kts
Normal file
33
jni/jvm/darwin/build.gradle.kts
Normal 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 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
33
jni/jvm/linux/build.gradle.kts
Normal file
33
jni/jvm/linux/build.gradle.kts
Normal 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 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
33
jni/jvm/mingw/build.gradle.kts
Normal file
33
jni/jvm/mingw/build.gradle.kts
Normal 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 } }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user