1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.ndkports
18
19 import com.github.ajalt.clikt.core.CliktCommand
20 import com.github.ajalt.clikt.parameters.arguments.argument
21 import com.github.ajalt.clikt.parameters.arguments.multiple
22 import com.github.ajalt.clikt.parameters.arguments.validate
23 import com.github.ajalt.clikt.parameters.options.convert
24 import com.github.ajalt.clikt.parameters.options.default
25 import com.github.ajalt.clikt.parameters.options.flag
26 import com.github.ajalt.clikt.parameters.options.option
27 import com.github.ajalt.clikt.parameters.options.required
28 import com.github.ajalt.clikt.parameters.types.file
29 import de.swirtz.ktsrunner.objectloader.KtsObjectLoader
30 import java.io.File
31 import java.io.FileNotFoundException
32 import java.lang.RuntimeException
33 import kotlin.system.exitProcess
34
35 class Cli : CliktCommand(help = "ndkports") {
36 private val outDir: File by option(
37 "-o",
38 "--out",
39 help = "Build directory."
40 ).file().default(File("out"))
41
42 private val publishToMavenLocal: Boolean by option(
43 help = "Publish AARs to the local Maven repository (~/.m2/repository)"
44 ).flag()
45
46 private val packages: List<String> by argument(
47 help = "Names of packages to build."
<lambda>null48 ).multiple().validate {
49 require(it.isNotEmpty()) { "must provide at least one package" }
50 }
51
<lambda>null52 private val ndk: Ndk by option().convert { Ndk(File(it)) }.required()
53
portDirectoryFornull54 private fun portDirectoryFor(name: String): File =
55 File("ports").resolve(name)
56
57 private fun loadPort(name: String): Port {
58 val portDir = portDirectoryFor(name).also {
59 if (!it.exists()) {
60 throw FileNotFoundException("Could not find ${it.path}")
61 }
62 }
63
64 val portFile = portDir.resolve("port.kts").also {
65 if (!it.exists()) {
66 throw FileNotFoundException("Could not find ${it.path}")
67 }
68 }
69
70 return KtsObjectLoader().load(portFile.reader())
71 }
72
runnull73 override fun run() {
74 println("Building packages: ${packages.joinToString(", ")}")
75 val portsByName = packages.map { loadPort(it) }.associateBy { it.name }
76 for (port in portsByName.values) {
77 val workingDirectory =
78 outDir.resolve(port.name).also { it.mkdirs() }
79
80 val sourceDirectory = workingDirectory.resolve("src")
81 val sourceTarball =
82 portDirectoryFor(port.name).resolve("src.tar.gz")
83
84 port.extractSource(sourceTarball, sourceDirectory, workingDirectory)
85
86 val apiForAbi = mapOf(
87 Abi.Arm to 16,
88 Abi.Arm64 to 21,
89 Abi.X86 to 16,
90 Abi.X86_64 to 21
91 )
92 for (abi in Abi.values()) {
93 val api = apiForAbi.getOrElse(abi) {
94 throw RuntimeException(
95 "No API level specified for ${abi.abiName}"
96 )
97 }
98 val toolchain = Toolchain(ndk, abi, api)
99
100 val buildDirectory = workingDirectory.resolve("build/$abi")
101 val installDirectory = installDirectoryForPort(
102 port.name, workingDirectory, toolchain
103 )
104
105 port.run(
106 toolchain,
107 sourceDirectory,
108 buildDirectory,
109 installDirectory,
110 workingDirectory
111 ).onFailure {
112 println(it)
113 exitProcess(1)
114 }
115 }
116
117 PrefabPackageBuilder(
118 port,
119 workingDirectory,
120 sourceDirectory,
121 publishToMavenLocal,
122 ndk,
123 apiForAbi,
124 portsByName
125 ).build()
126 }
127 }
128 }
129
mainnull130 fun main(args: Array<String>) {
131 Cli().main(args)
132 }