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
loadPortnull54 private fun loadPort(name: String): Port {
55 val portDir = File("ports").resolve(name).also {
56 if (!it.exists()) {
57 throw FileNotFoundException("Could not find ${it.path}")
58 }
59 }
60
61 val portFile = portDir.resolve("port.kts").also {
62 if (!it.exists()) {
63 throw FileNotFoundException("Could not find ${it.path}")
64 }
65 }
66
67 return KtsObjectLoader().load(portFile.reader())
68 }
69
runnull70 override fun run() {
71 println("Building packages: ${packages.joinToString(", ")}")
72 val portsByName = packages.map { loadPort(it) }.associateBy { it.name }
73 for (port in portsByName.values) {
74 val workingDirectory =
75 outDir.resolve(port.name).also { it.mkdirs() }
76 val sourceDirectory = workingDirectory.resolve("src")
77
78 port.fetchSource(sourceDirectory, workingDirectory).onFailure {
79 println(it)
80 exitProcess(1)
81 }
82
83 val apiForAbi = mapOf(
84 Abi.Arm to 16,
85 Abi.Arm64 to 21,
86 Abi.X86 to 16,
87 Abi.X86_64 to 21
88 )
89 for (abi in Abi.values()) {
90 val api = apiForAbi.getOrElse(abi) {
91 throw RuntimeException(
92 "No API level specified for ${abi.abiName}"
93 )
94 }
95 val toolchain = Toolchain(ndk, abi, api)
96
97 val buildDirectory = workingDirectory.resolve("build/$abi")
98 val installDirectory = installDirectoryForPort(
99 port.name, workingDirectory, toolchain
100 )
101
102 port.run(
103 toolchain,
104 sourceDirectory,
105 buildDirectory,
106 installDirectory,
107 workingDirectory
108 ).onFailure {
109 println(it)
110 exitProcess(1)
111 }
112 }
113
114 PrefabPackageBuilder(
115 port,
116 workingDirectory,
117 sourceDirectory,
118 publishToMavenLocal,
119 ndk,
120 apiForAbi,
121 portsByName
122 ).build()
123 }
124 }
125 }
126
mainnull127 fun main(args: Array<String>) {
128 Cli().main(args)
129 }