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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 393 additions and 694 deletions

View File

@ -5,10 +5,12 @@ on:
types: [published] types: [published]
jobs: jobs:
upload:
publish-ios: name: Upload
name: Publish iOS native runs-on: ${{ matrix.os }}
runs-on: macOS-latest strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -20,54 +22,65 @@ jobs:
path: ~/.konan path: ~/.konan
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-konan- restore-keys: ${{ runner.os }}-konan-
- name: Install automake - name: Cached Gradle
uses: actions/cache@v2
with:
path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Install Automake
if: matrix.os == 'macOS-latest'
run: brew install automake run: brew install automake
- name: Set up JDK 11 - name: Set up shell
uses: actions/setup-java@v1 if: matrix.os == 'windows-latest'
run: echo ::add-path::C:\msys64\usr\bin\
- name: Check JVM
shell: bash
run: ./gradlew jvmTest
- name: Check Linux
if: matrix.os == 'ubuntu-latest'
shell: bash
run: ./gradlew linuxTest
- name: Check iOS
if: matrix.os == 'macOS-latest'
shell: bash
run: ./gradlew iosX64Test
- name: Check Android
if: matrix.os == 'macOS-latest'
uses: reactivecircus/android-emulator-runner@v2
with: with:
java-version: 11 api-level: 29
- name: Check ndk: 21.3.6528147
uses: eskatos/gradle-command-action@v1 cmake: 3.10.2.4988404
with: script: ./gradlew connectedCheck
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 - name: Publish Linux
arguments: iosX64Test if: matrix.os == 'ubuntu-latest'
- name: Publish
uses: eskatos/gradle-command-action@v1
env: env:
BINTRAY_USER: ${{ secrets.bintray_user }} BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
with: shell: bash
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 run: ./gradlew publishLinuxPublicationToBintrayRepository :jni:jvm:linux:publishJvmPublicationToBintrayRepository
arguments: publishIosArm64PublicationToBintrayRepository publishIosX64PublicationToBintrayRepository - name: Publish Windows
if: matrix.os == 'windows-latest'
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: false # https://github.com/eskatos/gradle-command-action/issues/24
arguments: check
- name: Publish
uses: eskatos/gradle-command-action@v1
env: env:
BINTRAY_USER: ${{ secrets.bintray_user }} BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
with: shell: bash
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 run: ./gradlew :jni:jvm:mingw:publishJvmPublicationToBintrayRepository
arguments: publishAllPublicationsToBintrayRepository - name: Publish MacOS
if: matrix.os == 'macOS-latest'
env:
BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
shell: bash
run: ./gradlew publish
- name: Discard
if: ${{ failure() || cancelled() }}
env:
BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
run: ./gradlew postBintrayDiscard

View File

