// Defines logic for: // - embedding symbols_table/debug symbols into the bundle. // - for creating symbols zip with files having .so extension // UnityLibrary has to be evaluated first, so we could find buildIl2Cpp task evaluationDependsOn(':unityLibrary') def insertCopyInfo(Hashtable map, String targetDirectory, String extension, File sourceFile) { def abi = sourceFile.getParentFile().getName(); def fileName = sourceFile.getName(); def targetAbi = file(targetDirectory).toPath().resolve(abi) def dst = targetAbi.resolve(fileName + extension).toString() map.put(sourceFile.getAbsolutePath(), dst) } def constructCopyInfoForUnitySymbols(Project unityLibrary, String targetDirectory, String extension, Task buildIl2CppTask) { def unityLibraryRoot = unityLibrary.projectDir.toPath() def unitySymbols = unityLibraryRoot.resolve('symbols') // Note: libil2cpp.so might not yet exist, thus querying directory won't return libil2cpp.so def files = fileTree(unitySymbols) def result = new Hashtable() for (File f: files) { insertCopyInfo(result, targetDirectory, extension, f) } if (buildIl2CppTask != null) { buildIl2CppTask.outputs.files.each { it -> String path = it.toString() if (!path.contains(unitySymbols.toString())) return; insertCopyInfo(result, targetDirectory, extension, it) } } return result } def setupSymbols(String configName, String symbolType, String extension) { def dependee = tasks.findByName("extract${configName}Native${symbolType}"); if (dependee == null) return; def unityLibrary = project(':unityLibrary') def buildIl2CppTask = unityLibrary.tasks.findByName('buildIl2Cpp') def copyTaskName = "copy${configName}Unity${symbolType}"; def copyInfo = constructCopyInfoForUnitySymbols(unityLibrary, dependee.outputs.files.asPath, extension, buildIl2CppTask) def task = tasks.register(copyTaskName) { for (def c : copyInfo) { inputs.file c.key outputs.file c.value } doLast { def rootIdx = projectDir.getParent().toString().length() + 1; println "Copying Unity symbols: " for (def c : copyInfo) { println " ${c.key.substring(rootIdx)} -> ${c.value.substring(rootIdx)}" ant.copy(tofile: c.value, file: c.key) } } } if (buildIl2CppTask != null) task.get().dependsOn buildIl2CppTask // 'copy{configName}Unity{symbolType}' must be executed after 'extract${configName}Native${symbolType}' task // In case 'extract${configName}Native${symbolType}' produces same files as 'copy{configName}Unity{symbolType}' dependee.finalizedBy copyTaskName // native-debug-symbols.zip depends on 'copy{configName}Unity{symbolType}' task def mergeNativeDebugMetadataTask = tasks.findByName("merge${configName}NativeDebugMetadata"); if (mergeNativeDebugMetadataTask != null) mergeNativeDebugMetadataTask.dependsOn copyTaskName; // 'copy{configName}Unity{symbolType}' must be executed after 'package{configName}Bundle' def packageBundleTask = tasks.findByName("package${configName}Bundle"); if (packageBundleTask != null) packageBundleTask.dependsOn copyTaskName; } def createMergeNativeDebugMetadataSoTask(String configName, String symbolType) { def extractNativeSymbols = tasks.findByName("extract${configName}Native${symbolType}"); if (extractNativeSymbols == null) return; def copyUnitySymbolsTaskName = "copy${configName}Unity${symbolType}"; def copyUnitySymbolsTask = tasks.findByName(copyUnitySymbolsTaskName); tasks.register("merge${configName}NativeDebugMetadataSo", Zip) { dependsOn extractNativeSymbols, copyUnitySymbolsTask from extractNativeSymbols.outputs.files.asPath archiveFileName = "native-debug-symbols-so.zip" destinationDirectory = file(tasks.findByName("merge${configName}NativeDebugMetadata").outputs.files.asPath).getParentFile() rename '(.*\\.so)(.*)', '$1' } } afterEvaluate { def dbgLevel = project.android.defaultConfig.ndk.debugSymbolLevel == null ? "none" : project.android.defaultConfig.ndk.debugSymbolLevel.toString().toLowerCase(); if (dbgLevel.equals("none")) return; def symbolType = "SymbolTables"; def symbolExt = ".sym"; if (dbgLevel.equals("full")) { symbolType = "DebugMetadata"; symbolExt = ".dbg"; } android.buildTypes.configureEach { buildType -> // Turn 'debug' into 'Debug', 'release' into 'Release' var c = buildType.name.substring(0, 1).toUpperCase() + buildType.name.substring(1) setupSymbols(c, symbolType, symbolExt); createMergeNativeDebugMetadataSoTask(c, symbolType) } }