1 /*
<lambda>null2 * 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 okhttp3.OkHttpClient
20 import okhttp3.Request
21 import java.io.File
22 import java.io.FileOutputStream
23
24 @Suppress("unused")
25 fun executeProcessStep(
26 args: List<String>,
27 workingDirectory: File,
28 additionalEnvironment: Map<String, String>? = null
29 ): Result<Unit, String> {
30 val pb = ProcessBuilder(args)
31 .redirectOutput(ProcessBuilder.Redirect.INHERIT)
32 .redirectError(ProcessBuilder.Redirect.INHERIT)
33 .directory(workingDirectory)
34
35 if (additionalEnvironment != null) {
36 pb.environment().putAll(additionalEnvironment)
37 }
38
39 return pb.start()
40 .waitFor().let {
41 if (it == 0) {
42 Result.Ok(Unit)
43 } else {
44 Result.Error("Process failed with exit code $it")
45 }
46 }
47 }
48
installDirectoryForPortnull49 fun installDirectoryForPort(
50 name: String,
51 workingDirectory: File,
52 toolchain: Toolchain
53 ): File = workingDirectory.parentFile.resolve("$name/install/${toolchain.abi}")
54
55 data class Module(
56 val name: String,
57 val includesPerAbi: Boolean = false,
58 val dependencies: List<String> = emptyList()
59 )
60
61 abstract class Port {
62 abstract val name: String
63 abstract val version: String
64 open val prefabVersion: CMakeCompatibleVersion
65 get() = CMakeCompatibleVersion.parse(version)
66 open val mavenVersion: String
67 get() = version
68
69 abstract val url: String
70
71 open val licensePath: String = "LICENSE"
72
73 abstract val license: License
74
75 open val dependencies: List<String> = emptyList()
76 abstract val modules: List<Module>
77
78 protected val ncpus = Runtime.getRuntime().availableProcessors()
79
80 fun run(
81 toolchain: Toolchain,
82 sourceDirectory: File,
83 buildDirectory: File,
84 installDirectory: File,
85 workingDirectory: File
86 ): Result<Unit, String> {
87 configure(
88 toolchain,
89 sourceDirectory,
90 buildDirectory,
91 installDirectory,
92 workingDirectory
93 ).onFailure { return Result.Error(it) }
94
95 build(toolchain, buildDirectory).onFailure { return Result.Error(it) }
96
97 install(
98 toolchain,
99 buildDirectory,
100 installDirectory
101 ).onFailure { return Result.Error(it) }
102
103 return Result.Ok(Unit)
104 }
105
106 open fun fetchSource(
107 sourceDirectory: File,
108 workingDirectory: File
109 ): Result<Unit, String> {
110 val file = workingDirectory.resolve(File(url).name)
111
112 val client = OkHttpClient()
113 val request = Request.Builder().url(url).build()
114 client.newCall(request).execute().use { response ->
115 if (!response.isSuccessful) {
116 return Result.Error("Failed to download $url")
117 }
118
119 val body = response.body ?: throw RuntimeException(
120 "Expected non-null response body for $url"
121 )
122 FileOutputStream(file).use { output ->
123 body.byteStream().use { input ->
124 input.copyTo(output)
125 }
126 }
127 }
128
129 sourceDirectory.mkdirs()
130 return executeProcessStep(
131 listOf(
132 "tar",
133 "xf",
134 file.absolutePath,
135 "--strip-components=1"
136 ), sourceDirectory
137 )
138 }
139
140 open fun configure(
141 toolchain: Toolchain,
142 sourceDirectory: File,
143 buildDirectory: File,
144 installDirectory: File,
145 workingDirectory: File
146 ): Result<Unit, String> = Result.Ok(Unit)
147
148 open fun build(
149 toolchain: Toolchain,
150 buildDirectory: File
151 ): Result<Unit, String> = Result.Ok(Unit)
152
153 open fun install(
154 toolchain: Toolchain,
155 buildDirectory: File,
156 installDirectory: File
157 ): Result<Unit, String> = Result.Ok(Unit)
158 }