From 8d284cf331b989df4ebc9dc413136f34814b573e Mon Sep 17 00:00:00 2001 From: Kaushal Kumar Singh <56905738+kaushalbx@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:38:05 +0530 Subject: [PATCH] Use Kotlin instead of Groovy for Android build configuration (#2902) --- .github/workflows/android-ci.yml | 2 +- platform/android/MapLibreAndroid/build.gradle | 186 ----------------- .../android/MapLibreAndroid/build.gradle.kts | 196 ++++++++++++++++++ .../android/MapLibreAndroidLint/build.gradle | 23 -- .../MapLibreAndroidLint/build.gradle.kts | 22 ++ .../MapLibreAndroidTestApp/build.gradle | 129 ------------ .../MapLibreAndroidTestApp/build.gradle.kts | 122 +++++++++++ platform/android/build.gradle | 46 ---- platform/android/build.gradle.kts | 21 ++ platform/android/buildSrc/build.gradle.kts | 17 ++ platform/android/buildSrc/settings.gradle.kts | 9 + .../kotlin/DownloadVulkanValidationPlugin.kt | 20 ++ .../src/main/kotlin/NativeBuildPlugin.kt | 107 ++++++++++ .../buildSrc/src/main/kotlin/Versions.kt | 4 + .../maplibre.android-nitpick.gradle.kts | 18 ++ .../maplibre.artifact-settings.gradle.kts | 17 ++ .../kotlin/maplibre.dependencies.gradle.kts | 4 + ...ibre.download-vulkan-validation.gradle.kts | 67 ++++++ .../maplibre.gradle-checkstyle.gradle.kts | 32 +++ .../kotlin/maplibre.gradle-config.gradle.kts | 21 ++ ...libre.gradle-dependencies-graph.gradle.kts | 17 ++ .../kotlin/maplibre.gradle-lint.gradle.kts | 19 ++ .../kotlin/maplibre.gradle-make.gradle.kts | 14 ++ .../kotlin/maplibre.gradle-publish.gradle.kts | 99 +++++++++ .../kotlin/maplibre.jacoco-report.gradle.kts | 35 ++++ .../kotlin/maplibre.publish-root.gradle.kts | 6 + .../android/gradle/android-nitpick.gradle | 17 -- .../android/gradle/artifact-settings.gradle | 13 -- platform/android/gradle/dependencies.gradle | 6 - .../gradle/download-vulkan-validation.gradle | 51 ----- .../android/gradle/gradle-checkstyle.gradle | 29 --- platform/android/gradle/gradle-config.gradle | 23 -- .../gradle/gradle-dependencies-graph.gradle | 29 --- platform/android/gradle/gradle-lint.gradle | 22 -- platform/android/gradle/gradle-make.gradle | 18 -- platform/android/gradle/gradle-publish.gradle | 88 -------- platform/android/gradle/jacoco-report.gradle | 33 --- platform/android/gradle/libs.versions.toml | 4 +- platform/android/gradle/native-build.gradle | 75 ------- platform/android/gradle/publish-root.gradle | 6 - platform/android/settings.gradle | 17 -- platform/android/settings.gradle.kts | 39 ++++ 42 files changed, 910 insertions(+), 813 deletions(-) delete mode 100644 platform/android/MapLibreAndroid/build.gradle create mode 100644 platform/android/MapLibreAndroid/build.gradle.kts delete mode 100644 platform/android/MapLibreAndroidLint/build.gradle create mode 100644 platform/android/MapLibreAndroidLint/build.gradle.kts delete mode 100644 platform/android/MapLibreAndroidTestApp/build.gradle create mode 100644 platform/android/MapLibreAndroidTestApp/build.gradle.kts delete mode 100644 platform/android/build.gradle create mode 100644 platform/android/build.gradle.kts create mode 100644 platform/android/buildSrc/build.gradle.kts create mode 100644 platform/android/buildSrc/settings.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt create mode 100644 platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt create mode 100644 platform/android/buildSrc/src/main/kotlin/Versions.kt create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.download-vulkan-validation.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-checkstyle.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-config.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-dependencies-graph.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-lint.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-make.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.jacoco-report.gradle.kts create mode 100644 platform/android/buildSrc/src/main/kotlin/maplibre.publish-root.gradle.kts delete mode 100644 platform/android/gradle/android-nitpick.gradle delete mode 100644 platform/android/gradle/artifact-settings.gradle delete mode 100644 platform/android/gradle/dependencies.gradle delete mode 100644 platform/android/gradle/download-vulkan-validation.gradle delete mode 100644 platform/android/gradle/gradle-checkstyle.gradle delete mode 100644 platform/android/gradle/gradle-config.gradle delete mode 100644 platform/android/gradle/gradle-dependencies-graph.gradle delete mode 100644 platform/android/gradle/gradle-lint.gradle delete mode 100644 platform/android/gradle/gradle-make.gradle delete mode 100644 platform/android/gradle/gradle-publish.gradle delete mode 100644 platform/android/gradle/jacoco-report.gradle delete mode 100644 platform/android/gradle/native-build.gradle delete mode 100644 platform/android/gradle/publish-root.gradle delete mode 100644 platform/android/settings.gradle create mode 100644 platform/android/settings.gradle.kts diff --git a/.github/workflows/android-ci.yml b/.github/workflows/android-ci.yml index 47d23a34d..f17c7bba4 100644 --- a/.github/workflows/android-ci.yml +++ b/.github/workflows/android-ci.yml @@ -119,7 +119,7 @@ jobs: cache-name: gradle-v1 with: path: ~/.gradle - key: ${{ env.cache-name }}-${{ hashFiles('platform/android/gradle/dependencies.gradle') }}-${{ hashFiles('platform/android/build.gradle') }}-${{ hashFiles('platform/android/local.properties') }}-${{ hashFiles('platform/android/gradle/wrapper/gradle-wrapper.properties') }} + key: ${{ env.cache-name }}-${{ hashFiles('platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts') }}-${{ hashFiles('platform/android/build.gradle.kts') }}-${{ hashFiles('platform/android/local.properties') }}-${{ hashFiles('platform/android/gradle/wrapper/gradle-wrapper.properties') }} restore-keys: | - ${{ env.cache-name }} diff --git a/platform/android/MapLibreAndroid/build.gradle b/platform/android/MapLibreAndroid/build.gradle deleted file mode 100644 index 1966bcee0..000000000 --- a/platform/android/MapLibreAndroid/build.gradle +++ /dev/null @@ -1,186 +0,0 @@ -import org.jetbrains.dokka.gradle.DokkaTask - -plugins { - alias libs.plugins.kotlinter - alias libs.plugins.dokka -} - -apply plugin: 'com.android.library' -apply plugin: "com.jaredsburrows.license" -apply plugin: 'kotlin-android' -apply from: "${rootDir}/gradle/native-build.gradle" - -dependencies { - lintChecks project(":MapLibreAndroidLint") - api libs.maplibreJavaGeoJSON - api libs.maplibreGestures - - implementation libs.maplibreJavaTurf - implementation libs.supportAnnotations - implementation libs.supportFragmentV4 - implementation libs.okhttp3 - implementation libs.timber - implementation libs.interpolator - - testImplementation libs.junit - testImplementation libs.mockito - testImplementation libs.mockk - testImplementation libs.robolectric - testImplementation libs.commonsIO - testImplementation libs.assertjcore - - androidTestImplementation libs.testRunner - androidTestImplementation libs.testRules -} - -tasks.withType(DokkaTask.class) { - moduleName.set("MapLibre Native Android") - - dokkaSourceSets { - configureEach { - includes.from("Module.md") - } - } -} - -android { - defaultConfig { - compileSdk 34 - minSdkVersion 21 - targetSdkVersion 33 - buildConfigField "String", "GIT_REVISION_SHORT", String.format("\"%s\"", getGitRevision()) - buildConfigField "String", "GIT_REVISION", String.format("\"%s\"", getGitRevision(false)) - buildConfigField "String", "MAPLIBRE_VERSION_STRING", String.format("\"MapLibre Native/%s\"", project.VERSION_NAME) - consumerProguardFiles 'proguard-rules.pro' - - externalNativeBuild { - cmake { - arguments "-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF" - } - } - } - - flavorDimensions += "renderer" - productFlavors { - create("legacy") { - dimension = "renderer" - externalNativeBuild { - cmake { - arguments "-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF" - } - } - } - create("drawable") { - dimension = "renderer" - externalNativeBuild { - cmake { - arguments "-DMLN_LEGACY_RENDERER=OFF", "-DMLN_DRAWABLE_RENDERER=ON" - } - } - } - create("vulkan") { - dimension = "renderer" - externalNativeBuild { - cmake { - arguments "-DMLN_LEGACY_RENDERER=OFF", "-DMLN_DRAWABLE_RENDERER=ON" - arguments "-DMLN_WITH_OPENGL=OFF", "-DMLN_WITH_VULKAN=ON" - } - } - } - } - - sourceSets { - legacy { - java.srcDirs += ['src/opengl/java/'] - } - drawable { - java.srcDirs += ['src/opengl/java/'] - } - } - - // build native libraries - List nativeTargets = ["maplibre"] - if (project.hasProperty("mapbox.with_test")) { - nativeTargets.add("mbgl-test") - } - if (project.hasProperty("mapbox.with_benchmark")) { - nativeTargets.add("mbgl-benchmark") - } - nativeBuild(nativeTargets) - - // avoid naming conflicts, force usage of prefix - resourcePrefix 'maplibre_' - - sourceSets { - // limit amount of exposed library resources - main.res.srcDirs += 'src/main/res-public' - } - - - testOptions { - unitTests { - returnDefaultValues true - - // Roboelectric 4.0 required config - // http://robolectric.org/migrating/#migrating-to-40 - includeAndroidResources = true - } - } - - buildTypes { - debug { - testCoverageEnabled false - jniDebuggable true - debuggable true - } - } - namespace 'org.maplibre.android' - lint { - checkAllWarnings true - disable 'MissingTranslation', 'TypographyQuotes', 'ObsoleteLintCustomCheck', 'MissingPermission', 'WrongThreadInterprocedural' - warningsAsErrors false - } - - buildFeatures { - buildConfig true - } - - compileOptions { - sourceCompatibility = 11 - targetCompatibility = 11 - } - - kotlinOptions { - jvmTarget = "11" - } -} - -licenseReport { - generateHtmlReport = false - generateJsonReport = true - copyHtmlReportToAssets = false - copyJsonReportToAssets = false -} - -def static getGitRevision(shortRev = true) { - def cmd = shortRev ? "git rev-parse --short HEAD" : "git rev-parse HEAD" - def proc = cmd.execute() - def ref = proc.text.trim() - return ref -} - -configurations { - all*.exclude group: 'commons-logging', module: 'commons-logging' - all*.exclude group: 'commons-collections', module: 'commons-collections' -} - -// Download validation layers from -// https://github.com/KhronosGroup/Vulkan-ValidationLayers -apply from: "${rootDir}/gradle/download-vulkan-validation.gradle" - -apply from: "${rootDir}/gradle/gradle-checkstyle.gradle" -apply from: "${rootDir}/gradle/gradle-dependencies-graph.gradle" -apply from: "${rootDir}/gradle/android-nitpick.gradle" -apply from: "${rootDir}/gradle/gradle-publish.gradle" -// intentionally disabled -// apply from: "${rootDir}/gradle/jacoco-report.gradle" diff --git a/platform/android/MapLibreAndroid/build.gradle.kts b/platform/android/MapLibreAndroid/build.gradle.kts new file mode 100644 index 000000000..c0b5fe503 --- /dev/null +++ b/platform/android/MapLibreAndroid/build.gradle.kts @@ -0,0 +1,196 @@ +import org.jetbrains.dokka.gradle.DokkaTask + +plugins { + alias(libs.plugins.kotlinter) + alias(libs.plugins.dokka) + id("com.android.library") + id("com.jaredsburrows.license") + kotlin("android") + id("maplibre.download-vulkan-validation") + id("maplibre.gradle-checkstyle") + id("maplibre.gradle-dependencies-graph") + id("maplibre.android-nitpick") + id("maplibre.gradle-publish") + id("maplibre.artifact-settings") +} + +dependencies { + lintChecks(project(":MapLibreAndroidLint")) + api(libs.maplibreJavaGeoJSON) + api(libs.maplibreGestures) + + implementation(libs.maplibreJavaTurf) + implementation(libs.supportAnnotations) + implementation(libs.supportFragmentV4) + implementation(libs.okhttp3) + implementation(libs.timber) + implementation(libs.interpolator) + + testImplementation(libs.junit) + testImplementation(libs.mockito) + testImplementation(libs.mockk) + testImplementation(libs.robolectric) + testImplementation(libs.commonsIO) + testImplementation(libs.assertjcore) + + androidTestImplementation(libs.testRunner) + androidTestImplementation(libs.testRules) +} + +tasks.withType { + moduleName.set("MapLibre Native Android") + + dokkaSourceSets { + configureEach { + includes.from("Module.md") + } + } +} + +android { + defaultConfig { + compileSdk = 34 + minSdk = 21 + targetSdk = 33 + buildConfigField("String", "GIT_REVISION_SHORT", "\"${getGitRevision()}\"") + buildConfigField("String", "GIT_REVISION", "\"${getGitRevision(false)}\"") + buildConfigField( + "String", + "MAPLIBRE_VERSION_STRING", + "\"MapLibre Native/${project.property("VERSION_NAME")}\"" + ) + consumerProguardFiles("proguard-rules.pro") + + externalNativeBuild { + cmake { + arguments("-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF") + } + } + } + + flavorDimensions += "renderer" + productFlavors { + create("legacy") { + dimension = "renderer" + externalNativeBuild { + cmake { + arguments("-DMLN_LEGACY_RENDERER=ON", "-DMLN_DRAWABLE_RENDERER=OFF") + } + } + } + create("drawable") { + dimension = "renderer" + externalNativeBuild { + cmake { + arguments("-DMLN_LEGACY_RENDERER=OFF", "-DMLN_DRAWABLE_RENDERER=ON") + } + } + } + create("vulkan") { + dimension = "renderer" + externalNativeBuild { + cmake { + arguments("-DMLN_LEGACY_RENDERER=OFF", "-DMLN_DRAWABLE_RENDERER=ON") + arguments("-DMLN_WITH_OPENGL=OFF", "-DMLN_WITH_VULKAN=ON") + } + } + } + } + + sourceSets { + getByName("legacy") { + java.srcDirs("src/opengl/java/") + } + getByName("drawable") { + java.srcDirs("src/opengl/java/") + } + } + + // Build native libraries + val nativeTargets = mutableListOf("maplibre") + if (project.hasProperty("mapbox.with_test")) { + nativeTargets.add("mbgl-test") + } + if (project.hasProperty("mapbox.with_benchmark")) { + nativeTargets.add("mbgl-benchmark") + } + nativeBuild(nativeTargets) + + // Avoid naming conflicts, force usage of prefix + resourcePrefix("maplibre_") + + sourceSets { + getByName("main") { + res.srcDirs("src/main/res-public") + } + } + + testOptions { + unitTests { + isReturnDefaultValues = true + + // Robolectric 4.0 required config + // http://robolectric.org/migrating/#migrating-to-40 + isIncludeAndroidResources = true + } + } + + buildTypes { + debug { + isTestCoverageEnabled = false + isJniDebuggable = true + } + } + + namespace = "org.maplibre.android" + + lint { + checkAllWarnings = true + disable += listOf( + "MissingTranslation", + "TypographyQuotes", + "ObsoleteLintCustomCheck", + "MissingPermission", + "WrongThreadInterprocedural" + ) + warningsAsErrors = false + } + + buildFeatures { + buildConfig = true + } + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + + kotlinOptions { + jvmTarget = "11" + } +} + +licenseReport { + generateHtmlReport = false + generateJsonReport = true + copyHtmlReportToAssets = false + copyJsonReportToAssets = false +} + +fun getGitRevision(shortRev: Boolean = true): String { + val cmd = if (shortRev) "git rev-parse --short HEAD" else "git rev-parse HEAD" + val proc = Runtime.getRuntime().exec(cmd) + return proc.inputStream.bufferedReader().readText().trim() +} + +configurations { + getByName("implementation") { + exclude(group = "commons-logging", module = "commons-logging") + exclude(group = "commons-collections", module = "commons-collections") + } +} + +apply() + +// intentionally disabled +// apply(plugin = "maplibre.jacoco-report") \ No newline at end of file diff --git a/platform/android/MapLibreAndroidLint/build.gradle b/platform/android/MapLibreAndroidLint/build.gradle deleted file mode 100644 index dbddbcd5f..000000000 --- a/platform/android/MapLibreAndroidLint/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -plugins { - alias libs.plugins.kotlinter -} - -apply plugin: 'java-library' -apply plugin: 'kotlin' - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar']) - - compileOnly libs.lint - compileOnly libs.lintApi - compileOnly libs.lintChecks - compileOnly libs.supportAnnotations - - testImplementation libs.junit - testImplementation libs.robolectric - testImplementation libs.lintTests -} - -kotlin { - jvmToolchain(17) -} \ No newline at end of file diff --git a/platform/android/MapLibreAndroidLint/build.gradle.kts b/platform/android/MapLibreAndroidLint/build.gradle.kts new file mode 100644 index 000000000..396afd9cf --- /dev/null +++ b/platform/android/MapLibreAndroidLint/build.gradle.kts @@ -0,0 +1,22 @@ +plugins { + alias(libs.plugins.kotlinter) + `java-library` + kotlin("jvm") +} + +dependencies { + implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.jar")))) + + compileOnly(libs.lint) + compileOnly(libs.lintApi) + compileOnly(libs.lintChecks) + compileOnly(libs.supportAnnotations) + + testImplementation(libs.junit) + testImplementation(libs.robolectric) + testImplementation(libs.lintTests) +} + +kotlin { + jvmToolchain(17) +} diff --git a/platform/android/MapLibreAndroidTestApp/build.gradle b/platform/android/MapLibreAndroidTestApp/build.gradle deleted file mode 100644 index ab7596f8a..000000000 --- a/platform/android/MapLibreAndroidTestApp/build.gradle +++ /dev/null @@ -1,129 +0,0 @@ -plugins { - alias libs.plugins.kotlinter - id 'com.android.application' - id 'org.jetbrains.kotlin.android' - alias libs.plugins.kotlinPluginSerialization -} - -apply from: "${rootDir}/gradle/native-build.gradle" - -def obtainTestBuildType() { - def result = "debug"; - - if (project.hasProperty("testBuildType")) { - result = project.getProperties().get("testBuildType") - } - - result -} - -android { - defaultConfig { - applicationId "org.maplibre.android.testapp" - compileSdk 34 - minSdkVersion 21 - targetSdkVersion 33 - versionCode 14 - versionName "6.0.1" - testInstrumentationRunner "org.maplibre.android.InstrumentationRunner" - multiDexEnabled = true - } - - nativeBuild(["example-custom-layer"]) - packagingOptions { - resources { - excludes += ['META-INF/LICENSE.txt', 'META-INF/NOTICE.txt', 'LICENSE.txt'] - } - } - - - buildTypes { - debug { - jniDebuggable true - debuggable true - testCoverageEnabled true - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - release { - minifyEnabled true - shrinkResources true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - testProguardFiles 'test-proguard-rules.pro' - signingConfig signingConfigs.debug - } - } - - testBuildType obtainTestBuildType() - - flavorDimensions += "renderer" - productFlavors { - create("legacy") { - dimension = "renderer" - } - create("drawable") { - dimension = "renderer" - } - create("vulkan") { - dimension = "renderer" - } - } - - buildFeatures { - viewBinding = true - buildConfig true - } - - namespace 'org.maplibre.android.testapp' - - lint { - abortOnError false - baseline file('lint-baseline-local.xml') - checkAllWarnings true - disable 'MissingTranslation', 'GoogleAppIndexingWarning', 'UnpackedNativeCode', 'IconDipSize', 'TypographyQuotes' - warningsAsErrors true - } -} - -kotlin { - jvmToolchain(17) -} - -dependencies { - implementation project(':MapLibreAndroid') - implementation libs.maplibreJavaTurf - - implementation libs.supportRecyclerView - implementation libs.supportDesign - implementation libs.supportConstraintLayout - implementation libs.kotlinxSerializationJson - - implementation libs.multidex - - implementation libs.timber - - implementation libs.okhttp3 - - implementation libs.kotlinxCoroutinesCore - implementation libs.kotlinxCoroutinesAndroid - - debugImplementation libs.leakCanary - - androidTestImplementation libs.supportAnnotations - androidTestImplementation libs.testRunner - androidTestImplementation libs.testRules - androidTestImplementation libs.testEspressoCore - androidTestImplementation libs.testEspressoIntents - androidTestImplementation libs.testEspressoContrib - androidTestImplementation libs.testUiAutomator - androidTestImplementation libs.appCenter - androidTestImplementation libs.androidxTestExtJUnit - androidTestImplementation libs.androidxTestCoreKtx - androidTestImplementation libs.kotlinxCoroutinesTest -} - -apply from: "${rootDir}/gradle/gradle-make.gradle" -apply from: "${rootDir}/gradle/gradle-config.gradle" -apply from: "${rootDir}/gradle/gradle-checkstyle.gradle" -apply from: "${rootDir}/gradle/gradle-lint.gradle" \ No newline at end of file diff --git a/platform/android/MapLibreAndroidTestApp/build.gradle.kts b/platform/android/MapLibreAndroidTestApp/build.gradle.kts new file mode 100644 index 000000000..5de8de1b8 --- /dev/null +++ b/platform/android/MapLibreAndroidTestApp/build.gradle.kts @@ -0,0 +1,122 @@ +plugins { + alias(libs.plugins.kotlinter) + id("com.android.application") + alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.kotlinPluginSerialization) + id("maplibre.gradle-make") + id("maplibre.gradle-config") + id("maplibre.gradle-checkstyle") + id("maplibre.gradle-lint") +} + + +fun obtainTestBuildType(): String { + return if (project.hasProperty("testBuildType")) { + project.properties["testBuildType"] as String + } else { + "debug" + } +} + +android { + compileSdk = 34 + + defaultConfig { + applicationId = "org.maplibre.android.testapp" + minSdk = 21 + targetSdk = 33 + versionCode = 14 + versionName = "6.0.1" + testInstrumentationRunner = "org.maplibre.android.InstrumentationRunner" + multiDexEnabled = true + } + + nativeBuild(listOf("example-custom-layer")) + + packaging { + resources.excludes += listOf("META-INF/LICENSE.txt", "META-INF/NOTICE.txt", "LICENSE.txt") + } + + buildTypes { + getByName("debug") { + isJniDebuggable = true + isDebuggable = true + isTestCoverageEnabled = true + isMinifyEnabled = false + isShrinkResources = false + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + } + getByName("release") { + isMinifyEnabled = true + isShrinkResources = true + proguardFiles(getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro") + testProguardFiles("test-proguard-rules.pro") + signingConfig = signingConfigs.getByName("debug") + } + } + + testBuildType = obtainTestBuildType() + + flavorDimensions += "renderer" + + productFlavors { + create("legacy") { + dimension = "renderer" + } + create("drawable") { + dimension = "renderer" + } + create("vulkan") { + dimension = "renderer" + } + } + + buildFeatures { + viewBinding = true + buildConfig = true + } + + namespace = "org.maplibre.android.testapp" + + lint { + abortOnError = false + baseline = file("lint-baseline-local.xml") + checkAllWarnings = true + disable += listOf("MissingTranslation", "GoogleAppIndexingWarning", "UnpackedNativeCode", "IconDipSize", "TypographyQuotes") + warningsAsErrors = true + } +} + +kotlin { + jvmToolchain(17) +} + +dependencies { + implementation(project(":MapLibreAndroid")) + implementation(libs.maplibreJavaTurf) + + implementation(libs.supportRecyclerView) + implementation(libs.supportDesign) + implementation(libs.supportConstraintLayout) + implementation(libs.kotlinxSerializationJson) + + implementation(libs.multidex) + implementation(libs.timber) + implementation(libs.okhttp3) + implementation(libs.kotlinxCoroutinesCore) + implementation(libs.kotlinxCoroutinesAndroid) + + debugImplementation(libs.leakCanary) + + androidTestImplementation(libs.supportAnnotations) + androidTestImplementation(libs.testRunner) + androidTestImplementation(libs.testRules) + androidTestImplementation(libs.testEspressoCore) + androidTestImplementation(libs.testEspressoIntents) + androidTestImplementation(libs.testEspressoContrib) + androidTestImplementation(libs.testUiAutomator) + androidTestImplementation(libs.appCenter) + androidTestImplementation(libs.androidxTestExtJUnit) + androidTestImplementation(libs.androidxTestCoreKtx) + androidTestImplementation(libs.kotlinxCoroutinesTest) +} diff --git a/platform/android/build.gradle b/platform/android/build.gradle deleted file mode 100644 index 1ff30b7a3..000000000 --- a/platform/android/build.gradle +++ /dev/null @@ -1,46 +0,0 @@ -buildscript { - apply from: "${rootDir}/gradle/dependencies.gradle" - - repositories { - google() - maven { url "https://plugins.gradle.org/m2/" } - mavenCentral() - } - dependencies { - classpath libs.androidGradlePlugin - classpath libs.licensesPlugin - classpath libs.gradleNexus - classpath libs.kotlinPlugin - } -} - -plugins { - alias libs.plugins.nexusPublishPlugin - alias libs.plugins.kotlinter apply false - alias libs.plugins.kotlinAndroid apply false -} - -allprojects { - repositories { - mavenCentral() - google() - } -} - -subprojects { - apply from: "${rootDir}/gradle/dependencies.gradle" -} - -apply from: "${rootDir}/gradle/publish-root.gradle" -// Set up Sonatype repository -nexusPublishing { - repositories { - sonatype { - stagingProfileId = sonatypeStagingProfileId - username = ossrhUsername - password = ossrhPassword - nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) - snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) - } - } -} \ No newline at end of file diff --git a/platform/android/build.gradle.kts b/platform/android/build.gradle.kts new file mode 100644 index 000000000..c830ffbd0 --- /dev/null +++ b/platform/android/build.gradle.kts @@ -0,0 +1,21 @@ +plugins { + alias(libs.plugins.nexusPublishPlugin) + alias(libs.plugins.kotlinter) apply false + alias(libs.plugins.kotlinAndroid) apply false + id("com.jaredsburrows.license") version "0.9.8" apply false + id("maplibre.dependencies") + id("maplibre.publish-root") +} + + +nexusPublishing { + repositories { + sonatype { + stagingProfileId.set(extra["sonatypeStagingProfileId"] as String?) + username.set(extra["ossrhUsername"] as String?) + password.set(extra["ossrhPassword"] as String?) + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} diff --git a/platform/android/buildSrc/build.gradle.kts b/platform/android/buildSrc/build.gradle.kts new file mode 100644 index 000000000..c2b851aba --- /dev/null +++ b/platform/android/buildSrc/build.gradle.kts @@ -0,0 +1,17 @@ +plugins { + `kotlin-dsl` +} + +repositories { + gradlePluginPortal() + google() + mavenCentral() + maven("https://plugins.gradle.org/m2/") +} + +dependencies { + implementation("com.vanniktech:gradle-dependency-graph-generator-plugin:0.3.0") + implementation("com.android.tools.build:gradle:8.6.0") + implementation("com.android.application:com.android.application.gradle.plugin:8.6.0") + implementation("commons-collections:commons-collections:3.2.2") +} diff --git a/platform/android/buildSrc/settings.gradle.kts b/platform/android/buildSrc/settings.gradle.kts new file mode 100644 index 000000000..c0beff791 --- /dev/null +++ b/platform/android/buildSrc/settings.gradle.kts @@ -0,0 +1,9 @@ +rootProject.name = "maplibre-conventions" + +dependencyResolutionManagement { + versionCatalogs { + create("libs") { + from(files("../gradle/libs.versions.toml")) + } + } +} \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt b/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt new file mode 100644 index 000000000..afd8483f5 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/DownloadVulkanValidationPlugin.kt @@ -0,0 +1,20 @@ +import com.android.build.gradle.BaseExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + + +open class DownloadVulkanValidationPlugin : Plugin { + override fun apply(project: Project) { + project.configureVulkanJniLibs() + } +} + +internal fun Project.configureVulkanJniLibs() = this.extensions.getByType().run { + sourceSets { + getByName("vulkan") { + jniLibs.srcDir(tasks.named("unzip").get().outputs.files.asFileTree) + } + } + +} \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt b/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt new file mode 100644 index 000000000..52fe2c9d2 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/NativeBuildPlugin.kt @@ -0,0 +1,107 @@ +import com.android.build.gradle.BaseExtension +import org.gradle.api.Plugin +import org.gradle.api.Project +import org.gradle.kotlin.dsl.getByType + +open class NativeBuildPlugin : Plugin { + override fun apply(project: Project) { + val extension = project.extensions.create("nativeBuild", NativeBuildExtension::class.java) + project.afterEvaluate { + val targets = extension.nativeTargets + project.nativeBuild(nativeTargets = targets) + } + } +} + +open class NativeBuildExtension { + var nativeTargets: List = listOf() +} + +fun Project.nativeBuild(nativeTargets: List) = + this.extensions.getByType().run { + + // We sometimes want to invoke Gradle without building a native dependency, e.g. when we just want + // to invoke the Java tests. When we explicitly specify an ABI of 'none', no native dependencies are + // added. When another ABI is specified explicitly, we're just going to build that ABI. In all other + // cases, all ABIs are built. + // + // When invoking from the command line or to override the device default, set `-Pmaplibre.abis=...` to + // only build the desired architectures. + // + // When building from Android Studio, gradle.properties sets `android.buildOnlyTargetAbi=true` so that + // only the architecture for the device you're running on gets built. + + + var abi = "all" + if (!project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty("maplibre.abis")) { + abi = project.property("maplibre.abis") as String + } + + if (abi != "none") { + externalNativeBuild { + cmake { + path = file("../MapLibreAndroid/src/cpp/CMakeLists.txt") + version = Versions.cmakeVersion + } + } + } + + // Determine the C++ STL being used. + var stl = "c++_static" + if (project.hasProperty("mapbox.stl")) { + stl = project.property("mapbox.stl") as String + } + + defaultConfig { + if (abi != "none") { + externalNativeBuild { + cmake { + arguments.addAll( + listOf( + "-DANDROID_TOOLCHAIN=clang", + "-DANDROID_STL=$stl", + "-DANDROID_CPP_FEATURES=exceptions", + "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + ) + ) + + // Enable ccache if available. + val ccachePaths = listOf("/usr/bin/ccache", "/usr/local/bin/ccache") + for (path in ccachePaths) { + if (file(path).exists()) { + arguments.add("-DANDROID_CCACHE=$path") + } + } + + cFlags.add("-Qunused-arguments") + cppFlags.add("-Qunused-arguments") + + for (target in nativeTargets) { + targets(target) + } + + if (abi != "all") { + abiFilters.addAll(abi.split(" ")) + } else { + if (project.hasProperty("android.injected.invoked.from.ide") && project.hasProperty( + "android.injected.build.abi" + ) + ) { + abi = project.property("android.injected.build.abi") as String + abiFilters.add(abi.split(",").first()) + } else { + abiFilters.addAll( + listOf( + "armeabi-v7a", + "x86", + "arm64-v8a", + "x86_64" + ) + ) + } + } + } + } + } + } + } \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/Versions.kt b/platform/android/buildSrc/src/main/kotlin/Versions.kt new file mode 100644 index 000000000..16fd70fae --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/Versions.kt @@ -0,0 +1,4 @@ +object Versions { + const val ndkVersion ="27.0.12077973" + const val cmakeVersion = "3.18.1+" +} \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts new file mode 100644 index 000000000..b1a8ca841 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.android-nitpick.gradle.kts @@ -0,0 +1,18 @@ +plugins { + id("maplibre.dependencies") +} + +tasks.register("androidNitpick") { + doLast { + println("Running android nitpick script") + verifyLicenseGeneration() + } +} + +fun verifyLicenseGeneration() { + println("Verify license generation with git diff...") + exec { + workingDir(rootDir) + commandLine("python3", "scripts/validate-license.py") + } +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts new file mode 100644 index 000000000..917845263 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.artifact-settings.gradle.kts @@ -0,0 +1,17 @@ +extra["mapLibreArtifactGroupId"] = "org.maplibre.gl" +extra["mapLibreArtifactId"] = "android-sdk" +extra["mapLibreArtifactTitle"] = "MapLibre Maps SDK for Android" +extra["mapLibreArtifactDescription"] = "MapLibre Maps SDK for Android" +extra["mapLibreDeveloperName"] = "MapLibre" +extra["mapLibreDeveloperId"] = "maplibre" +extra["mapLibreArtifactUrl"] = "https://github.com/maplibre/maplibre-native" +extra["mapLibreArtifactScmUrl"] = "scm:git@github.com:maplibre/maplibre-native.git" +extra["mapLibreArtifactLicenseName"] = "BSD" +extra["mapLibreArtifactLicenseUrl"] = "https://opensource.org/licenses/BSD-2-Clause" + +// Handling conditional assignment for versionName +extra["versionName"] = if (project.hasProperty("VERSION_NAME")) { + project.property("VERSION_NAME") +} else { + System.getenv("VERSION_NAME") +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts new file mode 100644 index 000000000..d96344753 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.dependencies.gradle.kts @@ -0,0 +1,4 @@ +extra["androidSdkVersions"] = mapOf( + "ndkVersion" to Versions.ndkVersion, + "cmakeVersion" to Versions.cmakeVersion +) diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.download-vulkan-validation.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.download-vulkan-validation.gradle.kts new file mode 100644 index 000000000..0177bb402 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.download-vulkan-validation.gradle.kts @@ -0,0 +1,67 @@ +import java.net.URL + + +/** + * Download validation layer binary release zip file from Khronos github repo + * https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases + * + * To use this script, add the following to your module's build.gradle: + * ext.vvl_version='your-new-version' + * apply from: "${PATH-TO-THIS}/download_vvl.gradle" + * To update to a new version: + * - change the ext.vvl_version to a new version string. + * - delete directory pointed by ${vvlJniLibDir}. + * - sync gradle script in IDE and rebuild project. + * + * Note: binary release can also be manually downloaded and put it into + * the default jniLibs directory at app/src/main/jniLibs. + */ + +// Define the validation layer version, with a default value. +var vvlVersion = "1.3.290.0" +if (extra.has("vvl_version")) { + vvlVersion = extra["vvl_version"] as String +} + +// Declare variables for the Vulkan Validation Layers download and extraction paths. +val vvlSite = "https://github.com/KhronosGroup/Vulkan-ValidationLayers" +val vvlLibRoot = projectDir // Set project root or change to rootDir if needed +val vvlJniLibDir = "$vvlLibRoot/src/vulkanDebug/jniLibs" +val vvlSoName = "libVkLayer_khronos_validation.so" + +// Download the release zip file to ${vvlLibRoot}/ +val download = tasks.register("download") { + val vvlZipName = "releases/download/vulkan-sdk-$vvlVersion/android-binaries-$vvlVersion.zip" + val zipFile = file("$vvlLibRoot/android-binaries-$vvlVersion.zip") + + mkdir(vvlLibRoot) + + doLast { + // Download the zip file from the Vulkan Validation Layers GitHub repo. + URL("$vvlSite/$vvlZipName").openStream().use { inputStream -> + zipFile.outputStream().use { outputStream -> + inputStream.copyTo(outputStream) + } + } + } +} + +val unzip = tasks.register("unzip") { + dependsOn(download) + + from(zipTree(file("$vvlLibRoot/android-binaries-$vvlVersion.zip"))) { + eachFile { + path = path.substringAfter("/") + } + includeEmptyDirs = false // Optional: Exclude empty directories if not needed + } + into(file(vvlJniLibDir)) + + doFirst { + mkdir(vvlJniLibDir) + } +} + +tasks.named("preBuild") { + dependsOn(unzip) +} \ No newline at end of file diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-checkstyle.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-checkstyle.gradle.kts new file mode 100644 index 000000000..c95e3a219 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-checkstyle.gradle.kts @@ -0,0 +1,32 @@ +plugins { + checkstyle +} + + +checkstyle { + toolVersion = "7.1.1" // 7.3 + configFile = file("../checkstyle.xml") +} + +tasks.register("checkstyle") { + description = "Checks if the code adheres to coding standards" + group = "verification" + configFile = file("../checkstyle.xml") + source("src") + include("**/*.java") + exclude("**/gen/**") + exclude("**/style/*LayerTest.java") + exclude("**/style/LightTest.java") + exclude("**/style/layers/Property.java") + exclude("**/style/layers/PropertyFactory.java") + exclude("**/style/layers/*Layer.java") + exclude("**/style/light/Light.java") + exclude("**/log/LoggerDefinition.java") + exclude("**/log/Logger.java") + exclude("**/Expression.java") + exclude("**/location/LocationPropertyFactory.java") + exclude("**/location/LocationIndicatorLayer.java") + exclude("**/location/LocationIndicatorLayerTest.java") + classpath = files() + isIgnoreFailures = false +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-config.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-config.gradle.kts new file mode 100644 index 000000000..ae2392fa8 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-config.gradle.kts @@ -0,0 +1,21 @@ +tasks.register("apiKey") { + val tokenFile = file("${projectDir}/src/main/res/values/developer-config.xml") + if (!tokenFile.exists()) { + var apiKey = System.getenv("MLN_API_KEY") ?: "null" + if (apiKey == "null") { + println("You should set the MLN_API_KEY environment variable.") + apiKey = "YOUR_API_KEY_GOES_HERE" + } + val tokenFileContents = "\n" + + "\n" + + " $apiKey\n" + + "" + tokenFile.writeText(tokenFileContents) + } +} + +gradle.projectsEvaluated { + tasks.named("preBuild").configure { + dependsOn("apiKey") + } +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-dependencies-graph.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-dependencies-graph.gradle.kts new file mode 100644 index 000000000..3d9aa59ae --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-dependencies-graph.gradle.kts @@ -0,0 +1,17 @@ +import com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension.Generator + +plugins { + id("com.vanniktech.dependency.graph.generator") +} + +val mapboxGenerator = Generator("mapboxLibraries", // Suffix for our Gradle task. + "", // Root suffix that we don't want in this case. + { dependency -> dependency.moduleGroup.startsWith("com.mapbox.mapboxsdk") }, // Only want Mapbox libs. + { dependency -> true } // Include transitive dependencies. +) + +dependencyGraphGenerator { + generators = listOf(mapboxGenerator) +} + + diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-lint.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-lint.gradle.kts new file mode 100644 index 000000000..586a26a43 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-lint.gradle.kts @@ -0,0 +1,19 @@ +tasks.register("ciLint") { + if (isLocalBuild()) { + from(file("$projectDir/lint/lint-baseline-local.xml")) + into("$projectDir") + rename { fileName -> + fileName.replace("lint-baseline-local.xml", "lint-baseline.xml") + } + } else { + from(file("$projectDir/lint/lint-baseline-ci.xml")) + into("$projectDir") + rename { fileName -> + fileName.replace("lint-baseline-ci.xml", "lint-baseline.xml") + } + } +} + +fun isLocalBuild(): Boolean { + return System.getenv("IS_LOCAL_DEVELOPMENT")?.toBoolean() ?: true +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-make.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-make.gradle.kts new file mode 100644 index 000000000..9c4946755 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-make.gradle.kts @@ -0,0 +1,14 @@ +tasks.register("makeClean") { + workingDir = file("../../") + commandLine("make", "clean") +} + +tasks.register("makeAndroid") { + workingDir = file("../../") + commandLine("make", "android") +} + +tasks.register("makeAndroidAll") { + workingDir = file("../../") + commandLine("make", "apackage") +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts new file mode 100644 index 000000000..aff14ef59 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.gradle-publish.gradle.kts @@ -0,0 +1,99 @@ +import org.gradle.kotlin.dsl.get + +plugins { + `maven-publish` + signing + id("com.android.library") + id("maplibre.artifact-settings") + id("maplibre.publish-root") +} + +tasks.register("androidJavadocs") { + source = fileTree(android.sourceSets.getByName("main").java.srcDirs) + classpath = files(android.bootClasspath) + isFailOnError = false +} + +tasks.register("androidJavadocsJar") { + archiveClassifier.set("javadoc") + from(tasks.named("androidJavadocs", Javadoc::class.java).get().destinationDir) +} + +tasks.register("androidSourcesJar") { + archiveClassifier.set("sources") + from(android.sourceSets.getByName("main").java.srcDirs) +} + +tasks.withType { + options.encoding = "UTF-8" + (options as StandardJavadocDocletOptions).apply { + charSet = "UTF-8" + docEncoding = "UTF-8" + } +} + + +artifacts { + add("archives", tasks.named("androidSourcesJar")) + add("archives", tasks.named("androidJavadocsJar")) +} + +project.logger.lifecycle(project.extra["versionName"].toString()) + +version = project.extra["versionName"] as String +group = project.extra["mapLibreArtifactGroupId"] as String + +afterEvaluate { + publishing { + publications { + create("release") { + groupId = this@afterEvaluate.group.toString() + artifactId = project.extra["mapLibreArtifactId"].toString() + version = this@afterEvaluate.version.toString() + + // Conditional component selection based on environment variable + from(components[if (System.getenv("RENDERER")?.lowercase() == "vulkan") "vulkanRelease" else "drawableRelease"]) + + pom { + name.set(project.extra["mapLibreArtifactTitle"].toString()) + description.set(project.extra["mapLibreArtifactTitle"].toString()) + url.set(project.extra["mapLibreArtifactUrl"].toString()) + licenses { + license { + name.set(project.extra["mapLibreArtifactLicenseName"].toString()) + url.set(project.extra["mapLibreArtifactLicenseUrl"].toString()) + } + } + developers { + developer { + id.set(project.extra["mapLibreDeveloperId"].toString()) + name.set(project.extra["mapLibreDeveloperName"].toString()) + email.set("maplibre@maplibre.org") + } + } + scm { + connection.set(project.extra["mapLibreArtifactScmUrl"].toString()) + developerConnection.set(project.extra["mapLibreArtifactScmUrl"].toString()) + url.set(project.extra["mapLibreArtifactUrl"].toString()) + } + } + } + } + } + +} + + +afterEvaluate { + android.libraryVariants.forEach { variant -> + tasks.named("androidJavadocs", Javadoc::class.java).configure { + doFirst { + classpath = classpath.plus(files(variant.javaCompileProvider.get().classpath)) + } + } + } +} + +signing { + sign(publishing.publications) +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.jacoco-report.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.jacoco-report.gradle.kts new file mode 100644 index 000000000..d2f14b019 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.jacoco-report.gradle.kts @@ -0,0 +1,35 @@ +plugins { + jacoco + id("maplibre.dependencies") +} + +jacoco { + toolVersion = "0.8.12" +} + +tasks.register("jacocoTestReport") { + group = "Reporting" + description = "Combine code coverage to unified report." + dependsOn("testDebugUnitTest") + + reports { + xml.required = true + html.required = true + } + + val fileExcludes = listOf("**/R.class", "**/R$*.class", "**/BuildConfig.*", "**/Manifest*.*", "**/*Test*.*", "android/**/*.*") + val debugTree = fileTree("${project.buildDir}/intermediates/javac/debug/classes") { exclude(fileExcludes) } + val mainSrc = "${project.projectDir}/src/main/java" + val ecSrc = fileTree("${project.buildDir}") { include("**/*.ec") } + val execSrc = fileTree("${project.buildDir}") { include("**/*.exec") } + + doFirst { + val files = files(ecSrc, execSrc).files + println("Creating Jacoco Report for ${files.size} coverage files") + files.forEach { file -> println(file) } + } + + sourceDirectories.setFrom(files(mainSrc)) + classDirectories.setFrom(files(debugTree)) + executionData.setFrom(files(ecSrc, execSrc)) +} diff --git a/platform/android/buildSrc/src/main/kotlin/maplibre.publish-root.gradle.kts b/platform/android/buildSrc/src/main/kotlin/maplibre.publish-root.gradle.kts new file mode 100644 index 000000000..ac9311d26 --- /dev/null +++ b/platform/android/buildSrc/src/main/kotlin/maplibre.publish-root.gradle.kts @@ -0,0 +1,6 @@ +extra["signing.keyId"] = System.getenv("SIGNING_KEY_ID") +extra["signing.password"] = System.getenv("SIGNING_PASSWORD") +extra["signing.secretKeyRingFile"] = "${projectDir}/../signing-key.gpg" +extra["ossrhUsername"] = System.getenv("OSSRH_USERNAME") +extra["ossrhPassword"] = System.getenv("OSSRH_PASSWORD") +extra["sonatypeStagingProfileId"] = System.getenv("SONATYPE_STAGING_PROFILE_ID") \ No newline at end of file diff --git a/platform/android/gradle/android-nitpick.gradle b/platform/android/gradle/android-nitpick.gradle deleted file mode 100644 index a90c5d7b7..000000000 --- a/platform/android/gradle/android-nitpick.gradle +++ /dev/null @@ -1,17 +0,0 @@ -apply from: "${rootDir}/gradle/dependencies.gradle" - -task androidNitpick { - doLast { - println "Running android nitpick script" - - verifyLicenseGeneration() - } -} - -private def verifyLicenseGeneration() { - println "Verify license generation with git diff..." - exec { - workingDir = "${rootDir}" - commandLine "python3", "scripts/validate-license.py" - } -} \ No newline at end of file diff --git a/platform/android/gradle/artifact-settings.gradle b/platform/android/gradle/artifact-settings.gradle deleted file mode 100644 index 63fd1f57c..000000000 --- a/platform/android/gradle/artifact-settings.gradle +++ /dev/null @@ -1,13 +0,0 @@ -ext { - mapLibreArtifactGroupId = 'org.maplibre.gl' - mapLibreArtifactId = 'android-sdk' - mapLibreArtifactTitle = 'MapLibre Maps SDK for Android' - mapLibreArtifactDescription = 'MapLibre Maps SDK for Android' - mapLibreDeveloperName = 'MapLibre' - mapLibreDeveloperId = 'maplibre' - mapLibreArtifactUrl = 'https://github.com/maplibre/maplibre-native' - mapLibreArtifactScmUrl = 'scm:git@github.com:maplibre/maplibre-native.git' - mapLibreArtifactLicenseName = 'BSD' - mapLibreArtifactLicenseUrl = 'https://opensource.org/licenses/BSD-2-Clause' - versionName = project.hasProperty('VERSION_NAME') ? project.property('VERSION_NAME') : System.getenv('VERSION_NAME') -} \ No newline at end of file diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle deleted file mode 100644 index c8f0a0bd2..000000000 --- a/platform/android/gradle/dependencies.gradle +++ /dev/null @@ -1,6 +0,0 @@ -ext { - androidSdkVersions = [ - ndkVersion : '27.0.12077973', - cmakeVersion : '3.18.1+', - ] -} diff --git a/platform/android/gradle/download-vulkan-validation.gradle b/platform/android/gradle/download-vulkan-validation.gradle deleted file mode 100644 index 85f54d0f4..000000000 --- a/platform/android/gradle/download-vulkan-validation.gradle +++ /dev/null @@ -1,51 +0,0 @@ -//apply plugin: 'com.android.application' -/** - * Download validation layer binary release zip file from Khronos github repo - * https://github.com/KhronosGroup/Vulkan-ValidationLayers/releases - * - * To use this script, add the following to your module's build.gradle: - * ext.vvl_version='your-new-version' - * apply from: "${PATH-TO-THIS}/download_vvl.gradle" - * To update to a new version: - * - change the ext.vvl_version to a new version string. - * - delete directory pointed by ${VVL_JNILIB_DIR}. - * - sync gradle script in IDE and rebuild project. - * - * Note: binary release can also be manually downloaded and put it into - * the default jniLibs directory at app/src/main/jniLibs. - */ - -// get the validation layer version. -def VVL_VER = "1.3.290.0" -if (ext.has("vvl_version")) { - VVL_VER = ext.vvl_version -} - -// declare local variables shared between downloading and unzipping. -def VVL_SITE ="https://github.com/KhronosGroup/Vulkan-ValidationLayers" -def VVL_LIB_ROOT= "$projectDir" //rootDir.absolutePath.toString() + "" -def VVL_JNILIB_DIR="${VVL_LIB_ROOT}/src/vulkanDebug/jniLibs" -def VVL_SO_NAME = "libVkLayer_khronos_validation.so" - -// download the release zip file to ${VVL_LIB_ROOT}/ -task download { - def VVL_ZIP_NAME = "releases/download/vulkan-sdk-${VVL_VER}/android-binaries-${VVL_VER}.zip" - mkdir "${VVL_LIB_ROOT}" - def f = new File("${VVL_LIB_ROOT}/android-binaries-${VVL_VER}.zip") - new URL("${VVL_SITE}/${VVL_ZIP_NAME}") - .withInputStream { i -> f.withOutputStream { it << i } } -} - -// unzip the downloaded VVL zip archive to the ${VVL_JNILIB_DIR} for APK packaging. -task unzip(dependsOn: download, type: Copy) { - from zipTree(file("${VVL_LIB_ROOT}/android-binaries-${VVL_VER}.zip")) - into file("${VVL_JNILIB_DIR}") -} - -//android.sourceSets.vulkan.jniLibs { -// srcDirs += ["${VVL_JNILIB_DIR}"] -//} - -android.sourceSets.vulkan.jniLibs { - srcDir(tasks.unzip) -} diff --git a/platform/android/gradle/gradle-checkstyle.gradle b/platform/android/gradle/gradle-checkstyle.gradle deleted file mode 100644 index 3e36e7746..000000000 --- a/platform/android/gradle/gradle-checkstyle.gradle +++ /dev/null @@ -1,29 +0,0 @@ -apply plugin: 'checkstyle' - -checkstyle { - toolVersion = "7.1.1" // 7.3 - configFile = "../checkstyle.xml" as File -} - -task checkstyle(type: Checkstyle) { - description 'Checks if the code adheres to coding standards' - group 'verification' - configFile file("../checkstyle.xml") - source 'src' - include '**/*.java' - exclude '**/gen/**' - exclude '**/style/*LayerTest.java' - exclude '**/style/LightTest.java' - exclude '**/style/layers/Property.java' - exclude '**/style/layers/PropertyFactory.java' - exclude '**/style/layers/*Layer.java' - exclude '**/style/light/Light.java' - exclude '**/log/LoggerDefinition.java' - exclude '**/log/Logger.java' - exclude '**/Expression.java' - exclude '**/location/LocationPropertyFactory.java' - exclude '**/location/LocationIndicatorLayer.java' - exclude '**/location/LocationIndicatorLayerTest.java' - classpath = files() - ignoreFailures = false -} diff --git a/platform/android/gradle/gradle-config.gradle b/platform/android/gradle/gradle-config.gradle deleted file mode 100644 index c9028e8d5..000000000 --- a/platform/android/gradle/gradle-config.gradle +++ /dev/null @@ -1,23 +0,0 @@ -// -// Configuration file for gradle build execution. -// - -task apiKey { - def tokenFile = new File("${projectDir}/src/main/res/values/developer-config.xml") - if (!tokenFile.exists()) { - String apiKey = "$System.env.MLN_API_KEY" - if (apiKey == "null") { - System.out.println("You should set the MLN_API_KEY environment variable.") - apiKey = "YOUR_API_KEY_GOES_HERE" - } - String tokenFileContents = "\n" + - "\n" + - " " + apiKey + "\n" + - "" - tokenFile.write(tokenFileContents) - } -} - -gradle.projectsEvaluated { - preBuild.dependsOn('apiKey') -} diff --git a/platform/android/gradle/gradle-dependencies-graph.gradle b/platform/android/gradle/gradle-dependencies-graph.gradle deleted file mode 100644 index 5cbc7b974..000000000 --- a/platform/android/gradle/gradle-dependencies-graph.gradle +++ /dev/null @@ -1,29 +0,0 @@ -buildscript { - repositories { - mavenCentral() - } - - dependencies { - classpath "com.vanniktech:gradle-dependency-graph-generator-plugin:0.3.0" - } -} - -import com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorPlugin -import com.vanniktech.dependency.graph.generator.DependencyGraphGeneratorExtension.Generator -import com.vanniktech.dependency.graph.generator.dot.GraphFormattingOptions -import com.vanniktech.dependency.graph.generator.dot.Color -import com.vanniktech.dependency.graph.generator.dot.Shape -import com.vanniktech.dependency.graph.generator.dot.Style - -plugins.apply(DependencyGraphGeneratorPlugin) - -def mapboxGenerator = new Generator( - "mapboxLibraries", // Suffix for our Gradle task. - "", // Root suffix that we don't want in this case. - { dependency -> dependency.getModuleGroup().startsWith("com.mapbox.mapboxsdk") }, // Only want Mapbox libs. - { dependency -> true }, // Include transitive dependencies. -) - -dependencyGraphGenerator { - generators = [mapboxGenerator] -} diff --git a/platform/android/gradle/gradle-lint.gradle b/platform/android/gradle/gradle-lint.gradle deleted file mode 100644 index 8a60a79b4..000000000 --- a/platform/android/gradle/gradle-lint.gradle +++ /dev/null @@ -1,22 +0,0 @@ -task ciLint(type: Copy) { - if (isLocalBuild()) { - from "${projectDir}/lint/lint-baseline-local.xml" - into "${projectDir}" - rename { String fileName -> - fileName.replace("lint-baseline-local.xml", "lint-baseline.xml") - } - } else { - from "${projectDir}/lint/lint-baseline-ci.xml" - into "${projectDir}" - rename { String fileName -> - fileName.replace("lint-baseline-ci.xml", "lint-baseline.xml") - } - } -} - -def isLocalBuild() { - if (System.getenv('IS_LOCAL_DEVELOPMENT') != null) { - return System.getenv('IS_LOCAL_DEVELOPMENT').toBoolean() - } - return true -} \ No newline at end of file diff --git a/platform/android/gradle/gradle-make.gradle b/platform/android/gradle/gradle-make.gradle deleted file mode 100644 index 65d971cc9..000000000 --- a/platform/android/gradle/gradle-make.gradle +++ /dev/null @@ -1,18 +0,0 @@ -// -// Contains GL-native make commands -// - -task makeClean(type: Exec) { - workingDir '../../' - commandLine 'make', 'clean' -} - -task makeAndroid(type: Exec) { - workingDir '../../' - commandLine 'make', 'android' -} - -task makeAndroidAll(type: Exec) { - workingDir '../../' - commandLine 'make', 'apackage' -} diff --git a/platform/android/gradle/gradle-publish.gradle b/platform/android/gradle/gradle-publish.gradle deleted file mode 100644 index 735d9cd65..000000000 --- a/platform/android/gradle/gradle-publish.gradle +++ /dev/null @@ -1,88 +0,0 @@ -apply plugin: 'maven-publish' -apply plugin: 'signing' -apply from: "${rootDir}/gradle/artifact-settings.gradle" -apply from: "${rootDir}/gradle/publish-root.gradle" - -task androidJavadocs(type: Javadoc) { - source = android.sourceSets.main.java.sourceFiles - classpath = files(android.bootClasspath) - failOnError = false -} - -task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { - archiveClassifier.set('javadoc') - from androidJavadocs.destinationDir -} - -task androidSourcesJar(type: Jar) { - archiveClassifier.set('sources') - from android.sourceSets.main.java.sourceFiles -} - -tasks.withType(Javadoc) { - options.addStringOption('encoding', 'UTF-8') - options.addStringOption('docencoding', 'UTF-8') - options.addStringOption('charset', 'UTF-8') -} - -artifacts { - archives androidSourcesJar - archives androidJavadocsJar -} - - -project.logger.lifecycle(ext["versionName"]) - -version = project.ext.versionName -group = project.ext.mapLibreArtifactGroupId - -afterEvaluate { - publishing { - publications { - release(MavenPublication) { - groupId this.group - artifactId project.ext.mapLibreArtifactId - version this.version - - from components."${System.getenv('RENDERER')?.toLowerCase() == 'vulkan' ? 'vulkanRelease' : 'drawableRelease'}" - - pom { - name = project.ext.mapLibreArtifactTitle - description = project.ext.mapLibreArtifactTitle - url = project.ext.mapLibreArtifactUrl - licenses { - license { - name = project.ext.mapLibreArtifactLicenseName - url = project.ext.mapLibreArtifactLicenseUrl - } - } - developers { - developer { - id = project.ext.mapLibreDeveloperId - name = project.ext.mapLibreDeveloperName - email = 'maplibre@maplibre.org' - } - } - scm { - connection = project.ext.mapLibreArtifactScmUrl - developerConnection = project.ext.mapLibreArtifactScmUrl - url = project.ext.mapLibreArtifactUrl - } - } - } - } - } -} - -afterEvaluate { project -> - android.libraryVariants.all { variant -> - tasks.androidJavadocs.doFirst { - classpath += files(variant.javaCompileProvider.get().classpath.files) - } - } -} - -signing { - sign publishing.publications -} - diff --git a/platform/android/gradle/jacoco-report.gradle b/platform/android/gradle/jacoco-report.gradle deleted file mode 100644 index 64c99e09f..000000000 --- a/platform/android/gradle/jacoco-report.gradle +++ /dev/null @@ -1,33 +0,0 @@ -apply plugin: 'jacoco' -apply from: "${rootDir}/gradle/dependencies.gradle" - -jacoco { - toolVersion = versions.jacoco -} - -task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest']) { - group = "Reporting" - description = "Combine code coverage to unified report." - - reports { - xml.enabled = true - html.enabled = true - } - - def fileExcludes = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] - def debugTree = fileTree(dir: "${project.buildDir}/intermediates/javac/debug/classes", excludes: fileExcludes) - def mainSrc = "${project.projectDir}/src/main/java" - println(mainSrc) - def ecSrc = fileTree(dir: "$project.buildDir", include: "**/*.ec") - def execSrc = fileTree(dir: "$project.buildDir", include: "**/*.exec") - - doFirst { - def files = files([ecSrc, execSrc]).files - println "Creating Jacoco Report for ${files.size()} coverage files" - files.each { file -> println file } - } - - sourceDirectories.from = files([mainSrc]) - classDirectories.from = files([debugTree]) - executionData.from = files([ecSrc, execSrc]) -} \ No newline at end of file diff --git a/platform/android/gradle/libs.versions.toml b/platform/android/gradle/libs.versions.toml index d9a0cf51b..15d81d877 100644 --- a/platform/android/gradle/libs.versions.toml +++ b/platform/android/gradle/libs.versions.toml @@ -90,4 +90,6 @@ nexusPublishPlugin = { id = "io.github.gradle-nexus.publish-plugin", version = " kotlinter = { id = "org.jmailen.kotlinter", version = "4.4.1" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version = "2.0.20" } dokka = { id = "org.jetbrains.dokka", version = "1.9.20" } -kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.0.20" } \ No newline at end of file +kotlinPluginSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.0.20" } +android-application = { id = "com.android.application", version.ref = "androidGradlePlugin" } +android-library = { id = "com.android.library", version.ref = "androidGradlePlugin" } \ No newline at end of file diff --git a/platform/android/gradle/native-build.gradle b/platform/android/gradle/native-build.gradle deleted file mode 100644 index be04e3f60..000000000 --- a/platform/android/gradle/native-build.gradle +++ /dev/null @@ -1,75 +0,0 @@ -ext.nativeBuild = { nativeTargets -> - android { - ndkVersion androidSdkVersions.ndkVersion - - // We sometimes want to invoke Gradle without building a native dependency, e.g. when we just want - // to invoke the Java tests. When we explicitly specify an ABI of 'none', no native dependencies are - // added. When another ABI is specified explicitly, we're just going to build that ABI. In all other - // cases, all ABIs are built. - // - // When invoking from the command line or to override the device default, set `-Pmaplibre.abis=...` to - // only build the desired architectures. - // - // When building from Android Studio, gradle.properties sets `android.buildOnlyTargetAbi=true` so that - // only the architecture for the device you're running on gets built. - def abi = 'all' - if (!project.hasProperty('android.injected.invoked.from.ide') && project.hasProperty("maplibre.abis")) { - // Errors when the user invokes Gradle from the command line and didn't set maplibre.abis - abi = project.getProperty("maplibre.abis") - } - - if (abi != 'none') { - externalNativeBuild { - cmake { - path "../MapLibreAndroid/src/cpp/CMakeLists.txt" - version androidSdkVersions.cmakeVersion - } - } - } - - // Allow determining the C++ STL we're using when building Mapbox GL. - def stl = 'c++_static' - if (project.hasProperty("mapbox.stl")) { - stl = project.getProperty("mapbox.stl") - } - - defaultConfig { - if (abi != 'none') { - externalNativeBuild { - cmake { - arguments "-DANDROID_TOOLCHAIN=clang" - arguments "-DANDROID_STL=" + stl - arguments "-DANDROID_CPP_FEATURES=exceptions" - arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" - - // Enable ccache if the user has installed it. - if (file("/usr/bin/ccache").exists()) { - arguments "-DANDROID_CCACHE=/usr/bin/ccache" - } else if (file("/usr/local/bin/ccache").exists()) { - arguments "-DANDROID_CCACHE=/usr/local/bin/ccache" - } - - cFlags "-Qunused-arguments" - cppFlags "-Qunused-arguments" - - for (target in nativeTargets) { - targets target - } - - if (abi != 'all') { - abiFilters abi.split(' ') - } else { - if (project.hasProperty('android.injected.invoked.from.ide') && project.hasProperty('android.injected.build.abi')) { - //Only build the target abi while running from Android studio - abi = project.getProperty("android.injected.build.abi") - abiFilters abi.split(',').first() - } else { - abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64" - } - } - } - } - } - } - } -} diff --git a/platform/android/gradle/publish-root.gradle b/platform/android/gradle/publish-root.gradle deleted file mode 100644 index 6bed2e9db..000000000 --- a/platform/android/gradle/publish-root.gradle +++ /dev/null @@ -1,6 +0,0 @@ -ext["signing.keyId"] = System.getenv('SIGNING_KEY_ID') -ext["signing.password"] = System.getenv('SIGNING_PASSWORD') -ext["signing.secretKeyRingFile"] = "${projectDir}/../signing-key.gpg" -ext["ossrhUsername"] = System.getenv('OSSRH_USERNAME') -ext["ossrhPassword"] = System.getenv('OSSRH_PASSWORD') -ext["sonatypeStagingProfileId"] = System.getenv('SONATYPE_STAGING_PROFILE_ID') diff --git a/platform/android/settings.gradle b/platform/android/settings.gradle deleted file mode 100644 index 79419e696..000000000 --- a/platform/android/settings.gradle +++ /dev/null @@ -1,17 +0,0 @@ -plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' -} - -include ':MapLibreAndroid', ':MapLibreAndroidTestApp', ':MapLibreAndroidLint' - -rootProject.name = "MapLibre Native for Android" - -def renderTestProjectDir = new File(rootDir, '../../render-test/android') -includeBuild(renderTestProjectDir) { - name ="renderTestApp" -} - -def cppTestProjectDir = new File(rootDir, '../../test/android') -includeBuild(cppTestProjectDir) { - name ="cppUnitTestsApp" -} \ No newline at end of file diff --git a/platform/android/settings.gradle.kts b/platform/android/settings.gradle.kts new file mode 100644 index 000000000..cec5e4bfd --- /dev/null +++ b/platform/android/settings.gradle.kts @@ -0,0 +1,39 @@ +pluginManagement { + repositories { + google { + content { + includeGroupByRegex("com\\.android.*") + includeGroupByRegex("com\\.google.*") + includeGroupByRegex("androidx.*") + } + } + mavenCentral() + gradlePluginPortal() + } +} +dependencyResolutionManagement { + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) + repositories { + google() + mavenCentral() + maven("https://plugins.gradle.org/m2/") + } +} + +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} + +include(":MapLibreAndroid", ":MapLibreAndroidTestApp", ":MapLibreAndroidLint") + +rootProject.name = "MapLibre Native for Android" + +val renderTestProjectDir = file("$rootDir/../../render-test/android") +includeBuild(renderTestProjectDir) { + name = "renderTestApp" +} + +val cppTestProjectDir = file("$rootDir/../../test/android") +includeBuild(cppTestProjectDir) { + name = "cppUnitTestsApp" +}