aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorandroid-build-team Robot <android-build-team-robot@google.com>2021-06-21 14:54:23 +0000
committerandroid-build-team Robot <android-build-team-robot@google.com>2021-06-21 14:54:23 +0000
commit49c976fc0cd013f2ddb23a28390b7a5d00ab9c53 (patch)
tree96d3320fa24a1aa2160e56ef7d8157d653cc0f9b
parentd0ec81e4b134f4b1446d3fd5a6dfbf095475597c (diff)
parenta181fe59a34803a1ba7300bd1a32532b6dc3e9fb (diff)
downloadndkports-android12-mainline-extservices-release.tar.gz
Change-Id: I6b6b3ded37c1d5c959e176b1f35c113802458a99
-rw-r--r--Dockerfile2
-rw-r--r--README.md37
-rw-r--r--build.gradle.kts69
-rw-r--r--ports/curl/port.kts6
-rw-r--r--ports/curl/src.tar.gzbin0 -> 4131634 bytes
-rw-r--r--ports/jsoncpp/port.kts24
-rw-r--r--ports/jsoncpp/src.tar.gzbin0 -> 200226 bytes
-rw-r--r--ports/openssl/port.kts8
-rw-r--r--ports/openssl/src.tar.gzbin0 -> 9801502 bytes
-rw-r--r--src/main/kotlin/com/android/ndkports/Cli.kt13
-rw-r--r--src/main/kotlin/com/android/ndkports/Port.kt178
-rw-r--r--src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt4
12 files changed, 247 insertions, 94 deletions
diff --git a/Dockerfile b/Dockerfile
index 2185c83..aba9898 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -12,4 +12,4 @@ RUN mv android-ndk-r20b /ndk
WORKDIR /src
ENTRYPOINT ["./gradlew"]
-CMD ["-PndkPath=/ndk", "run"]
+CMD ["-PndkPath=/ndk", "release"]
diff --git a/README.md b/README.md
index 7d47a9b..6a70957 100644
--- a/README.md
+++ b/README.md
@@ -20,44 +20,13 @@ A port is a subclass of the abstract Kotlin class `com.android.ndkports.Port`.
Projects define the name and version of the port, the URL to fetch source from,
a list of modules (libraries) to build, and the build steps.
-```kotlin
-abstract class Port {
- abstract val name: String
- abstract val version: String
- abstract val url: String
-
- open val dependencies: List<String> = emptyList()
- abstract val modules: List<Module>
-
- open fun fetchSource(
- sourceDirectory: File,
- workingDirectory: File
- ): Result<Unit, String>
-
- open fun configure(
- toolchain: Toolchain,
- sourceDirectory: File,
- buildDirectory: File,
- installDirectory: File,
- workingDirectory: File
- ): Result<Unit, String>
-
- open fun build(
- toolchain: Toolchain,
- buildDirectory: File
- ): Result<Unit, String>
-
- open fun install(
- toolchain: Toolchain,
- buildDirectory: File,
- installDirectory: File
- ): Result<Unit, String>
-}
-```
+See the [Port class] for documentation on the port API.
Individual port files are kept in `ports/$name/port.kts`. For example, the cURL
port is [ports/curl/port.kts](ports/curl/port.kts).
+[Port class]: src/main/kotlin/com/android/ndkports/Port.kt
+
## Building a Port
ndkports requires an NDK to be used for building to be specified on the command
diff --git a/build.gradle.kts b/build.gradle.kts
index b9a4d11..a00d626 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
- kotlin("jvm") version "1.3.50"
+ kotlin("jvm") version "1.3.72"
application
}
@@ -16,13 +16,12 @@ repositories {
}
dependencies {
- implementation(kotlin("stdlib", "1.3.50"))
- implementation(kotlin("reflect", "1.3.50"))
+ implementation(kotlin("stdlib", "1.3.72"))
+ implementation(kotlin("reflect", "1.3.72"))
- implementation("com.google.prefab:api:1.0.0-alpha2")
+ implementation("com.google.prefab:api:1.0.0")
implementation("com.github.ajalt:clikt:2.2.0")
- implementation("com.squareup.okhttp3:okhttp:4.2.2")
implementation("de.swirtz:ktsRunner:0.0.7")
implementation("org.apache.maven:maven-core:3.6.2")
implementation("org.redundent:kotlin-xml-builder:1.5.3")
@@ -46,6 +45,10 @@ tasks.withType<KotlinCompile> {
)
}
+val portsBuildDir = buildDir.resolve("ports")
+
+val allPorts = listOf("openssl", "curl", "jsoncpp")
+
// Can be specified in ~/.gradle/gradle.properties:
//
// ndkPath=/path/to/ndk
@@ -55,6 +58,56 @@ tasks.withType<KotlinCompile> {
// ./gradlew -PndkPath=/path/to/ndk run
val ndkPath: String by project
tasks.named<JavaExec>("run") {
- val allPorts = File("ports").listFiles()!!.map { it.name }
- args = listOf("--ndk", ndkPath, "-o", "out") + allPorts
-} \ No newline at end of file
+ // Order matters since we don't do any dependency sorting, so we can't just
+ // use the directory list.
+ args = listOf("--ndk", ndkPath, "-o", portsBuildDir.toString()) + allPorts
+}
+
+for (port in allPorts) {
+ distributions {
+ create(port) {
+ contents {
+ includeEmptyDirs = false
+ from(portsBuildDir.resolve(port)) {
+ include("**/*.aar")
+ include("**/*.pom")
+ }
+ }
+ }
+ }
+
+ tasks.named("${port}DistTar") {
+ dependsOn(":run")
+ }
+
+ tasks.named("${port}DistZip") {
+ dependsOn(":run")
+ }
+}
+
+distributions {
+ create("all") {
+ contents {
+ includeEmptyDirs = false
+ from(portsBuildDir) {
+ include("**/*.aar")
+ include("**/*.pom")
+ }
+ }
+ }
+}
+
+tasks.named("allDistTar") {
+ dependsOn(":run")
+}
+
+tasks.named("allDistZip") {
+ dependsOn(":run")
+}
+
+tasks.register("release") {
+ dependsOn(":allDistZip")
+ for (port in allPorts) {
+ dependsOn(":${port}DistZip")
+ }
+}
diff --git a/ports/curl/port.kts b/ports/curl/port.kts
index 734fa27..a870a86 100644
--- a/ports/curl/port.kts
+++ b/ports/curl/port.kts
@@ -20,8 +20,8 @@ import java.io.File
object : AutoconfPort() {
override val name = "curl"
- override val version = "7.66.0"
- override val url = "https://curl.haxx.se/download/curl-$version.tar.gz"
+ override val version = "7.69.1"
+ override val mavenVersion = "$version-alpha-1"
override val licensePath = "COPYING"
override val license = License(
@@ -67,4 +67,4 @@ object : AutoconfPort() {
// TODO: Switch to lld once we're using r21.
"LDFLAGS" to "-fuse-ld=gold"
)
-} \ No newline at end of file
+}
diff --git a/ports/curl/src.tar.gz b/ports/curl/src.tar.gz
new file mode 100644
index 0000000..b0da690
--- /dev/null
+++ b/ports/curl/src.tar.gz
Binary files differ
diff --git a/ports/jsoncpp/port.kts b/ports/jsoncpp/port.kts
index f951e23..8a3e1ba 100644
--- a/ports/jsoncpp/port.kts
+++ b/ports/jsoncpp/port.kts
@@ -20,9 +20,8 @@ import java.io.File
object : MesonPort() {
override val name = "jsoncpp"
- override val version = "1.9.1"
- override val url =
- "https://github.com/open-source-parsers/jsoncpp/archive/$version.tar.gz"
+ override val version = "1.8.4"
+ override val mavenVersion = "$version-alpha-1"
override val license = License(
"The JsonCpp License",
@@ -33,14 +32,17 @@ object : MesonPort() {
Module("jsoncpp")
)
- override fun fetchSource(
+ override fun extractSource(
+ sourceTarball: File,
sourceDirectory: File,
workingDirectory: File
): Result<Unit, String> =
- super.fetchSource(sourceDirectory, workingDirectory).onSuccess {
- // jsoncpp has a "version" file on the include path that conflicts
- // with https://en.cppreference.com/w/cpp/header/version. Remove it
- // so we can build.
- sourceDirectory.resolve("version").delete()
- }
-} \ No newline at end of file
+ super.extractSource(sourceTarball, sourceDirectory, workingDirectory)
+ .onSuccess {
+ // jsoncpp has a "version" file on the include path that
+ // conflicts with
+ // https://en.cppreference.com/w/cpp/header/version. Remove it
+ // so we can build.
+ sourceDirectory.resolve("version").delete()
+ }
+}
diff --git a/ports/jsoncpp/src.tar.gz b/ports/jsoncpp/src.tar.gz
new file mode 100644
index 0000000..7f3cd4b
--- /dev/null
+++ b/ports/jsoncpp/src.tar.gz
Binary files differ
diff --git a/ports/openssl/port.kts b/ports/openssl/port.kts
index 00345bc..45b5206 100644
--- a/ports/openssl/port.kts
+++ b/ports/openssl/port.kts
@@ -20,9 +20,9 @@ import java.io.File
object : Port() {
override val name = "openssl"
- override val version = "1.1.1d"
- override val prefabVersion = CMakeCompatibleVersion(1, 1, 1, 4)
- override val url = "https://www.openssl.org/source/openssl-$version.tar.gz"
+ override val version = "1.1.1g"
+ override val mavenVersion = "$version-alpha-1"
+ override val prefabVersion = CMakeCompatibleVersion(1, 1, 1, 7)
override val license = License(
"Dual OpenSSL and SSLeay License",
@@ -87,4 +87,4 @@ object : Port() {
"PATH" to "${toolchain.binDir}:${System.getenv("PATH")}"
)
)
-} \ No newline at end of file
+}
diff --git a/ports/openssl/src.tar.gz b/ports/openssl/src.tar.gz
new file mode 100644
index 0000000..e768f9e
--- /dev/null
+++ b/ports/openssl/src.tar.gz
Binary files differ
diff --git a/src/main/kotlin/com/android/ndkports/Cli.kt b/src/main/kotlin/com/android/ndkports/Cli.kt
index 25d48ed..e2a5879 100644
--- a/src/main/kotlin/com/android/ndkports/Cli.kt
+++ b/src/main/kotlin/com/android/ndkports/Cli.kt
@@ -51,8 +51,11 @@ class Cli : CliktCommand(help = "ndkports") {
private val ndk: Ndk by option().convert { Ndk(File(it)) }.required()
+ private fun portDirectoryFor(name: String): File =
+ File("ports").resolve(name)
+
private fun loadPort(name: String): Port {
- val portDir = File("ports").resolve(name).also {
+ val portDir = portDirectoryFor(name).also {
if (!it.exists()) {
throw FileNotFoundException("Could not find ${it.path}")
}
@@ -73,12 +76,12 @@ class Cli : CliktCommand(help = "ndkports") {
for (port in portsByName.values) {
val workingDirectory =
outDir.resolve(port.name).also { it.mkdirs() }
+
val sourceDirectory = workingDirectory.resolve("src")
+ val sourceTarball =
+ portDirectoryFor(port.name).resolve("src.tar.gz")
- port.fetchSource(sourceDirectory, workingDirectory).onFailure {
- println(it)
- exitProcess(1)
- }
+ port.extractSource(sourceTarball, sourceDirectory, workingDirectory)
val apiForAbi = mapOf(
Abi.Arm to 16,
diff --git a/src/main/kotlin/com/android/ndkports/Port.kt b/src/main/kotlin/com/android/ndkports/Port.kt
index 08c8fbf..2e0433f 100644
--- a/src/main/kotlin/com/android/ndkports/Port.kt
+++ b/src/main/kotlin/com/android/ndkports/Port.kt
@@ -16,10 +16,7 @@
package com.android.ndkports
-import okhttp3.OkHttpClient
-import okhttp3.Request
import java.io.File
-import java.io.FileOutputStream
@Suppress("unused")
fun executeProcessStep(
@@ -52,29 +49,105 @@ fun installDirectoryForPort(
toolchain: Toolchain
): File = workingDirectory.parentFile.resolve("$name/install/${toolchain.abi}")
+/**
+ * A module exported by the package.
+ *
+ * As currently implemented by ndkports, one module is exactly one library.
+ * Prefab supports header-only libraries, but ndkports does not support these
+ * yet.
+ *
+ * Static libraries are not currently supported by ndkports.
+ *
+ * @property[name] The name of the module. Note that currently the name of the
+ * installed library file must be exactly `lib$name.so`.
+ * @property[includesPerAbi] Set to true if a different set of headers should be
+ * exposed per-ABI. Not currently implemented.
+ * @property[dependencies] A list of other modules required by this module, in
+ * the format described by https://google.github.io/prefab/.
+ */
data class Module(
val name: String,
val includesPerAbi: Boolean = false,
val dependencies: List<String> = emptyList()
)
+/**
+ * The base class for all ports.
+ */
abstract class Port {
+ /**
+ * The name of the port. Will be used as the package name in prefab.json.
+ */
abstract val name: String
+
+ /**
+ * The version of the package.
+ *
+ * Used as the default for [prefabVersion] and [mavenVersion] when
+ * appropriate.
+ */
abstract val version: String
+
+ /**
+ * The version to encode in the prefab.json.
+ *
+ * This version must be compatible with CMake's `find_package` for
+ * config-style packages. This means that it must be one to four decimal
+ * separated integers. No other format is allowed.
+ *
+ * If not set, the default is [version] as interpreted by
+ * [CMakeCompatibleVersion.parse].
+ *
+ * For example, OpenSSL 1.1.1g will set this value to
+ * `CMakeCompatibleVersion(1, 1, 1, 7)`.
+ */
open val prefabVersion: CMakeCompatibleVersion
get() = CMakeCompatibleVersion.parse(version)
+
+ /**
+ * The version to use for the maven package.
+ *
+ * This field allows versioning the maven package differently from the
+ * package itself, which is sometimes necessary given CMake's strict version
+ * format requirements.
+ *
+ * If not set, the default is [version].
+ *
+ * For example, this could be set to `"$name-$version-alpha-1"` to
+ * distribute an alpha of the package.
+ */
open val mavenVersion: String
get() = version
- abstract val url: String
-
+ /**
+ * The relative path to the license file of this package.
+ *
+ * This file will be packaged in the AAR in the META-INF directory.
+ */
open val licensePath: String = "LICENSE"
+ /**
+ * A description of the license (name and URL) for use in the pom.xml.
+ */
abstract val license: License
+ /**
+ * A list of dependencies for this package.
+ *
+ * For example, curl depends on `listOf("openssl")`.
+ */
open val dependencies: List<String> = emptyList()
+
+ /**
+ * A list of modules exported by this package.
+ */
abstract val modules: List<Module>
+ /**
+ * The number of CPUs available for building.
+ *
+ * May be passed to the build system if required.
+ */
protected val ncpus = Runtime.getRuntime().availableProcessors()
fun run(
@@ -103,40 +176,53 @@ abstract class Port {
return Result.Ok(Unit)
}
- open fun fetchSource(
+ /**
+ * Overridable build step for extracting the source package.
+ *
+ * @param[sourceTarball] The path to the source tarball.
+ * @param[sourceDirectory] The destination directory for the extracted
+ * source.
+ * @param[workingDirectory] The working top-level directory for this
+ * package.
+ * @return A [Result<Unit, String>][Result] describing the result of the
+ * operation. On failure, [Result.Error<String>][Result.Error] containing an
+ * error message is returned.
+ */
+ open fun extractSource(
+ sourceTarball: File,
sourceDirectory: File,
workingDirectory: File
): Result<Unit, String> {
- val file = workingDirectory.resolve(File(url).name)
-
- val client = OkHttpClient()
- val request = Request.Builder().url(url).build()
- client.newCall(request).execute().use { response ->
- if (!response.isSuccessful) {
- return Result.Error("Failed to download $url")
- }
-
- val body = response.body ?: throw RuntimeException(
- "Expected non-null response body for $url"
- )
- FileOutputStream(file).use { output ->
- body.byteStream().use { input ->
- input.copyTo(output)
- }
- }
- }
-
sourceDirectory.mkdirs()
return executeProcessStep(
listOf(
"tar",
"xf",
- file.absolutePath,
+ sourceTarball.absolutePath,
"--strip-components=1"
), sourceDirectory
)
}
+ /**
+ * Overridable build step for configuring the build.
+ *
+ * Any pre-build steps should be run here.
+ *
+ * In an autoconf build, this runs `configure`.
+ *
+ * @param[toolchain] The toolchain used for this build.
+ * @param[sourceDirectory] The directory containing the extracted package
+ * source.
+ * @param[buildDirectory] The directory to use for building.
+ * @param[installDirectory] The destination directory for this package's
+ * installed headers and libraries.
+ * @param[workingDirectory] The top-level working directory for this
+ * package.
+ * @return A [Result<Unit, String>][Result] describing the result of the
+ * operation. On failure, [Result.Error<String>][Result.Error] containing an
+ * error message is returned.
+ */
open fun configure(
toolchain: Toolchain,
sourceDirectory: File,
@@ -145,11 +231,51 @@ abstract class Port {
workingDirectory: File
): Result<Unit, String> = Result.Ok(Unit)
+ /**
+ * Overridable build step for building the package.
+ *
+ * In an autoconf build, this runs `make`.
+ *
+ * @param[toolchain] The toolchain used for this build.
+ * @param[buildDirectory] The directory to use for building.
+ * @return A [Result<Unit, String>][Result] describing the result of the
+ * operation. On failure, [Result.Error<String>][Result.Error] containing an
+ * error message is returned.
+ */
open fun build(
toolchain: Toolchain,
buildDirectory: File
): Result<Unit, String> = Result.Ok(Unit)
+ /**
+ * Overridable build step for installing built artifacts for packaging.
+ *
+ * The install step is expected to install headers and libraries to the
+ * [installDirectory] with the following layout:
+ *
+ * [installDirectory]
+ * include/
+ * <package headers>
+ * lib/
+ * <package libraries>
+ *
+ * A matching `lib${module.name}.so` must be present in the `lib` directory
+ * for every item in [modules].
+ *
+ * Note that it is expected for all modules to use the same headers. This is
+ * currently the case for all ports currently maintained, but could change
+ * in the future.
+ *
+ * In an autoconf build, this runs `make install`.
+ *
+ * @param[toolchain] The toolchain used for this build.
+ * @param[buildDirectory] The directory containing build artifacts.
+ * @param[installDirectory] The destination directory for this package's
+ * installed headers and libraries.
+ * @return A [Result<Unit, String>][Result] describing the result of the
+ * operation. On failure, [Result.Error<String>][Result.Error] containing an
+ * error message is returned.
+ */
open fun install(
toolchain: Toolchain,
buildDirectory: File,
diff --git a/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt b/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
index cac9acd..1a58f5a 100644
--- a/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
+++ b/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt
@@ -212,8 +212,8 @@ class PrefabPackageBuilder(
}
private fun createArchive() {
- val archive = directory.resolve("${port.name}.aar")
- val pomFile = directory.resolve("${port.name}.pom")
+ val archive = directory.resolve("${port.name}-${port.mavenVersion}.aar")
+ val pomFile = directory.resolve("${port.name}-${port.mavenVersion}.pom")
createZipFromDirectory(archive, packageDirectory)
createPom(pomFile)
if (publishToMavenLocal) {