diff --git a/build.gradle b/build.gradle index ef849e5..e6b97f4 100644 --- a/build.gradle +++ b/build.gradle @@ -9,18 +9,15 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.3.1' + classpath 'com.android.tools.build:gradle:3.3.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}" - classpath 'javax.inject:javax.inject:1' - classpath 'net.java.dev.jna:jna-platform:4.5.1' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } } - allprojects { repositories { google() diff --git a/requirements.lock b/requirements.lock index 0c9aef0..eb1691b 100644 --- a/requirements.lock +++ b/requirements.lock @@ -1,51 +1,56 @@ -# Generated with dmenv 0.11.1, python 3.7.1, on Linux --e git+ssh://git@tanker.local/Tanker/ci@9057d36029825cc05210c1083f26fcaff2a2bf0c#egg=ci -astroid==2.2.4 +# Generated with dmenv 0.11.0, python 3.7.2+, on Linux +-e git+ssh://git@tanker.local/Tanker/ci@d74efd7ac6bf2383788cec6b011dd80bc8fa145c#egg=ci +astroid==2.0.4 attrs==19.1.0 -bottle==0.12.16 -certifi==2018.11.29 +bottle==0.12.13 +certifi==2018.10.15 chardet==3.0.4 cli-ui==0.9.1 -colorama==0.4.1 +colorama==0.3.9 conan==1.12.3 contextlib2==0.5.5 deprecation==2.0.6 distro==1.1.0 -docopt==0.6.2 +docopt==0.4.0 fasteners==0.14.1 future==0.16.0 -idna==2.8 -importlib-metadata==0.8 -isort==4.3.10 +idna==2.7 +importlib-metadata==0.6 +isort==4.3.4 lazy-object-proxy==1.3.1 mandrill-really-maintained==1.2.4 +mandrill==1.0.57 mccabe==0.6.1 monotonic==1.5 +mypy-extensions==0.4.1 +mypy==0.641 node-semver==0.6.1 -packaging==19.0 +packaging==18.0 patch==1.16 path.py==11.5.0 pip==19.0.3 pluginbase==0.7 psutil==5.6.0 -Pygments==2.3.1 -PyJWT==1.7.1 -pylint==2.3.1 -pyparsing==2.3.1 -python-gitlab==1.8.0 +Pygments==2.2.0 +PyJWT==1.6.4 +pylint==2.1.1 +pyparsing==2.3.0 +python-gitlab==1.6.0 PyYAML==3.13 -requests==2.21.0 +requests==2.20.0 +ruamel.yaml==0.15.89 schema==0.7.0 setuptools==40.8.0 -six==1.12.0 -tabulate==0.8.3 +six==1.11.0 +tabulate==0.8.2 tbump==5.0.3 toml==0.10.0 +tqdm-conan==4.27.0 tqdm==4.31.1 -typed-ast==1.3.1 -Unidecode==1.0.23 +typed-ast==1.1.0 +Unidecode==1.0.22 urllib3==1.24.1 websockets==7.0 wheel==0.33.1 -wrapt==1.11.1 +wrapt==1.10.11 zipp==0.3.3 diff --git a/run-ci.py b/run-ci.py index eb7e8e1..4b98441 100644 --- a/run-ci.py +++ b/run-ci.py @@ -27,7 +27,7 @@ def main(): args = parser.parse_args() if args.command == "update-conan-config": - ci.cpp.update_conan_config(args.platform) + ci.cpp.update_conan_config() elif args.command == "check": ci.android.check(native_from_sources=args.native_from_sources) elif args.command == "deploy": diff --git a/tanker-bindings/build.gradle b/tanker-bindings/build.gradle index 0616120..10bee61 100644 --- a/tanker-bindings/build.gradle +++ b/tanker-bindings/build.gradle @@ -1,10 +1,9 @@ -import com.sun.jna.Platform - apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'org.jetbrains.dokka' apply plugin: 'maven' apply plugin: 'maven-publish' +apply from: 'native.gradle' group 'io.tanker' version 'dev' @@ -33,11 +32,6 @@ android { } } } - externalNativeBuild { - cmake { - path 'CMakeLists.txt' - } - } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -76,118 +70,6 @@ android { } } -class Helper { - public static def runCmd(cmd, path) { - print("${path}: ${cmd} \n") - def sout = new StringBuilder(), serr = new StringBuilder() - def proc = cmd.execute(null, path) - proc.consumeProcessOutput(sout, serr) - proc.waitFor() - println "$sout $serr" - if (proc.exitValue() != 0) { - throw new Exception("out> $sout err> $serr" + "\nCommand: ${cmd}") - } - } - - // This creates a .jar with our .so inside, so we can put it in the classpath for tests - public static def createNativeLibJar(File libPath, String jarName) { - def platformPrefix = Platform.getNativeLibraryResourcePrefix() - def relPrefixedPath = platformPrefix + '/' + libPath.name - def prefixedLibPath = new File(libPath.parent + '/' + relPrefixedPath) - prefixedLibPath.parentFile.mkdirs() - prefixedLibPath.bytes = libPath.bytes // This is just a file copy in Groovy - runCmd("jar cf ${jarName} -C ${libPath.parent} $relPrefixedPath", libPath.parentFile) - } -} - -class BuildNativeFromSourcesTask extends DefaultTask { - String projectPath - String buildType - - static def runConan(buildPath, installPath, sourcePath, buildType, arch, profile) { - buildPath.mkdirs() - installPath.mkdirs() - Helper.runCmd("conan install $sourcePath --profile $profile --build missing --options shared=True --settings build_type=$buildType --settings arch=$arch --install-folder $buildPath", sourcePath) - Helper.runCmd("conan build --configure --build --install $sourcePath --package-folder $installPath --build-folder $buildPath", sourcePath) - } - - @TaskAction - void compile() { - def androidBuildType = buildType.toLowerCase() - def buildPathBase = projectPath+"/../../sdk-native/build/android/$buildType" - def installPathBase = projectPath+"/src/$androidBuildType/jniLibs/" - def sourcePath = new File(projectPath+"/../../sdk-native") - - // Run each known android arch (except x86, known bug) - def conanAndroidArchs = ["x86_64": "x86_64", "x86": "x86", "armeabi-v7a":"armv7", "arm64-v8a": "armv8"] - conanAndroidArchs.each{ k, v -> - def buildPath = new File("$buildPathBase/$k") - def installPath = new File("$installPathBase/$k") - runConan(buildPath, installPath, sourcePath, buildType, v, "android") - Helper.runCmd("cp lib/libtanker.so .", installPath) - } - - // Last run for host build (used for unit testing) - def buildPath = new File(projectPath+"/../../sdk-native/build/host/$buildType/") - def installPath = new File(projectPath+"/conan/host/") - def profile = System.getenv("CI") ? "gcc8" : "default" - runConan(buildPath, installPath, sourcePath, buildType, "x86_64", profile) - def hostLibDir = new File(installPath, "lib/libtanker.so") - Helper.createNativeLibJar(hostLibDir, 'tanker-native.jar') - } -} - -class UseDeployedNative extends DefaultTask { - String projectPath - String buildType - - static def runConan(installPath, sourcePath, buildType, arch, profile) { - installPath.mkdirs() - Helper.runCmd("conan install $sourcePath --profile $profile --build missing --settings build_type=$buildType --settings arch=$arch --install-folder $installPath", sourcePath) - } - - @TaskAction - void compile() { - def androidBuildType = buildType.toLowerCase() - def installPathBase = projectPath+"/src/$androidBuildType/jniLibs/" - def sourcePath = new File(projectPath+"/conan") - - // Run each known android arch (except x86, known bug) - def conanAndroidArchs = ["x86_64": "x86_64", "x86": "x86", "armeabi-v7a":"armv7", "arm64-v8a": "armv8"] - conanAndroidArchs.each{ k, v -> - def installPath = new File("$installPathBase/$k") - runConan(installPath, sourcePath, buildType, v, "android") - } - - // Last run for host build (used for unit testing) - def installPath = new File(projectPath+"/conan/host/lib") - def profile = System.getenv("CI") ? "gcc8" : "default" - runConan(installPath, sourcePath, buildType, "x86_64", profile) - def hostLibDir = new File(installPath, "libtanker.so") - Helper.createNativeLibJar(hostLibDir, 'tanker-native.jar') - } -} - -task buildNativeFromSourcesDebug(type: BuildNativeFromSourcesTask) { - projectPath = projectDir.absolutePath - buildType = "Debug" -} - -task buildNativeFromSourcesRelease(type: BuildNativeFromSourcesTask) { - projectPath = projectDir.absolutePath - buildType = "Release" -} - -task useDeployedNativeDebug(type: UseDeployedNative) { - projectPath = projectDir.absolutePath - buildType = "Debug" -} - -task useDeployedNativeRelease(type: UseDeployedNative) { - projectPath = projectDir.absolutePath - buildType = "Release" -} - task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs classifier = 'sources' @@ -198,27 +80,6 @@ task javaDocJar(type: Jar, dependsOn: dokka) { classifier = 'javadoc' } -dependencies { - api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" - api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1' - implementation 'com.android.support:support-compat:28.0.0' - testImplementation 'io.kotlintest:kotlintest-core:3.2.1' - testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.2.1' - api 'net.java.dev.jna:jna:4.5.1@aar' - testImplementation 'net.java.dev.jna:jna:4.5.1' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' - testImplementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7' - testImplementation 'org.slf4j:slf4j-nop:1.7.25' - testImplementation files('jna.jar') - testImplementation files('conan/host/lib/tanker-native.jar') -} - -clean { - delete "conan/build" -} - dokka { outputFormat = 'javadoc' @@ -260,3 +121,19 @@ uploadArchives { } } } + +dependencies { + api "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + api "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + api 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.1.1' + api 'net.java.dev.jna:jna:4.5.1@aar' + implementation 'com.android.support:support-compat:28.0.0' + testImplementation 'io.kotlintest:kotlintest-core:3.2.1' + testImplementation 'io.kotlintest:kotlintest-runner-junit5:3.2.1' + androidTestImplementation 'com.android.support.test:runner:1.0.2' + androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + testImplementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7' + testImplementation 'org.slf4j:slf4j-nop:1.7.25' + testImplementation files('jna.jar') + testImplementation files('conan/host/lib/tanker-native.jar') +} diff --git a/tanker-bindings/conan/conanfile.txt b/tanker-bindings/conan/conanfile.txt index 82c991d..09237cb 100644 --- a/tanker-bindings/conan/conanfile.txt +++ b/tanker-bindings/conan/conanfile.txt @@ -1,8 +1,5 @@ [requires] -tanker/1.10.0@tanker/stable +tanker/1.10.0-r4@tanker/stable [imports] lib, *tanker*.* -> . - -[options] -tanker:shared=True diff --git a/tanker-bindings/native.gradle b/tanker-bindings/native.gradle new file mode 100644 index 0000000..85217f7 --- /dev/null +++ b/tanker-bindings/native.gradle @@ -0,0 +1,188 @@ +import javax.inject.Inject +import com.sun.jna.Platform + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath 'javax.inject:javax.inject:1' + classpath 'net.java.dev.jna:jna-platform:4.5.1' + } +} + +class NativeHelper { + static def conanAndroidArchs = ["x86_64": "x86_64", "x86": "x86", "armeabi-v7a":"armv7", "arm64-v8a": "armv8"] + + static def runCmd(cmd, path) { + print("${path}: ${cmd} \n") + def proc = cmd.execute(null, path) + proc.consumeProcessOutput(System.out, System.err) + proc.waitFor() + if (proc.exitValue() != 0) + throw new Exception("Command failed: ${cmd}") + } + + static def getAndroidProfile(arch, buildType) { + return "android-$arch-${buildType.toLowerCase()}" + } + + static def conanInstall(buildPath, sourcePath, profile) { + buildPath.mkdirs() + runCmd("conan install $sourcePath " + + "--install-folder $buildPath " + + "--profile $profile " + + "--option tanker:tankerlib_shared=True " + + "--build missing ", + sourcePath + ) + } + + static def conanBuild(buildPath, installPath, sourcePath) { + installPath.mkdirs() + runCmd("conan build --configure --build " + + "--install $sourcePath " + + "--package-folder $installPath " + + "--build-folder $buildPath", + sourcePath + ) + } + + // This creates a .jar with our .so inside, so we can put it in the classpath for tests + static def createNativeLibJar(File libPath, String jarName) { + def platformPrefix = Platform.getNativeLibraryResourcePrefix() + def relPrefixedPath = platformPrefix + '/' + libPath.name + def prefixedLibPath = new File(libPath.parent + '/' + relPrefixedPath) + prefixedLibPath.parentFile.mkdirs() + prefixedLibPath.bytes = libPath.bytes // This is just a file copy in Groovy + runCmd("jar cf ${jarName} -C ${libPath.parent} $relPrefixedPath", libPath.parentFile) + } +} + +class BuildNative extends DefaultTask { + final String buildType + final String buildFor + final String projectPath + final File sourcePath + + @Inject BuildNative(String buildType, String buildFor) { + this.buildType = buildType + this.buildFor = buildFor + + this.projectPath = getProject().getProjectDir().absolutePath + this.sourcePath = new File(projectPath+"/../../sdk-native") + } + + void compileForAndroid() { + def androidBuildType = buildType.toLowerCase() + def buildPathBase = projectPath+"/../../sdk-native/build/android/$buildType" + def installPathBase = projectPath+"/src/$androidBuildType/jniLibs/" + + // Run each known android arch + NativeHelper.conanAndroidArchs.each { k, v -> + def buildPath = new File("$buildPathBase/$k") + def installPath = new File("$installPathBase/$k") + + def profileName = NativeHelper.getAndroidProfile(v, buildType) + NativeHelper.conanInstall(buildPath, sourcePath, profileName) + NativeHelper.conanBuild(buildPath, installPath, sourcePath) + NativeHelper.runCmd("cp lib/libtanker.so .", installPath) + } + } + + void compileForHost() { + // Last run for host build (used for unit testing) + def buildPath = new File(projectPath + "/../../sdk-native/build/host/$buildType/") + def installPath = new File(projectPath + "/conan/host/") + def profile = System.getenv("CI") ? "gcc8-release" : "default" + + NativeHelper.conanInstall(buildPath, sourcePath, profile) + NativeHelper.conanBuild(buildPath, installPath, sourcePath) + + def hostLibDir = new File(installPath, "lib/libtanker.so") + NativeHelper.createNativeLibJar(hostLibDir, 'tanker-native.jar') + } + + @TaskAction + void compile() { + if (buildFor == 'android' || buildFor == 'all') + compileForAndroid() + if (buildFor == 'host' || buildFor == 'all') + compileForHost() + } +} + +class UseDeployedNative extends DefaultTask { + String buildType + + @Inject UseDeployedNative(String buildType) { + this.buildType = buildType + } + + @TaskAction + void compile() { + def projectPath = getProject().getProjectDir().absolutePath + def installPathBase = projectPath+"/src/${buildType.toLowerCase()}/jniLibs/" + def sourcePath = new File(projectPath+"/conan") + + NativeHelper.conanAndroidArchs.each{ k, v -> + def installPath = new File("$installPathBase/$k") + def profileName = NativeHelper.getAndroidProfile(v, buildType) + NativeHelper.conanInstall(installPath, sourcePath, profileName) + } + + def installPath = new File(projectPath + "/conan/host/lib/") + def profile = System.getenv("CI") ? "gcc8-release" : "default" + NativeHelper.conanInstall(installPath, sourcePath, profile) + NativeHelper.createNativeLibJar(new File(installPath, 'libtanker.so'), 'tanker-native.jar') + } +} + +// If we didn't already fetch or build Native libs, we need to build them now +class RequireNativeLibs extends DefaultTask { + @Inject RequireNativeLibs(String buildType, String buildFor) { + boolean hasNativeLibs = true + String projectPath = getProject().getProjectDir().absolutePath + if (buildFor == 'android') { + String installPathBase = projectPath + "/src/${buildType.toLowerCase()}/jniLibs" + + NativeHelper.conanAndroidArchs.each { k, v -> + File lib = new File("$installPathBase/$k/libtanker.so") + if (!lib.exists()) { + doFirst { getLogger().warn("$lib not found, triggering build") } + hasNativeLibs = false + } + } + } else { + File expectedPath = new File(projectPath + "/conan/host/lib/libtanker.so") + if (!expectedPath.exists()) { + doFirst { getLogger().warn("$expectedPath not found, triggering build") } + hasNativeLibs = false + } + } + if (!hasNativeLibs) + finalizedBy(getProject().getTasks().create("require${buildFor}NativeBuild${buildType}", BuildNative, buildType, buildFor)) + } +} + +task buildNativeDebug(type: BuildNative, constructorArgs: ['Debug', 'all']) +task buildNativeRelease(type: BuildNative, constructorArgs: ['Release', 'all']) +task useDeployedNativeDebug(type: UseDeployedNative, constructorArgs: ['Debug']) +task useDeployedNativeRelease(type: UseDeployedNative, constructorArgs: ['Release']) + +// Setup regular tasks to depend on Native +tasks.whenTaskAdded { task -> + if (task.name == 'compileDebugUnitTestKotlin') { + task.dependsOn tasks.create('requireHostNativeDebug', RequireNativeLibs, 'Debug', 'host') + } else if (task.name == 'compileReleaseUnitTestKotlin') { + task.dependsOn tasks.create('requireHostNativeRelease', RequireNativeLibs, 'Release', 'host') + } else if (task.name == 'bundleDebugAar') { + task.dependsOn tasks.create('requireAndroidNativeDebug', RequireNativeLibs, 'Debug', 'android') + } else if (task.name == 'bundleReleaseAar') { + task.dependsOn tasks.create('requireAndroidNativeRelease', RequireNativeLibs, 'Release', 'android') + } +} + +clean { + delete "conan/build" +}