From fa425731a1e8ec56cf475d1bcc1d7c8d8be0ef1d Mon Sep 17 00:00:00 2001 From: Salomon BRYS Date: Fri, 3 Jul 2020 19:12:38 +0200 Subject: [PATCH] GitHub actions (#2) * Updated readme, enabled automatc testing * Snapshot support * Release CI support Co-authored-by: Salomon BRYS --- .github/workflows/release.yml | 71 +++++++++++++++++++++++++++++++++ .github/workflows/snapshot.yml | 72 ++++++++++++++++++++++++++++++++++ .github/workflows/test.yml | 71 +++++++++++++++++++++++++++++++++ README.md | 66 +++++++++++++++++++++++++++++++ build.gradle.kts | 9 +++-- jni/build.gradle.kts | 3 ++ jni/build.sh | 3 +- native/build.gradle.kts | 3 ++ native/build.sh | 7 +++- 9 files changed, 299 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/snapshot.yml create mode 100644 .github/workflows/test.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..fb0f252 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,71 @@ +name: Publish release + +on: + release: + types: [published] + +jobs: + + publish-ios: + name: Publish iOS native + runs-on: macOS-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Install automake + run: brew install automake + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Check + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + arguments: iosX64Test + - name: Publish + uses: eskatos/gradle-command-action@v1 + env: + BINTRAY_USER: ${{ secrets.bintray_user }} + BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} + with: + arguments: publishIosArm64PublicationToBintrayRepository publishIosX64PublicationToBintrayRepository + + publish: + name: Publish JVM & Linux native + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Check + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + arguments: check + - name: Publish + uses: eskatos/gradle-command-action@v1 + env: + BINTRAY_USER: ${{ secrets.bintray_user }} + BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} + with: + arguments: publishAllPublicationsToBintrayRepository \ No newline at end of file diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml new file mode 100644 index 0000000..a68932a --- /dev/null +++ b/.github/workflows/snapshot.yml @@ -0,0 +1,72 @@ +name: Publish snapshot + +on: + push: + branches: + - 'snapshot/*' + +jobs: + + publish-ios: + name: Publish iOS native + runs-on: macOS-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Install automake + run: brew install automake + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Check + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + arguments: iosX64Test + - name: Publish + uses: eskatos/gradle-command-action@v1 + env: + BINTRAY_USER: ${{ secrets.bintray_user }} + BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} + with: + arguments: publishIosArm64PublicationToBintrayRepository publishIosX64PublicationToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }} -PgitSha=${{ github.sha }} + + publish: + name: Publish JVM & Linux native + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Check + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + arguments: check + - name: Publish + uses: eskatos/gradle-command-action@v1 + env: + BINTRAY_USER: ${{ secrets.bintray_user }} + BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} + with: + arguments: publishAllPublicationsToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }} -PgitSha=${{ github.sha }} \ No newline at end of file diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..5809e22 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,71 @@ +name: Check + +on: + push: + branches-ignore: + - 'snapshot/*' + +jobs: + + linux: + name: JNI & Linux + runs-on: ubuntu-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Check JNI + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + dependencies-cache-enabled: true + arguments: jvmTest -PnoCrossCompile=true + - name: Check Linux + uses: eskatos/gradle-command-action@v1 + with: + arguments: linuxTest -PnoCrossCompile=true + + macos: + name: iOS & Android + runs-on: macos-latest + steps: + - name: Check out + uses: actions/checkout@v2 + with: + submodules: 'true' + - name: Cached Konan + uses: actions/cache@v2 + with: + path: ~/.konan + key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} + restore-keys: ${{ runner.os }}-konan- + - name: Set up JDK 11 + uses: actions/setup-java@v1 + with: + java-version: 11 + - name: Install Automake + run: brew install automake + - name: Check iOS + uses: eskatos/gradle-command-action@v1 + with: + wrapper-cache-enabled: true + dependencies-cache-enabled: true + arguments: iosX64Test -PnoCrossCompile=true + - name: Check Android + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: 29 + ndk: 21.3.6528147 + cmake: 3.10.2.4988404 + script: ./gradlew connectedCheck -PnoCrossCompile=true diff --git a/README.md b/README.md index 7d4cb9b..a3739f8 100644 --- a/README.md +++ b/README.md @@ -2,3 +2,69 @@ Bitcoin's secp256k1 library ported to Kotlin/Multiplatform for JVM, Android, iOS & Linux. +## Installation + +### Multiplatform + +Add the `secp256k1` dependency to the common sourceSet, and the JNI dependencies to JVM and Android sourcesets: + +```kotlin +// build.gradle.kts + +kotlin { + jvm() + android() + linuxX64("linux") + ios() + + sourceSets { + val commonMain by getting { + dependencies { + implementation(kotlin("stdlib-common")) + implementation(kotlin("fr.acinq.secp256k1:secp256k1:$secp256k1_version")) + } + } + val jvmMain by getting { + dependencies { + implementation(kotlin("stdlib")) + implementation(kotlin("fr.acinq.secp256k1:secp256k1-jni-jvm:$secp256k1_version")) + } + } + val androidMain by getting { + dependencies { + implementation(kotlin("stdlib")) + implementation(kotlin("fr.acinq.secp256k1:secp256k1-jni-android:$secp256k1_version")) + } + } + } +} +``` + +### Native targets (iOS, linux64) + +Native targets include libsecp256k1, called through KMP's c-interop, simply add the `fr.acinq.secp256k1:secp256k1` dependency. + +### JVM target & Android + +The JVM library uses JNI bindings for libsecp256k1, which is much faster than BouncyCastle. It will extract and load native bindings for your operating system in a temporary directory. + +JNI libraries are included for: +- Linux 64 bits +- Windows 64 bits +- Macos 64 bits + +Along this library, you **must** specify which JNI native library to use in your dependency manager: + +* For desktop or server JVMs, you must add the `fr.acinq.secp256k1:secp256k1-jni-jvm` dependency +* For Android, you must add the `fr.acinq.secp256k1:secp256k1-jni-android` dependency + +If you are using the JVM on an OS for which we don't provide JNI bindings (32 bits OS for example), you can use your own library native library by +adding the `fr.acinq.secp256k1:secp256k1-jni-jvm` dependency and specifying its path with `-Dfr.acinq.secp256k1.lib.path` and optionally its name with `-Dfr.acinq.secp256k1.lib.name` +(if unspecified bitcoink use the standard name for your OS i.e. libsecp256k1.so on Linux, secp256k1.dll on Windows, ...). + +You can also specify the temporary directory where the library will be extracted with `-Djava.io.tmpdir` or `-Dfr.acinq.secp256k1.tmpdir` +(if you want to use a different directory from `-Djava.io.tmpdir`). + +## Usage + +Please have a look at unit tests, more samples will be added soon. diff --git a/build.gradle.kts b/build.gradle.kts index 540d3d1..d353c87 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -17,7 +17,7 @@ buildscript { allprojects { group = "fr.acinq.secp256k1" - version = "0.1.0-1.4-M2" + version = "0.1.1-1.4-M2" repositories { jcenter() @@ -110,7 +110,6 @@ allprojects { allprojects { plugins.withId("maven-publish") { publishing { - val snapshotName: String? by project val snapshotNumber: String? by project val bintrayUsername: String? = (properties["bintrayUsername"] as String?) ?: System.getenv("BINTRAY_USER") @@ -130,8 +129,12 @@ allprojects { } } + val gitRef: String? by project + val gitSha: String? by project + val eapBranch = gitRef?.split("/")?.last() ?: "dev" + val eapSuffix = gitSha?.let { "-${it.substring(0, 7)}" } ?: "" publications.withType().configureEach { - if (snapshotName != null && snapshotNumber != null) version = "${project.version}-${snapshotName}-${snapshotNumber}" + if (snapshotNumber != null) version = "${project.version}-$eapBranch-$snapshotNumber$eapSuffix" pom { description.set("Bitcoin's secp256k1 library ported to Kotlin/Multiplatform for JVM, Android, iOS & Linux") url.set("https://github.com/ACINQ/secp256k1-kmp") diff --git a/jni/build.gradle.kts b/jni/build.gradle.kts index e7565e8..a984915 100644 --- a/jni/build.gradle.kts +++ b/jni/build.gradle.kts @@ -49,12 +49,15 @@ sealed class Cross { 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")) diff --git a/jni/build.sh b/jni/build.sh index b56bb20..f0dd5d6 100755 --- a/jni/build.sh +++ b/jni/build.sh @@ -15,6 +15,7 @@ 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 if [ -z "$CROSS_TRIPLE" ]; then @@ -24,7 +25,7 @@ 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_OPTS="-fPIC" fi mkdir -p build/jni/$TARGET diff --git a/native/build.gradle.kts b/native/build.gradle.kts index eed1c8a..09968d5 100644 --- a/native/build.gradle.kts +++ b/native/build.gradle.kts @@ -25,10 +25,13 @@ val buildSecp256k1Jvm by tasks.creating { group = "build" buildSecp256k1.dependsOn(this) } +val noCrossCompile: String? by project fun creatingBuildSecp256k1(target: String, cross: Cross?) = tasks.creating(Exec::class) { group = "build" buildSecp256k1Jvm.dependsOn(this) + if (noCrossCompile == "true") onlyIf { cross == null } + inputs.files(projectDir.resolve("build.sh")) outputs.dir(projectDir.resolve("build/$target")) diff --git a/native/build.sh b/native/build.sh index f94ec8d..b1bb46e 100755 --- a/native/build.sh +++ b/native/build.sh @@ -12,12 +12,15 @@ cd "$(dirname "$0")" cd secp256k1 if [ "$TARGET" == "mingw" ]; then - CONF_OPTS="CFLAGS=-fpic --host=x86_64-w64-mingw32" + CONF_OPTS="CFLAGS=-fPIC --host=x86_64-w64-mingw32" elif [ "$TARGET" == "linux" ]; then - CONF_OPTS="CFLAGS=-fpic" + CONF_OPTS="CFLAGS=-fPIC" [ "$CROSS" == "1" ] && sudo apt -y install libgmp-dev elif [ "$TARGET" == "darwin" ]; then CONF_OPTS="--host=x86_64-w64-darwin" +else + echo "Unknown TARGET=$TARGET" + exit 1 fi ./autogen.sh