@ -13,9 +13,12 @@ on:
jobs: jobs:
publish-ios: upload:
name: Publish iOS native name: Upload
runs-on: macOS-latest runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -27,54 +30,90 @@ jobs:
path: ~/.konan path: ~/.konan
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-konan- restore-keys: ${{ runner.os }}-konan-
- name: Install automake - name: Cached Gradle
run: brew install automake uses: actions/cache@v2
with:
path: ~/.gradle
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-gradle-
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Check - name: Install Automake
uses: eskatos/gradle-command-action@v1 if: matrix.os == 'macOS-latest'
run: brew install automake
- name: Set up shell
if: matrix.os == 'windows-latest'
run: echo ::add-path::C:\msys64\usr\bin\
- name: Check JVM
shell: bash
run: ./gradlew jvmTest
- name: Check Linux
if: matrix.os == 'ubuntu-latest'
shell: bash
run: ./gradlew linuxTest
- name: Check iOS
if: matrix.os == 'macOS-latest'
shell: bash
run: ./gradlew iosX64Test
- name: Check Android
if: matrix.os == 'macOS-latest'
uses: reactivecircus/android-emulator-runner@v2
with: with:
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 api-level: 29
arguments: iosX64Test ndk: 21.3.6528147
- name: Publish cmake: 3.10.2.4988404
uses: eskatos/gradle-command-action@v1 script: ./gradlew connectedCheck
- name: Publish Linux
if: matrix.os == 'ubuntu-latest'
env: env:
BINTRAY_USER: ${{ secrets.bintray_user }} BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
with: shell: bash
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 run: ./gradlew publishLinuxPublicationToBintrayRepository :jni:jvm:linux:publishJvmPublicationToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
arguments: publishIosArm64PublicationToBintrayRepository publishIosX64PublicationToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }} -PgitSha=${{ github.sha }} - name: Publish Windows
if: matrix.os == 'windows-latest'
env:
BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
shell: bash
run: ./gradlew :jni:jvm:mingw:publishJvmPublicationToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
- name: Publish MacOS
if: matrix.os == 'macOS-latest'
env:
BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
shell: bash
run: ./gradlew publish -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
- name: Discard
if: ${{ failure() || cancelled() }}
env:
BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
run: ./gradlew postBintrayDiscard -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
publish: publish:
name: Publish JVM & Linux native name: Publish
needs: upload
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
submodules: 'true' submodules: 'true'
- name: Cached Konan - name: Cached Gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ~/.konan path: ~/.gradle
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-konan- restore-keys: ${{ runner.os }}-gradle-
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Check
uses: eskatos/gradle-command-action@v1
with:
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24
arguments: check
- name: Publish - name: Publish
uses: eskatos/gradle-command-action@v1
env: env:
BINTRAY_USER: ${{ secrets.bintray_user }} BINTRAY_USER: ${{ secrets.bintray_user }}
BINTRAY_APIKEY: ${{ secrets.bintray_apikey }} BINTRAY_APIKEY: ${{ secrets.bintray_apikey }}
with: run: ./gradlew postBintrayPublish -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }}
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24
arguments: publishAllPublicationsToBintrayRepository -PsnapshotNumber=${{ github.run_number }} -PgitRef=${{ github.ref }} -PgitSha=${{ github.sha }}

View File

@ -19,10 +19,12 @@ on:
- '!.github/workflows/test.yml' - '!.github/workflows/test.yml'
jobs: jobs:
check:
linux: name: Check
name: JNI & Linux runs-on: ${{ matrix.os }}
runs-on: ubuntu-latest strategy:
matrix:
os: [ubuntu-latest, macOS-latest, windows-latest]
steps: steps:
- name: Check out - name: Check out
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -34,53 +36,38 @@ jobs:
path: ~/.konan path: ~/.konan
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-konan- restore-keys: ${{ runner.os }}-konan-
- name: Set up JDK 11 - name: Cached Gradle
uses: actions/setup-java@v1
with:
java-version: 11
- name: Check JNI
uses: eskatos/gradle-command-action@v1
with:
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24
dependencies-cache-enabled: false
arguments: jvmTest -PnoCrossCompile=true
- name: Check Linux
uses: eskatos/gradle-command-action@v1
with:
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24
dependencies-cache-enabled: false
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 uses: actions/cache@v2
with: with:
path: ~/.konan path: ~/.gradle
key: ${{ runner.os }}-konan-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}
restore-keys: ${{ runner.os }}-konan- restore-keys: ${{ runner.os }}-gradle-
- name: Set up JDK 11 - name: Set up JDK 11
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 11 java-version: 11
- name: Install Automake - name: Install Automake
if: matrix.os == 'macOS-latest'
run: brew install automake run: brew install automake
- name: Set up shell
if: matrix.os == 'windows-latest'
run: echo ::add-path::C:\msys64\usr\bin\
- name: Check JVM
shell: bash
run: ./gradlew jvmTest
- name: Check Linux
if: matrix.os == 'ubuntu-latest'
shell: bash
run: ./gradlew linuxTest
- name: Check iOS - name: Check iOS
uses: eskatos/gradle-command-action@v1 if: matrix.os == 'macOS-latest'
with: shell: bash
wrapper-cache-enabled: false # https://github.com/eskatos/gradle-command-action/issues/24 run: ./gradlew iosX64Test
dependencies-cache-enabled: false
arguments: iosX64Test -PnoCrossCompile=true
- name: Check Android - name: Check Android
if: matrix.os == 'macOS-latest'
uses: reactivecircus/android-emulator-runner@v2 uses: reactivecircus/android-emulator-runner@v2
with: with:
api-level: 29 api-level: 29
ndk: 21.3.6528147 ndk: 21.3.6528147
cmake: 3.10.2.4988404 cmake: 3.10.2.4988404
script: ./gradlew connectedCheck -PnoCrossCompile=true script: ./gradlew connectedCheck

