blob: 2e0433f0c75a00a145072830ffaee3d105a1fa10 [file] [log] [blame]
Dan Albertdca0d722019-07-16 14:03:43 -07001/*
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
17package com.android.ndkports
18
Dan Albertdca0d722019-07-16 14:03:43 -070019import java.io.File
Dan Albertdca0d722019-07-16 14:03:43 -070020
21@Suppress("unused")
22fun executeProcessStep(
23 args: List<String>,
24 workingDirectory: File,
25 additionalEnvironment: Map<String, String>? = null
26): Result<Unit, String> {
27 val pb = ProcessBuilder(args)
28 .redirectOutput(ProcessBuilder.Redirect.INHERIT)
29 .redirectError(ProcessBuilder.Redirect.INHERIT)
30 .directory(workingDirectory)
31
32 if (additionalEnvironment != null) {
33 pb.environment().putAll(additionalEnvironment)
34 }
35
36 return pb.start()
37 .waitFor().let {
38 if (it == 0) {
39 Result.Ok(Unit)
40 } else {
41 Result.Error("Process failed with exit code $it")
42 }
43 }
44}
45
46fun installDirectoryForPort(
47 name: String,
48 workingDirectory: File,
49 toolchain: Toolchain
50): File = workingDirectory.parentFile.resolve("$name/install/${toolchain.abi}")
51
Dan Alberta3fd28e2020-05-19 16:11:16 -070052/**
53 * A module exported by the package.
54 *
55 * As currently implemented by ndkports, one module is exactly one library.
56 * Prefab supports header-only libraries, but ndkports does not support these
57 * yet.
58 *
59 * Static libraries are not currently supported by ndkports.
60 *
61 * @property[name] The name of the module. Note that currently the name of the
62 * installed library file must be exactly `lib$name.so`.
63 * @property[includesPerAbi] Set to true if a different set of headers should be
64 * exposed per-ABI. Not currently implemented.
65 * @property[dependencies] A list of other modules required by this module, in
66 * the format described by https://google.github.io/prefab/.
67 */
Dan Albertdca0d722019-07-16 14:03:43 -070068data class Module(
69 val name: String,
70 val includesPerAbi: Boolean = false,
71 val dependencies: List<String> = emptyList()
72)
73
Dan Alberta3fd28e2020-05-19 16:11:16 -070074/**
75 * The base class for all ports.
76 */
Dan Albertdca0d722019-07-16 14:03:43 -070077abstract class Port {
Dan Alberta3fd28e2020-05-19 16:11:16 -070078 /**
79 * The name of the port. Will be used as the package name in prefab.json.
80 */
Dan Albertdca0d722019-07-16 14:03:43 -070081 abstract val name: String
Dan Alberta3fd28e2020-05-19 16:11:16 -070082
83 /**
84 * The version of the package.
85 *
86 * Used as the default for [prefabVersion] and [mavenVersion] when
87 * appropriate.
88 */
Dan Albertdca0d722019-07-16 14:03:43 -070089 abstract val version: String
Dan Alberta3fd28e2020-05-19 16:11:16 -070090
91 /**
92 * The version to encode in the prefab.json.
93 *
94 * This version must be compatible with CMake's `find_package` for
95 * config-style packages. This means that it must be one to four decimal
96 * separated integers. No other format is allowed.
97 *
98 * If not set, the default is [version] as interpreted by
99 * [CMakeCompatibleVersion.parse].
100 *
101 * For example, OpenSSL 1.1.1g will set this value to
102 * `CMakeCompatibleVersion(1, 1, 1, 7)`.
103 */
Dan Albertdca0d722019-07-16 14:03:43 -0700104 open val prefabVersion: CMakeCompatibleVersion
105 get() = CMakeCompatibleVersion.parse(version)
Dan Alberta3fd28e2020-05-19 16:11:16 -0700106
107 /**
108 * The version to use for the maven package.
109 *
110 * This field allows versioning the maven package differently from the
111 * package itself, which is sometimes necessary given CMake's strict version
112 * format requirements.
113 *
114 * If not set, the default is [version].
115 *
116 * For example, this could be set to `"$name-$version-alpha-1"` to
117 * distribute an alpha of the package.
118 */
Dan Albertdca0d722019-07-16 14:03:43 -0700119 open val mavenVersion: String
120 get() = version
121
Dan Alberta3fd28e2020-05-19 16:11:16 -0700122 /**
123 * The relative path to the license file of this package.
124 *
125 * This file will be packaged in the AAR in the META-INF directory.
126 */
Dan Albertdca0d722019-07-16 14:03:43 -0700127 open val licensePath: String = "LICENSE"
128
Dan Alberta3fd28e2020-05-19 16:11:16 -0700129 /**
130 * A description of the license (name and URL) for use in the pom.xml.
131 */
Dan Albertdca0d722019-07-16 14:03:43 -0700132 abstract val license: License
133
Dan Alberta3fd28e2020-05-19 16:11:16 -0700134 /**
135 * A list of dependencies for this package.
136 *
137 * For example, curl depends on `listOf("openssl")`.
138 */
Dan Albertdca0d722019-07-16 14:03:43 -0700139 open val dependencies: List<String> = emptyList()
Dan Alberta3fd28e2020-05-19 16:11:16 -0700140
141 /**
142 * A list of modules exported by this package.
143 */
Dan Albertdca0d722019-07-16 14:03:43 -0700144 abstract val modules: List<Module>
145
Dan Alberta3fd28e2020-05-19 16:11:16 -0700146 /**
147 * The number of CPUs available for building.
148 *
149 * May be passed to the build system if required.
150 */
Dan Albertdca0d722019-07-16 14:03:43 -0700151 protected val ncpus = Runtime.getRuntime().availableProcessors()
152
153 fun run(
154 toolchain: Toolchain,
155 sourceDirectory: File,
156 buildDirectory: File,
157 installDirectory: File,
158 workingDirectory: File
159 ): Result<Unit, String> {
160 configure(
161 toolchain,
162 sourceDirectory,
163 buildDirectory,
164 installDirectory,
165 workingDirectory
166 ).onFailure { return Result.Error(it) }
167
168 build(toolchain, buildDirectory).onFailure { return Result.Error(it) }
169
170 install(
171 toolchain,
172 buildDirectory,
173 installDirectory
174 ).onFailure { return Result.Error(it) }
175
176 return Result.Ok(Unit)
177 }
178
Dan Alberta3fd28e2020-05-19 16:11:16 -0700179 /**
180 * Overridable build step for extracting the source package.
181 *
182 * @param[sourceTarball] The path to the source tarball.
183 * @param[sourceDirectory] The destination directory for the extracted
184 * source.
185 * @param[workingDirectory] The working top-level directory for this
186 * package.
187 * @return A [Result<Unit, String>][Result] describing the result of the
188 * operation. On failure, [Result.Error<String>][Result.Error] containing an
189 * error message is returned.
190 */
Dan Albertabf50c12020-02-03 15:51:15 -0800191 open fun extractSource(
192 sourceTarball: File,
Dan Albertdca0d722019-07-16 14:03:43 -0700193 sourceDirectory: File,
194 workingDirectory: File
195 ): Result<Unit, String> {
Dan Albertdca0d722019-07-16 14:03:43 -0700196 sourceDirectory.mkdirs()
197 return executeProcessStep(
198 listOf(
199 "tar",
200 "xf",
Dan Albertabf50c12020-02-03 15:51:15 -0800201 sourceTarball.absolutePath,
Dan Albertdca0d722019-07-16 14:03:43 -0700202 "--strip-components=1"
203 ), sourceDirectory
204 )
205 }
206
Dan Alberta3fd28e2020-05-19 16:11:16 -0700207 /**
208 * Overridable build step for configuring the build.
209 *
210 * Any pre-build steps should be run here.
211 *
212 * In an autoconf build, this runs `configure`.
213 *
214 * @param[toolchain] The toolchain used for this build.
215 * @param[sourceDirectory] The directory containing the extracted package
216 * source.
217 * @param[buildDirectory] The directory to use for building.
218 * @param[installDirectory] The destination directory for this package's
219 * installed headers and libraries.
220 * @param[workingDirectory] The top-level working directory for this
221 * package.
222 * @return A [Result<Unit, String>][Result] describing the result of the
223 * operation. On failure, [Result.Error<String>][Result.Error] containing an
224 * error message is returned.
225 */
Dan Albertdca0d722019-07-16 14:03:43 -0700226 open fun configure(
227 toolchain: Toolchain,
228 sourceDirectory: File,
229 buildDirectory: File,
230 installDirectory: File,
231 workingDirectory: File
232 ): Result<Unit, String> = Result.Ok(Unit)
233
Dan Alberta3fd28e2020-05-19 16:11:16 -0700234 /**
235 * Overridable build step for building the package.
236 *
237 * In an autoconf build, this runs `make`.
238 *
239 * @param[toolchain] The toolchain used for this build.
240 * @param[buildDirectory] The directory to use for building.
241 * @return A [Result<Unit, String>][Result] describing the result of the
242 * operation. On failure, [Result.Error<String>][Result.Error] containing an
243 * error message is returned.
244 */
Dan Albertdca0d722019-07-16 14:03:43 -0700245 open fun build(
246 toolchain: Toolchain,
247 buildDirectory: File
248 ): Result<Unit, String> = Result.Ok(Unit)
249
Dan Alberta3fd28e2020-05-19 16:11:16 -0700250 /**
251 * Overridable build step for installing built artifacts for packaging.
252 *
253 * The install step is expected to install headers and libraries to the
254 * [installDirectory] with the following layout:
255 *
256 * [installDirectory]
257 * include/
258 * <package headers>
259 * lib/
260 * <package libraries>
261 *
262 * A matching `lib${module.name}.so` must be present in the `lib` directory
263 * for every item in [modules].
264 *
265 * Note that it is expected for all modules to use the same headers. This is
266 * currently the case for all ports currently maintained, but could change
267 * in the future.
268 *
269 * In an autoconf build, this runs `make install`.
270 *
271 * @param[toolchain] The toolchain used for this build.
272 * @param[buildDirectory] The directory containing build artifacts.
273 * @param[installDirectory] The destination directory for this package's
274 * installed headers and libraries.
275 * @return A [Result<Unit, String>][Result] describing the result of the
276 * operation. On failure, [Result.Error<String>][Result.Error] containing an
277 * error message is returned.
278 */
Dan Albertdca0d722019-07-16 14:03:43 -0700279 open fun install(
280 toolchain: Toolchain,
281 buildDirectory: File,
282 installDirectory: File
283 ): Result<Unit, String> = Result.Ok(Unit)
284}