diff --git a/README.md b/README.md index a8c53cd..fc2a291 100644 --- a/README.md +++ b/README.md @@ -35,8 +35,6 @@ Libraries built with different NDK versions should not be used in the same appli Run unit tests provided by upstream packages. -Figure out proper way to deliver per ABI headers. - ## Ports #### [GNU FriBidi](https://github.com/fribidi/fribidi) diff --git a/buildSrc/src/main/kotlin/com/android/ndkports/PortTask.kt b/buildSrc/src/main/kotlin/com/android/ndkports/PortTask.kt index 44afae5..87e5d3b 100644 --- a/buildSrc/src/main/kotlin/com/android/ndkports/PortTask.kt +++ b/buildSrc/src/main/kotlin/com/android/ndkports/PortTask.kt @@ -125,93 +125,9 @@ abstract class PortTask(objects: ObjectFactory) : DefaultTask() { installDirectory = installDirectoryFor(abi), generatedDirectoryFor(abi) ) - migrateConfigFiles(abi) } } - private fun migrateConfigFiles(abi: Abi) { - val installDirectory = installDirectoryFor(abi) - val generatedDirectory = generatedDirectoryFor(abi) - - val srcDir = installDirectory.resolve("lib") - val dstDir = installDirectory.resolve("include/android.${abi.abiName}/lib").apply { mkdirs() } - - val ndkPathAbsolute = ndkPath.asFile.get().absolutePath - - listOf( - srcDir.resolve("cmake"), - srcDir.resolve("pkgconfig") - ).forEach { dir -> - dir.walkTopDown().forEach { - val dst = dstDir.resolve(it.relativeTo(srcDir)) - if (it.isDirectory) { - dst.mkdir() - } else if (it.isFile && it.extension in listOf("cmake", "pc")) { - dst.writeText( - it.readText() - .replace(installDirectory.absolutePath, "/__PREFAB__PACKAGE__PATH__") - .replace(generatedDirectory.absolutePath, "/__PREFAB__PACKAGE__PATH__") - .replace(ndkPathAbsolute, "/__NDK__PATH__") - ) - } - - // Some dependencies link against static libraries, - // but don't pick up private dependencies - if (libraryType.get() == LibraryType.Static && it.isFile && it.extension == "pc") { - val sb = StringBuilder() - val libs = mutableListOf() - val libsPrivate = mutableListOf() - val requires = mutableListOf() - val requiresPrivate = mutableListOf() - dst.readLines().forEach { line -> - if (line.startsWith(prefix = "Libs:", ignoreCase = true)) { - libs.add(line.substring("Libs:".length)) - } - else if (line.startsWith(prefix = "Libs.private:", ignoreCase = true)) { - libsPrivate.add(line.substring("Libs.private:".length)) - } - else if (line.startsWith(prefix = "Requires:", ignoreCase = true)) { - requires.add(line.substring("Requires:".length)) - } - else if (line.startsWith(prefix = "Requires.private:", ignoreCase = true)) { - requiresPrivate.add(line.substring("Requires.private:".length)) - } - else { - sb.appendLine(line) - } - } - (libs + libsPrivate).joinToString(" ").trim().let { libsWithPrivates -> - if (libsWithPrivates.isNotEmpty()) { - sb.appendLine("Libs: $libsWithPrivates") - } - } - (requires + requiresPrivate).joinToString(" ").trim().let { requiresWithPrivates -> - if (requiresWithPrivates.isNotEmpty()) { - sb.appendLine("Requires: $requiresWithPrivates") - } - } - dst.writeText(sb.toString()) - } - } - } - - (srcDir.listFiles { file -> file.extension == "la" } ?: arrayOf()).forEach { - dstDir.resolve(it.relativeTo(srcDir)).writeText( - it.readText() - .replace(installDirectory.absolutePath, "/__PREFAB__PACKAGE__PATH__") - .replace(generatedDirectory.absolutePath, "/__PREFAB__PACKAGE__PATH__") - .replace(ndkPathAbsolute, "/__NDK__PATH__") - ) - } - - // Remove empty dirs - installDirectory.resolve("include/android.${abi.abiName}").walkBottomUp() - .filter { it.isDirectory && it.listFiles().isNullOrEmpty() } - .forEach { - it.delete() - } - } - abstract fun buildForAbi( toolchain: Toolchain, portDirectory: File, diff --git a/buildSrc/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt b/buildSrc/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt index 5a6dc94..df246ff 100644 --- a/buildSrc/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt +++ b/buildSrc/src/main/kotlin/com/android/ndkports/PrefabPackageBuilder.kt @@ -62,7 +62,7 @@ data class ModuleDescription( class PrefabPackageBuilder( private val packageData: PackageData, private val packageDirectory: File, - private val directory: File, + private val installDirectory: File, private val sourceDirectory: File, private val ndk: Ndk, ) { @@ -106,14 +106,11 @@ class PrefabPackageBuilder( private fun installLibForAbi(module: ModuleDescription, abi: Abi, libsDir: File) { val extension = if (module.static) "a" else "so" val libName = "lib${module.name}.${extension}" - val installDirectory = libsDir.resolve("android.${abi.abiName}").apply { - mkdirs() - } + val dstDir = libsDir.resolve("android.${abi.abiName}") - directory.resolve("$abi/lib/$libName") - .copyTo(installDirectory.resolve(libName)) + installDirectory.resolve("$abi/lib/$libName").copyTo(dstDir.resolve(libName)) - installDirectory.resolve("abi.json").writeText( + dstDir.resolve("abi.json").writeText( Json.encodeToString( AndroidAbiMetadata( abi = abi.abiName, @@ -152,7 +149,7 @@ class PrefabPackageBuilder( } private fun installAssets() { - val sourceAssets = directory.parentFile.parentFile.resolve("assets") + val sourceAssets = installDirectory.parentFile.parentFile.resolve("assets") if (sourceAssets.exists()) { sourceAssets.copyRecursively(assetsDirectory) } @@ -167,38 +164,34 @@ class PrefabPackageBuilder( } makeModuleMetadata(module, moduleDirectory) - Abi.values().forEach { abi -> - val includeDir = directory.resolve("${abi}/include") - if (module.includesPerAbi) { - val destination = moduleDirectory.resolve("include/android.${abi.abiName}").apply { mkdir() } - val commonHeaders = includeDir.listFiles { _, name -> !Abi.values().map { "android.${it.abiName}" }.contains(name) } ?: arrayOf() - val perAbiHeaders = includeDir.resolve("android.${abi.abiName}").listFiles() ?: arrayOf() - (commonHeaders + perAbiHeaders).forEach { - it.copyRecursively(destination.resolve(it.name)) - } - } else { - val destination = moduleDirectory.resolve("include").apply { mkdir() } - includeDir.copyRecursively(destination) { file, exception -> - if (exception !is FileAlreadyExistsException) { - throw exception - } - if (!file.readBytes().contentEquals(exception.file.readBytes())) { - val path = file.relativeTo(destination) - throw RuntimeException( - "Found duplicate headers with non-equal contents: $path" - ) - } - - OnErrorAction.SKIP - } + val libsDir = moduleDirectory.resolve("libs").apply { mkdir() } + for (abi in Abi.values()) { + libsDir.resolve("android.${abi.abiName}").apply { mkdir() } + installConfigForAbi(module, abi, libsDir) + if (!module.headerOnly) { + installLibForAbi(module, abi, libsDir) } } - if (!module.headerOnly) { - val libsDir = moduleDirectory.resolve("libs").apply { mkdirs() } - for (abi in Abi.values()) { - installLibForAbi(module, abi, libsDir) + Abi.values().forEach { abi -> + val destination = if (module.includesPerAbi) { + libsDir.resolve("android.${abi.abiName}").apply{ mkdir() }.resolve("include").apply { mkdir() } + } else { + moduleDirectory.resolve("include").apply { mkdir() } + } + installDirectory.resolve("${abi}/include").copyRecursively(destination) { file, exception -> + if (exception !is FileAlreadyExistsException) { + throw exception + } + + if (!file.readBytes().contentEquals(exception.file.readBytes())) { + val path = file.relativeTo(destination) + throw RuntimeException( + "Found duplicate headers with non-equal contents: $path" + ) + } + OnErrorAction.SKIP } } } @@ -209,4 +202,78 @@ class PrefabPackageBuilder( createAndroidManifest() } + + private fun installConfigForAbi(module: ModuleDescription, abi: Abi, libsDir: File) { + val srcDir = installDirectory.resolve("$abi/lib") + val dstDir = libsDir.resolve("android.${abi.abiName}") + + val abiInstallDir = installDirectory.resolve("$abi") + val generatedDir = installDirectory.resolve("../dependencies/generated/${abi.triple}").absoluteFile + + listOf( + srcDir.resolve("cmake"), + srcDir.resolve("pkgconfig") + ).forEach { dir -> + dir.walkTopDown().forEach { + val dst = dstDir.resolve(it.relativeTo(srcDir)) + if (it.isDirectory) { + dst.mkdir() + } else if (it.isFile && it.extension in listOf("cmake", "pc")) { + dst.writeText( + it.readText() + .replace(abiInstallDir.absolutePath, "/__PREFAB__PACKAGE__PATH__") + .replace(generatedDir.absolutePath, "/__PREFAB__PACKAGE__PATH__") + .replace(ndk.path.absolutePath, "/__NDK__PATH__") + ) + } + + // Some dependencies link against static libraries, + // but don't pick up private dependencies + if (module.static && it.isFile && it.extension == "pc") { + val sb = StringBuilder() + val libs = mutableListOf() + val libsPrivate = mutableListOf() + val requires = mutableListOf() + val requiresPrivate = mutableListOf() + dst.readLines().forEach { line -> + if (line.startsWith(prefix = "Libs:", ignoreCase = true)) { + libs.add(line.substring("Libs:".length)) + } + else if (line.startsWith(prefix = "Libs.private:", ignoreCase = true)) { + libsPrivate.add(line.substring("Libs.private:".length)) + } + else if (line.startsWith(prefix = "Requires:", ignoreCase = true)) { + requires.add(line.substring("Requires:".length)) + } + else if (line.startsWith(prefix = "Requires.private:", ignoreCase = true)) { + requiresPrivate.add(line.substring("Requires.private:".length)) + } + else { + sb.appendLine(line) + } + } + (libs + libsPrivate).joinToString(" ").trim().let { libsWithPrivates -> + if (libsWithPrivates.isNotEmpty()) { + sb.appendLine("Libs: $libsWithPrivates") + } + } + (requires + requiresPrivate).joinToString(" ").trim().let { requiresWithPrivates -> + if (requiresWithPrivates.isNotEmpty()) { + sb.appendLine("Requires: $requiresWithPrivates") + } + } + dst.writeText(sb.toString()) + } + } + } + + (srcDir.listFiles { file -> file.extension == "la" } ?: arrayOf()).forEach { + dstDir.resolve(it.relativeTo(srcDir)).writeText( + it.readText() + .replace(abiInstallDir.absolutePath, "/__PREFAB__PACKAGE__PATH__") + .replace(generatedDir.absolutePath, "/__PREFAB__PACKAGE__PATH__") + .replace(ndk.path.absolutePath, "/__NDK__PATH__") + ) + } + } } diff --git a/buildSrc/src/main/kotlin/com/android/ndkports/PrefabSysrootPlugin.kt b/buildSrc/src/main/kotlin/com/android/ndkports/PrefabSysrootPlugin.kt index 509e29a..49c74dd 100644 --- a/buildSrc/src/main/kotlin/com/android/ndkports/PrefabSysrootPlugin.kt +++ b/buildSrc/src/main/kotlin/com/android/ndkports/PrefabSysrootPlugin.kt @@ -31,8 +31,8 @@ class PrefabSysrootPlugin( val includeDir = installDir.resolve("include").apply { mkdir() } val libDir = installDir.resolve("lib") - installHeaders(module.includePath.toFile(), includeDir, requirement.targetTriple) - migrateLibFiles(includeDir, libDir) + installHeaders(module, includeDir, requirement.targetTriple) + installConfigFiles(module, libDir, requirement.targetTriple) if (!module.isHeaderOnly) { module.getLibraryFor(requirement).path.toFile().apply { @@ -51,10 +51,9 @@ class PrefabSysrootPlugin( } } - private fun installHeaders(src: File, includeDir: File, abiTriple: String) { - val commonHeaders = src.listFiles { _, name -> !Abi.values().map { "android.${it.abiName}" }.contains(name) } ?: arrayOf() - val perAbiHeaders = src.resolve("android.${targetTripleToAbiName(abiTriple)}").listFiles() ?: arrayOf() - + private fun installHeaders(module: Module, includeDir: File, abiTriple: String) { + val commonHeaders = module.includePath.toFile().listFiles() ?: arrayOf() + val perAbiHeaders = module.path.toFile().resolve("libs/android.${abiTriple}/include").listFiles() ?: arrayOf() (commonHeaders + perAbiHeaders).forEach { it.copyRecursively(includeDir.resolve(it.name)) { file, exception -> if (exception !is FileAlreadyExistsException) { @@ -73,24 +72,25 @@ class PrefabSysrootPlugin( } } - private fun migrateLibFiles(includeDir: File, libDir: File) { - includeDir.resolve("lib").let { - if (it.exists()) { - it.copyRecursively(libDir) { file, exception -> - if (exception !is FileAlreadyExistsException) { - throw exception - } - - if (!file.readBytes().contentEquals(exception.file.readBytes())) { - val path = file.relativeTo(includeDir) - throw RuntimeException( - "Found duplicate headers with non-equal contents: $path" - ) - } - - OnErrorAction.SKIP + private fun installConfigFiles(module: Module, libDir: File, abiTriple: String) { + val src = module.path.toFile().resolve("libs/android.${targetTripleToAbiName(abiTriple)}") + + src.listFiles { file, filename -> + listOf("cmake", "pkgconfig").contains(filename) || file.extension == "la" + }?.forEach { + it.copyRecursively(libDir.resolve(it.name)) { file, exception -> + if (exception !is FileAlreadyExistsException) { + throw exception + } + + if (!file.readBytes().contentEquals(exception.file.readBytes())) { + val path = file.relativeTo(src) + throw RuntimeException( + "Found duplicate headers with non-equal contents: $path" + ) } - it.deleteRecursively() + + OnErrorAction.SKIP } } }