View File

@ -68,13 +68,20 @@ JNI libraries are included for:
Along this library, you **must** specify which JNI native library to use in your dependency manager: 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 desktop or server JVMs**, you must add the dependency:
* For Android, you must add the `fr.acinq.secp256k1:secp256k1-jni-android` dependency * Either the `fr.acinq.secp256k1:secp256k1-jni-jvm` dependency which imports all supported platforms.
* Or the platform specific dependencies (note that you can add multiple as they do not conflict):
* `fr.acinq.secp256k1:secp256k1-jni-jvm-linux` for Linux
* `fr.acinq.secp256k1:secp256k1-jni-jvm-darwin` for Mac OS X
* `fr.acinq.secp256k1:secp256k1-jni-jvm-mingw` for Windows
* **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 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` 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, ...). (if unspecified bitcoink use the standard name for your OS i.e. libsecp256k1.so on Linux, secp256k1.dll on Windows, ...).
To compile your own JNI bindings, have a look add the `native/build.sh` and `jni/build.sh` scripts.
You can also specify the temporary directory where the library will be extracted with `-Djava.io.tmpdir` or `-Dfr.acinq.secp256k1.tmpdir` 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`). (if you want to use a different directory from `-Djava.io.tmpdir`).

View File

@ -1,3 +1,10 @@
import org.apache.http.impl.client.HttpClients
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.ContentType
import org.apache.http.entity.StringEntity
import org.apache.http.impl.auth.BasicScheme
import org.apache.http.auth.UsernamePasswordCredentials
plugins { plugins {
kotlin("multiplatform") version "1.4-M3" kotlin("multiplatform") version "1.4-M3"
`maven-publish` `maven-publish`
@ -17,7 +24,7 @@ buildscript {
allprojects { allprojects {
group = "fr.acinq.secp256k1" group = "fr.acinq.secp256k1"
version = "0.1.0-1.4-M3" version = "0.2.0-1.4-M3"
repositories { repositories {
jcenter() jcenter()
@ -58,7 +65,7 @@ kotlin {
val nativeMain by sourceSets.creating { dependsOn(commonMain) } val nativeMain by sourceSets.creating { dependsOn(commonMain) }
linuxX64("linux") { linuxX64("linux") {
secp256k1CInterop("linux") secp256k1CInterop("host")
// https://youtrack.jetbrains.com/issue/KT-39396 // https://youtrack.jetbrains.com/issue/KT-39396
compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/linux/libsecp256k1.a") compilations["main"].kotlinOptions.freeCompilerArgs += listOf("-include-binary", "$rootDir/native/build/linux/libsecp256k1.a")
compilations["main"].defaultSourceSet.dependsOn(nativeMain) compilations["main"].defaultSourceSet.dependsOn(nativeMain)
@ -107,21 +114,25 @@ allprojects {
} }
} }
val snapshotNumber: String? by project
val gitRef: String? by project
val eapBranch = gitRef?.split("/")?.last() ?: "dev"
val bintrayVersion = if (snapshotNumber != null) "${project.version}-$eapBranch-$snapshotNumber" else project.version.toString()
val bintrayRepo = if (snapshotNumber != null) "snapshots" else "libs"
val bintrayUsername: String? = (properties["bintrayUsername"] as String?) ?: System.getenv("BINTRAY_USER")
val bintrayApiKey: String? = (properties["bintrayApiKey"] as String?) ?: System.getenv("BINTRAY_APIKEY")
val hasBintray = bintrayUsername != null && bintrayApiKey != null
if (!hasBintray) logger.warn("Skipping bintray configuration as bintrayUsername or bintrayApiKey is not defined")
allprojects { allprojects {
plugins.withId("maven-publish") { plugins.withId("maven-publish") {
publishing { publishing {
val snapshotNumber: String? by project if (hasBintray) {
val bintrayUsername: String? = (properties["bintrayUsername"] as String?) ?: System.getenv("BINTRAY_USER")
val bintrayApiKey: String? = (properties["bintrayApiKey"] as String?) ?: System.getenv("BINTRAY_APIKEY")
if (bintrayUsername == null || bintrayApiKey == null) logger.warn("Skipping bintray configuration as bintrayUsername or bintrayApiKey is not defined")
else {
val btRepo = if (snapshotNumber != null) "snapshots" else "libs"
val btPublish = if (snapshotNumber != null) "1" else "0"
repositories { repositories {
maven { maven {
name = "bintray" name = "bintray"
setUrl("https://api.bintray.com/maven/acinq/$btRepo/${rootProject.name}/;publish=$btPublish") setUrl("https://api.bintray.com/maven/acinq/$bintrayRepo/${rootProject.name}/;publish=0")
credentials { credentials {
username = bintrayUsername username = bintrayUsername
password = bintrayApiKey password = bintrayApiKey
@ -130,12 +141,8 @@ 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<MavenPublication>().configureEach { publications.withType<MavenPublication>().configureEach {
if (snapshotNumber != null) version = "${project.version}-$eapBranch-$snapshotNumber$eapSuffix" version = bintrayVersion
pom { pom {
description.set("Bitcoin's secp256k1 library ported to Kotlin/Multiplatform for JVM, Android, iOS & Linux") description.set("Bitcoin's secp256k1 library ported to Kotlin/Multiplatform for JVM, Android, iOS & Linux")
url.set("https://github.com/ACINQ/secp256k1-kmp") url.set("https://github.com/ACINQ/secp256k1-kmp")
@ -155,3 +162,39 @@ allprojects {
} }
} }
} }
if (hasBintray) {
val postBintrayPublish by tasks.creating {
doLast {
HttpClients.createDefault().use { client ->
val post = HttpPost("https://api.bintray.com/content/acinq/$bintrayRepo/${rootProject.name}/$bintrayVersion/publish").apply {
entity = StringEntity("{}", ContentType.APPLICATION_JSON)
addHeader(BasicScheme().authenticate(UsernamePasswordCredentials(bintrayUsername, bintrayApiKey), this, null))
}
client.execute(post)
}
}
}
val postBintrayDiscard by tasks.creating {
doLast {
HttpClients.createDefault().use { client ->
val post = HttpPost("https://api.bintray.com/content/acinq/$bintrayRepo/${rootProject.name}/$bintrayVersion/publish").apply {
entity = StringEntity("{ \"discard\": true }", ContentType.APPLICATION_JSON)
addHeader(BasicScheme().authenticate(UsernamePasswordCredentials(bintrayUsername, bintrayApiKey), this, null))
}
client.execute(post)
}
}
}
}
afterEvaluate {
tasks.withType<AbstractTestTask>() {
testLogging {
events("passed", "skipped", "failed", "standard_out", "standard_error")
showExceptions = true
showStackTraces = true
}
}
}

View File

@ -1,256 +0,0 @@
#!/usr/bin/env bash
DEFAULT_DOCKCROSS_IMAGE=dockcross/linux-x64:latest
#------------------------------------------------------------------------------
# Helpers
#
err() {
echo -e >&2 ERROR: $@\\n
}
die() {
err $@
exit 1
}
has() {
# eg. has command update
local kind=$1
local name=$2
type -t $kind:$name | grep -q function
}
#------------------------------------------------------------------------------
# Command handlers
#
command:update-image() {
docker pull $FINAL_IMAGE
}
help:update-image() {
echo Pull the latest $FINAL_IMAGE .
}
command:update-script() {
if cmp -s <( docker run --rm $FINAL_IMAGE ) $0; then
echo $0 is up to date
else
echo -n Updating $0 '... '
docker run --rm $FINAL_IMAGE > $0 && echo ok
fi
}
help:update-image() {
echo Update $0 from $FINAL_IMAGE .
}
command:update() {
command:update-image
command:update-script
}
help:update() {
echo Pull the latest $FINAL_IMAGE, and then update $0 from that.
}
command:help() {
if [[ $# != 0 ]]; then
if ! has command $1; then
err \"$1\" is not an dockcross command
command:help
elif ! has help $1; then
err No help found for \"$1\"
else
help:$1
fi
else
cat >&2 <<ENDHELP
Usage: dockcross [options] [--] command [args]
By default, run the given *command* in an dockcross Docker container.
The *options* can be one of:
--args|-a Extra args to the *docker run* command
--image|-i Docker cross-compiler image to use
--config|-c Bash script to source before running this script
Additionally, there are special update commands:
update-image
update-script
update
For update command help use: $0 help <command>
ENDHELP
exit 1
fi
}
#------------------------------------------------------------------------------
# Option processing
#
special_update_command=''
while [[ $# != 0 ]]; do
case $1 in
--)
shift
break
;;
--args|-a)
ARG_ARGS="$2"
shift 2
;;
--config|-c)
ARG_CONFIG="$2"
shift 2
;;
--image|-i)
ARG_IMAGE="$2"
shift 2
;;
update|update-image|update-script)
special_update_command=$1
break
;;
-*)
err Unknown option \"$1\"
command:help
exit
;;
*)
break
;;
esac
done
# The precedence for options is:
# 1. command-line arguments
# 2. environment variables
# 3. defaults
# Source the config file if it exists
DEFAULT_DOCKCROSS_CONFIG=~/.dockcross
FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}}
[[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG"
# Set the docker image
FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}}
# Handle special update command
if [ "$special_update_command" != "" ]; then
case $special_update_command in
update)
command:update
exit $?
;;
update-image)
command:update-image
exit $?
;;
update-script)
command:update-script
exit $?
;;
esac
fi
# Set the docker run extra args (if any)
FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}}
# Bash on Ubuntu on Windows
UBUNTU_ON_WINDOWS=$([ -e /proc/version ] && grep -l Microsoft /proc/version || echo "")
# MSYS, Git Bash, etc.
MSYS=$([ -e /proc/version ] && grep -l MINGW /proc/version || echo "")
if [ -z "$UBUNTU_ON_WINDOWS" -a -z "$MSYS" ]; then
USER_IDS=(-e BUILDER_UID="$( id -u )" -e BUILDER_GID="$( id -g )" -e BUILDER_USER="$( id -un )" -e BUILDER_GROUP="$( id -gn )")
fi
# Change the PWD when working in Docker on Windows
if [ -n "$UBUNTU_ON_WINDOWS" ]; then
WSL_ROOT="/mnt/"
CFG_FILE=/etc/wsl.conf
if [ -f "$CFG_FILE" ]; then
CFG_CONTENT=$(cat $CFG_FILE | sed -r '/[^=]+=[^=]+/!d' | sed -r 's/\s+=\s/=/g')
eval "$CFG_CONTENT"
if [ -n "$root" ]; then
WSL_ROOT=$root
fi
fi
HOST_PWD=`pwd -P`
HOST_PWD=${HOST_PWD/$WSL_ROOT//}
elif [ -n "$MSYS" ]; then
HOST_PWD=$PWD
HOST_PWD=${HOST_PWD/\//}
HOST_PWD=${HOST_PWD/\//:\/}
else
HOST_PWD=$PWD
[ -L $HOST_PWD ] && HOST_PWD=$(readlink $HOST_PWD)
fi
# Mount Additional Volumes
if [ -z "$SSH_DIR" ]; then
SSH_DIR="$HOME/.ssh"
fi
HOST_VOLUMES=
if [ -e "$SSH_DIR" -a -z "$MSYS" ]; then
HOST_VOLUMES+="-v $SSH_DIR:/home/$(id -un)/.ssh"
fi
#------------------------------------------------------------------------------
# Now, finally, run the command in a container
#
TTY_ARGS=
tty -s && [ -z "$MSYS" ] && TTY_ARGS=-ti
CONTAINER_NAME=dockcross_$RANDOM
docker run $TTY_ARGS --name $CONTAINER_NAME \
-v "$HOST_PWD":/work \
$HOST_VOLUMES \
"${USER_IDS[@]}" \
$FINAL_ARGS \
$FINAL_IMAGE "$@"
run_exit_code=$?
# Attempt to delete container
rm_output=$(docker rm -f $CONTAINER_NAME 2>&1)
rm_exit_code=$?
if [[ $rm_exit_code != 0 ]]; then
if [[ "$CIRCLECI" == "true" ]] && [[ $rm_output == *"Driver btrfs failed to remove"* ]]; then
: # Ignore error because of https://circleci.com/docs/docker-btrfs-error/
else
echo "$rm_output"
exit $rm_exit_code
fi
fi
exit $run_exit_code
################################################################################
#
# This image is not intended to be run manually.
#
# To create a dockcross helper script for the
# dockcross/linux-x64:latest image, run:
#
# docker run --rm dockcross/linux-x64:latest > dockcross-linux-x64-latest
# chmod +x dockcross-linux-x64-latest
#
# You may then wish to move the dockcross script to your PATH.
#
################################################################################

View File

@ -1,200 +0,0 @@
#!/bin/bash
DEFAULT_DOCKCROSS_IMAGE=dockcross/windows-x64
#------------------------------------------------------------------------------
# Helpers
#
err() {
echo -e >&2 ERROR: $@\\n
}
die() {
err $@
exit 1
}
has() {
# eg. has command update
local kind=$1
local name=$2
type -t $kind:$name | grep -q function
}
#------------------------------------------------------------------------------
# Command handlers
#
command:update-image() {
docker pull $FINAL_IMAGE
}
help:update-image() {
echo Pull the latest $FINAL_IMAGE .
}
command:update-script() {
if cmp -s <( docker run $FINAL_IMAGE ) $0; then
echo $0 is up to date
else
echo -n Updating $0 '... '
docker run $FINAL_IMAGE > $0 && echo ok
fi
}
help:update-image() {
echo Update $0 from $FINAL_IMAGE .
}
command:update() {
command:update-image
command:update-script
}
help:update() {
echo Pull the latest $FINAL_IMAGE, and then update $0 from that.
}
command:help() {
if [[ $# != 0 ]]; then
if ! has command $1; then
err \"$1\" is not an dockcross command
command:help
elif ! has help $1; then
err No help found for \"$1\"
else
help:$1
fi
else
cat >&2 <<ENDHELP
Usage: dockcross [options] [--] command [args]
By default, run the given *command* in an dockcross Docker container.
The *options* can be one of:
--args|-a Extra args to the *docker run* command
--image|-i Docker cross-compiler image to use
--config|-c Bash script to source before running this script
Additionally, there are special update commands:
update-image
update-script
update
For update command help use: $0 help <command>
ENDHELP
exit 1
fi
}
#------------------------------------------------------------------------------
# Option processing
#
special_update_command=''
while [[ $# != 0 ]]; do
case $1 in
--)
break
;;
--args|-a)
ARG_ARGS="$2"
shift 2
;;
--config|-c)
ARG_CONFIG="$2"
shift 2
;;
--image|-i)
ARG_IMAGE="$2"
shift 2
;;
update|update-image|update-script)
special_update_command=$1
break
;;
-*)
err Unknown option \"$1\"
command:help
exit
;;
*)
break
;;
esac
done
# The precedence for options is:
# 1. command-line arguments
# 2. environment variables
# 3. defaults
# Source the config file if it exists
DEFAULT_DOCKCROSS_CONFIG=~/.dockcross
FINAL_CONFIG=${ARG_CONFIG-${DOCKCROSS_CONFIG-$DEFAULT_DOCKCROSS_CONFIG}}
[[ -f "$FINAL_CONFIG" ]] && source "$FINAL_CONFIG"
# Set the docker image
FINAL_IMAGE=${ARG_IMAGE-${DOCKCROSS_IMAGE-$DEFAULT_DOCKCROSS_IMAGE}}
# Handle special update command
if [ "$special_update_command" != "" ]; then
case $special_update_command in
update)
command:update
exit $?
;;
update-image)
command:update-image
exit $?
;;
update-script)
command:update-script
exit $?
;;
esac
fi
# Set the docker run extra args (if any)
FINAL_ARGS=${ARG_ARGS-${DOCKCROSS_ARGS}}
# If we are not running via boot2docker
if [ -z $DOCKER_HOST ]; then
USER_IDS=(-e BUILDER_UID="$( id -u )" -e BUILDER_GID="$( id -g )" -e BUILDER_USER="$( id -un )" -e BUILDER_GROUP="$( id -gn )")
fi
#------------------------------------------------------------------------------
# Now, finally, run the command in a container
#
docker run --rm \
-v $PWD:/work \
"${USER_IDS[@]}" \
$FINAL_ARGS \
$FINAL_IMAGE "$@"
################################################################################
#
# This image is not intended to be run manually.
#
# To create a dockcross helper script for the
# dockcross/linux-armv7 image, run:
#
# docker run --rm dockcross/linux-armv7 > dockcross-linux-armv7
# chmod +x dockcross-linux-armv7
#
# You may then wish to move the dockcross script to your PATH.
#
################################################################################

View File

@ -8,6 +8,7 @@ kotlin.incremental.multiplatform = true
kotlin.parallel.tasks.in.project = true kotlin.parallel.tasks.in.project = true
#kotlin.mpp.enableGranularSourceSetsMetadata = true #kotlin.mpp.enableGranularSourceSetsMetadata = true
kotlin.native.enableDependencyPropagation = false kotlin.native.enableDependencyPropagation = false
kotlin.native.ignoreDisabledTargets = true
# https://github.com/gradle/gradle/issues/11412 # https://github.com/gradle/gradle/issues/11412
systemProp.org.gradle.internal.publish.checksums.insecure = true systemProp.org.gradle.internal.publish.checksums.insecure = true

View File

@ -3,8 +3,6 @@ plugins {
`maven-publish` `maven-publish`
} }
val currentOs = org.gradle.internal.os.OperatingSystem.current()
kotlin { kotlin {
explicitApi() explicitApi()
} }
@ -14,7 +12,7 @@ dependencies {
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
} }
val generateJniHeaders by tasks.creating(JavaCompile::class) { val generateHeaders by tasks.creating(JavaCompile::class) {
group = "build" group = "build"
classpath = sourceSets["main"].compileClasspath classpath = sourceSets["main"].compileClasspath
destinationDir = file("${buildDir}/generated/jni") 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 { publishing {
publications { publications {
create<MavenPublication>("jvm") { create<MavenPublication>("jvm") {

View File

@ -12,6 +12,8 @@
#define JNIIMPORT __declspec(dllimport) #define JNIIMPORT __declspec(dllimport)
#define JNICALL __stdcall #define JNICALL __stdcall
#include <stdint.h>
typedef long jint; typedef long jint;
typedef int64_t jlong; typedef int64_t jlong;
typedef signed char jbyte; typedef signed char jbyte;

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` `maven-publish`
} }
kotlin { val currentOs = org.gradle.internal.os.OperatingSystem.current()
explicitApi() 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 { dependencies {
@ -12,26 +31,17 @@ dependencies {
implementation(kotlin("stdlib-jdk8")) 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 { publishing {
publications { publications {
create<MavenPublication>("jvm") { create<MavenPublication>("jvm") {
artifactId = "secp256k1-jni-jvm" artifactId = "secp256k1-jni-jvm-extract"
from(components["java"]) from(components["java"])
} }
} }
} }
afterEvaluate {
tasks["clean"].doLast {
delete("$buildDir/build/cmake")
}
}

View File

@ -14,7 +14,6 @@ JNI_HEADERS=$TARGET
if [ "$TARGET" == "linux" ]; then if [ "$TARGET" == "linux" ]; then
OUTFILE=libsecp256k1-jni.so OUTFILE=libsecp256k1-jni.so
[ "$CROSS" == "1" ] && sudo apt -y install libgmp-dev
ADD_LIB=-lgmp ADD_LIB=-lgmp
CC_OPTS="-fPIC" CC_OPTS="-fPIC"
elif [ "$TARGET" == "darwin" ]; then elif [ "$TARGET" == "darwin" ]; then
@ -22,14 +21,12 @@ elif [ "$TARGET" == "darwin" ]; then
ADD_LIB=-lgmp ADD_LIB=-lgmp
elif [ "$TARGET" == "mingw" ]; then elif [ "$TARGET" == "mingw" ]; then
OUTFILE=secp256k1-jni.dll OUTFILE=secp256k1-jni.dll
CC=/usr/src/mxe/usr/bin/x86_64-w64-mingw32.static-gcc CC=x86_64-w64-mingw32-gcc
JNI_HEADERS=linux
CC_OPTS="-fPIC"
fi fi
mkdir -p build/jni/$TARGET 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 . [[ ! -z "$TO_UID" ]] && chown -R $TO_UID:$TO_UID .

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

View File

@ -1,47 +1,28 @@
evaluationDependsOn(":jni:android") evaluationDependsOn(":jni:android")
val currentOs = org.gradle.internal.os.OperatingSystem.current() val currentOs = org.gradle.internal.os.OperatingSystem.current()
val bash = if (currentOs.isWindows) "bash.exe" else "bash"
val buildSecp256k1 by tasks.creating { group = "build" } val buildSecp256k1 by tasks.creating { group = "build" }
sealed class Cross { val buildSecp256k1Host by tasks.creating(Exec::class) {
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 ./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.projectDir.absolutePath}:/workdir",
"-e", "CROSS_TRIPLE=$crossTriple", "-e", "TARGET=$target", "-e", "TO_UID=$uid", "-e", "CROSS=1",
"multiarch/crossbuild", "./build.sh"
)
}
}
}
val buildSecp256k1Jvm by tasks.creating {
group = "build" group = "build"
buildSecp256k1.dependsOn(this) 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 } val target = when {
currentOs.isLinux -> "linux"
currentOs.isMacOsX -> "darwin"
currentOs.isWindows -> "mingw"
else -> error("UnsupportedmOS $currentOs")
}
inputs.files(projectDir.resolve("build.sh")) inputs.files(projectDir.resolve("build.sh"))
outputs.dir(projectDir.resolve("build/$target")) outputs.dir(projectDir.resolve("build/$target"))
workingDir = projectDir workingDir = projectDir
environment("TARGET", target) environment("TARGET", target)
commandLine((cross?.cmd(target, project) ?: emptyList()) + "./build.sh") commandLine(bash, "build.sh")
} }
val buildSecp256k1Darwin by creatingBuildSecp256k1("darwin", if (currentOs.isMacOsX) null else Cross.MultiArch("x86_64-apple-darwin"))
val buildSecp256k1Linux by creatingBuildSecp256k1("linux", if (currentOs.isLinux) null else Cross.DockCross("linux-x64"))
val buildSecp256k1Mingw by creatingBuildSecp256k1("mingw", if (currentOs.isWindows) null else Cross.DockCross("windows-x64"))
val buildSecp256k1Ios by tasks.creating(Exec::class) { val buildSecp256k1Ios by tasks.creating(Exec::class) {
group = "build" group = "build"
@ -53,7 +34,7 @@ val buildSecp256k1Ios by tasks.creating(Exec::class) {
outputs.dir(projectDir.resolve("build/ios")) outputs.dir(projectDir.resolve("build/ios"))
workingDir = projectDir workingDir = projectDir
commandLine("./build-ios.sh") commandLine(bash, "build-ios.sh")
} }
val buildSecp256k1Android by tasks.creating { val buildSecp256k1Android by tasks.creating {
@ -78,7 +59,7 @@ fun creatingBuildSecp256k1Android(arch: String) = tasks.creating(Exec::class) {
environment("TOOLCHAIN", toolchain) environment("TOOLCHAIN", toolchain)
environment("ARCH", arch) environment("ARCH", arch)
environment("ANDROID_NDK", (project(":jni:android").extensions["android"] as com.android.build.gradle.LibraryExtension).ndkDirectory) environment("ANDROID_NDK", (project(":jni:android").extensions["android"] as com.android.build.gradle.LibraryExtension).ndkDirectory)
commandLine("./build-android.sh") commandLine(bash, "build-android.sh")
} }
val buildSecp256k1AndroidX86_64 by creatingBuildSecp256k1Android("x86_64") val buildSecp256k1AndroidX86_64 by creatingBuildSecp256k1Android("x86_64")
val buildSecp256k1AndroidX86 by creatingBuildSecp256k1Android("x86") val buildSecp256k1AndroidX86 by creatingBuildSecp256k1Android("x86")

View File

@ -6,12 +6,16 @@ pluginManagement {
jcenter() jcenter()
} }
} }
rootProject.name = "secp256k1-kmp" rootProject.name = "secp256k1"
include( include(
":native", ":native",
":jni", ":jni",
":jni:android", ":jni:android",
":jni:jvm", ":jni:jvm",
":jni:jvm:darwin",
":jni:jvm:linux",
":jni:jvm:mingw",
":jni:jvm:all",
":tests" ":tests"
) )

View File

@ -24,7 +24,7 @@ kotlin {
} }
compilations["main"].dependencies { compilations["main"].dependencies {
implementation(kotlin("stdlib-jdk8")) implementation(kotlin("stdlib-jdk8"))
implementation(project(":jni:jvm")) implementation(project(":jni:jvm:all"))
} }
compilations["test"].dependencies { compilations["test"].dependencies {
implementation(kotlin("test-junit")) implementation(kotlin("test-junit"))