blob: bb243839663dab4b65179fbd6027a44fc650e7e4 [file] [log] [blame]
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import androidx.build.AndroidXConfig
import androidx.build.KmpPlatformsKt
import androidx.build.PlatformIdentifier
import androidx.build.Publish
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.konan.target.Family
import org.jetbrains.kotlin.konan.target.KonanTarget
plugins {
id("AndroidXPlugin")
id("com.android.library")
}
// List of flags we use to compile SQLite.
// See: https://www.sqlite.org/compile.html
// TODO(b/310681164): Validate these flags and compare to other platforms.
def SQLITE_COMPILE_FLAGS = [
"-DHAVE_USLEEP=1",
"-DSQLITE_ENABLE_COLUMN_METADATA=1",
"-DSQLITE_ENABLE_NORMALIZE=1",
"-DSQLITE_ENABLE_LOAD_EXTENSION=1",
"-DSQLITE_ENABLE_FTS3=1",
"-DSQLITE_ENABLE_FTS3_PARENTHESIS=1",
"-DSQLITE_ENABLE_FTS4=1",
"-DSQLITE_ENABLE_FTS5=1",
"-DSQLITE_ENABLE_JSON1=1",
"-DSQLITE_ENABLE_RTREE=1",
"-DSQLITE_ENABLE_STAT4=1",
"-DSQLITE_THREADSAFE=1",
"-DSQLITE_DEFAULT_MEMSTATUS=0",
"-DSQLITE_OMIT_PROGRESS_CALLBACK=0",
"-DSQLITE_ENABLE_RBU=1",
]
// Copy SQLite sources into a build directory. Even though this is not needed, it will be
// nice to have them there so that we can swap them with SQLite amalgamation for Github.
// TODO(b/306669673): Support GitHub builds
def copySqliteSourcesTask = tasks.register("copySqliteSources", Copy) {
from(new File(AndroidXConfig.getExternalProjectPath(project), "sqlite/dist/orig")) {
include "sqlite3.c"
include "sqlite3.h"
}
into(project.layout.buildDirectory.dir("sqlite3/src"))
}
configurations {
// Configuration for producing an shareable archive file of compiled SQLite. Only the Linux X64
// target of SQLite is produced hence the explicit name and attributes
linuxSharedArchive {
canBeConsumed = true
canBeResolved = false
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.NATIVE_LINK))
}
}
}
def nativeEnabled = KmpPlatformsKt.enableNative(project)
androidXMultiplatform {
// List of targets for native compilation that are needed for JVM / ART tests.
// Note that even if the native KMP targets are disabled, we still need to compile the C
// code for these targets as they are used in JVM / ART tests (via JNI).
def requiredNativeTargets = [
KonanTarget.ANDROID_ARM32,
KonanTarget.ANDROID_ARM64,
KonanTarget.ANDROID_X64,
KonanTarget.ANDROID_X86,
KonanTarget.MACOS_ARM64,
KonanTarget.MACOS_X64,
KonanTarget.LINUX_X64,
].collect { it.INSTANCE } // Use INSTANCE to get object class instance from kotlin
// Define C compilation of SQLite (sqlite3.c)
def sqliteCompilation = createNativeCompilation("androidXBundledSqlite") {
configureEachTarget { nativeCompilation ->
// add SQLite header
nativeCompilation.includes.from(
copySqliteSourcesTask.map { it.destinationDir }
)
// add SQLite sources
nativeCompilation.sources.from(
copySqliteSourcesTask.map {
fileTree(it.destinationDir).matching { include "**/*.c" }
}
)
// add SQLite compile flags
nativeCompilation.freeArgs.addAll(SQLITE_COMPILE_FLAGS)
if (nativeCompilation.konanTarget.family == Family.ANDROID) {
nativeCompilation.freeArgs.add("-Oz") // optimize for size
} else {
nativeCompilation.freeArgs.add("-O3") // optimize for speed
}
}
configureTargets(requiredNativeTargets)
}
// add SQLite compilation output as an artifact of a producer configuration
if (nativeEnabled) {
artifacts.add(
"linuxSharedArchive",
sqliteCompilation.sharedArchiveOutputFor(KonanTarget.LINUX_X64.INSTANCE)
)
}
// Defince C++ compilation of JNI
def jvmArtJniImplementation = createNativeCompilation("jvmArtJniImplementation") {
configureEachTarget { nativeCompilation ->
// add JNI headers as sources
nativeCompilation.addJniHeaders()
// add SQLite headers
nativeCompilation.includes.from(
copySqliteSourcesTask.map {it.destinationDir }
)
// add our JNI sources, i.e. the SQLite bindings
nativeCompilation.sources.from(
fileTree("src/androidJvmCommonMain/jni").matching { include "**/*.cpp" }
)
// dynamically link with the output of SQLite
nativeCompilation.linkWith(sqliteCompilation)
}
configureTargets(requiredNativeTargets)
}
android() {
addNativeLibrariesToJniLibs(it, sqliteCompilation)
addNativeLibrariesToJniLibs(it, jvmArtJniImplementation)
}
androidNative()
ios()
jvm() {
addNativeLibrariesToResources(it, sqliteCompilation)
addNativeLibrariesToResources(it, jvmArtJniImplementation)
}
linux()
mac()
defaultPlatform(PlatformIdentifier.ANDROID)
targets.all { target ->
if (target.platformType == KotlinPlatformType.native) {
// Configure this native target to the SQLite compilation.
// This list likely only adds the iOS targets when they are enabled as the desktop
// targets are already part of the required targets to run JVM / ART tests.
sqliteCompilation.configureTarget(target.konanTarget)
// Create cinterop code for this native target from the SQLite compilation.
createCinterop(target, sqliteCompilation)
}
}
sourceSets {
// commonMain
// ┌───────────────────────────────────────────┐
// ▼ ▼
// androidJvmCommonMain nativeMain
// ┌────────────────┐ ┌──────────┬────────────┐
// │ │ │ │ │
// ▼ ▼ ▼ ▼ ▼
// jvmMain androidMain macMain linuxMain iosMain
//
//
//
//
//
// sharedTest
// ┌───────────────────────────────────────────┐
// │ │
// ▼ ▼
// androidJvmCommonTest nativeTest
// ┌────────────────────┐ ┌─────────┬─────────────┐
// │ │ │ │ │
// ▼ ▼ ▼ ▼ ▼
// jvmTest androidInstrumentedTest macTest linuxTest iosTest
commonMain {
dependencies {
implementation(libs.kotlinStdlib)
api(project(":sqlite:sqlite"))
}
}
sharedTest {
// Using a custom sourceSet for tests instead of commonTest because commonTest is
// added to the Android Host test compilation and cannot run since it doesn't have the
// native dependencies besides Android (in other words, it is running the AAR on JVM
// hence doesn't have the necessary native libs to run the code).
dependencies {
implementation(libs.kotlinTest)
implementation(libs.kotlinTestAnnotationsCommon)
implementation(project(":kruth:kruth"))
implementation(project(":sqlite:integration-tests:driver-conformance-test"))
}
}
androidJvmCommonMain {
// common code between android and jvm
dependsOn(commonMain)
}
androidJvmCommonTest {
dependsOn(sharedTest)
}
jvmMain {
dependsOn(androidJvmCommonMain)
}
jvmTest {
dependsOn(androidJvmCommonTest)
}
androidMain {
dependsOn(androidJvmCommonMain)
}
androidInstrumentedTest {
dependsOn(androidJvmCommonTest)
dependencies {
implementation(libs.testRunner)
implementation(libs.testCore)
implementation(libs.kotlinTestJunit)
}
}
if (nativeEnabled) {
nativeMain {
dependsOn(commonMain)
dependencies {
implementation(project(":sqlite:sqlite-framework"))
}
}
nativeTest {
dependsOn(sharedTest)
}
}
targets.all { target ->
if (target.platformType == KotlinPlatformType.native) {
target.compilations["main"].defaultSourceSet {
dependsOn(nativeMain)
}
target.compilations["test"].defaultSourceSet {
dependsOn(nativeTest)
}
}
}
}
}
android {
namespace "androidx.sqlite.driver.bundled"
}
androidx {
name = "SQLite Bundled Integration"
publish = Publish.SNAPSHOT_AND_RELEASE
inceptionYear = "2023"
description = "The implementation of SQLite library using the bundled SQLite."
metalavaK2UastEnabled = false
}