diff --git a/platform/android/SCsub b/platform/android/SCsub index f5258a5497c..a8361750039 100644 --- a/platform/android/SCsub +++ b/platform/android/SCsub @@ -51,9 +51,9 @@ if lib_arch_dir != "": if env["target"] == "release": lib_type_dir = "release" elif env["target"] == "release_debug": - lib_type_dir = "release_debug" - else: # debug lib_type_dir = "debug" + else: # debug + lib_type_dir = "dev" if env["tools"]: lib_tools_dir = "tools/" diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index 47026798d1b..4a89ee7f62f 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -42,6 +42,11 @@ allprojects { } } +configurations { + // Initializes a placeholder for the devImplementation dependency configuration. + devImplementation {} +} + dependencies { implementation libraries.kotlinStdLib implementation libraries.androidxFragment @@ -54,6 +59,7 @@ dependencies { // Custom build mode. In this scenario this project is the only one around and the Godot // library is available through the pre-generated godot-lib.*.aar android archive files. debugImplementation fileTree(dir: 'libs/debug', include: ['*.jar', '*.aar']) + devImplementation fileTree(dir: 'libs/dev', include: ['*.jar', '*.aar']) releaseImplementation fileTree(dir: 'libs/release', include: ['*.jar', '*.aar']) } @@ -107,7 +113,7 @@ android { minSdkVersion getExportMinSdkVersion() targetSdkVersion getExportTargetSdkVersion() - missingDimensionStrategy 'tools', 'toolsDisabled' + missingDimensionStrategy 'products', 'template' //CHUNK_ANDROID_DEFAULTCONFIG_BEGIN //CHUNK_ANDROID_DEFAULTCONFIG_END } @@ -163,6 +169,18 @@ android { } } + dev { + initWith debug + // Signing and zip-aligning are skipped for prebuilt builds, but + // performed for custom builds. + zipAlignEnabled shouldZipAlign() + if (shouldSign()) { + signingConfig signingConfigs.debug + } else { + signingConfig null + } + } + release { // Signing and zip-aligning are skipped for prebuilt builds, but // performed for custom builds. @@ -203,6 +221,11 @@ android { 'libs/debug' //DIR_JNI_DEBUG_BEGIN //DIR_JNI_DEBUG_END + ] + dev.jniLibs.srcDirs = [ + 'libs/dev' +//DIR_JNI_DEV_BEGIN +//DIR_JNI_DEV_END ] release.jniLibs.srcDirs = [ 'libs/release' @@ -224,6 +247,12 @@ task copyAndRenameDebugApk(type: Copy) { rename "android_debug.apk", getExportFilename() } +task copyAndRenameDevApk(type: Copy) { + from "$buildDir/outputs/apk/dev/android_dev.apk" + into getExportPath() + rename "android_dev.apk", getExportFilename() +} + task copyAndRenameReleaseApk(type: Copy) { from "$buildDir/outputs/apk/release/android_release.apk" into getExportPath() @@ -236,6 +265,12 @@ task copyAndRenameDebugAab(type: Copy) { rename "build-debug.aab", getExportFilename() } +task copyAndRenameDevAab(type: Copy) { + from "$buildDir/outputs/bundle/dev/build-dev.aab" + into getExportPath() + rename "build-dev.aab", getExportFilename() +} + task copyAndRenameReleaseAab(type: Copy) { from "$buildDir/outputs/bundle/release/build-release.aab" into getExportPath() diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 8f0f2c6cb68..1b2976e7152 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -103,7 +103,7 @@ ext.getGodotLibraryVersionName = { -> ext.generateGodotLibraryVersion = { List requiredKeys -> // Attempt to read the version from the `version.py` file. String libraryVersionName = "" - int libraryVersionCode = 1 + int libraryVersionCode = 0 File versionFile = new File("../../../version.py") if (versionFile.isFile()) { @@ -126,10 +126,20 @@ ext.generateGodotLibraryVersion = { List requiredKeys -> if (requiredKeys.empty) { libraryVersionName = map.values().join(".") try { - libraryVersionCode = Integer.parseInt(map["patch"]) + - (Integer.parseInt(map["minor"]) * 100) + - (Integer.parseInt(map["major"]) * 10000) - } catch (NumberFormatException ignore) {} + if (map.containsKey("patch")) { + libraryVersionCode = Integer.parseInt(map["patch"]) + } + + if (map.containsKey("minor")) { + libraryVersionCode += (Integer.parseInt(map["minor"]) * 100) + } + + if (map.containsKey("major")) { + libraryVersionCode += (Integer.parseInt(map["major"]) * 10000) + } + } catch (NumberFormatException ignore) { + libraryVersionCode = 1 + } } } @@ -137,6 +147,11 @@ ext.generateGodotLibraryVersion = { List requiredKeys -> // Fallback value in case we're unable to read the file. libraryVersionName = "custom_build" } + + if (libraryVersionCode == 0) { + libraryVersionCode = 1 + } + return [libraryVersionName, libraryVersionCode] } @@ -147,7 +162,10 @@ ext.getGodotLibraryVersion = { -> ext.getGodotPublishVersion = { -> List requiredKeys = ["major", "minor", "patch", "status"] - return generateGodotLibraryVersion(requiredKeys) + String versionName = "" + int versionCode = 1 + (versionName, versionCode) = generateGodotLibraryVersion(requiredKeys) + return versionName } final String VALUE_SEPARATOR_REGEX = "\\|" diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index 5ee63e0fc6c..e16ca65df5b 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -26,8 +26,8 @@ allprojects { ext { supportedAbis = ["armv7", "arm64v8", "x86", "x86_64"] - supportedTargets = ["release", "release_debug", "debug"] - supportedFlavors = ["toolsEnabled", "toolsDisabled"] + supportedTargetsMap = [release: "release", dev: "debug", debug: "release_debug"] + supportedFlavors = ["editor", "template"] // Used by gradle to specify which architecture to build for by default when running // `./gradlew build` (this command is usually used by Android Studio). @@ -55,6 +55,17 @@ task copyDebugBinaryToBin(type: Copy) { include('android_debug.apk') } +/** + * Copy the generated 'android_dev.apk' binary template into the Godot bin directory. + * Depends on the app build task to ensure the binary is generated prior to copying. + */ +task copyDevBinaryToBin(type: Copy) { + dependsOn ':app:assembleDev' + from('app/build/outputs/apk/dev') + into(binDir) + include('android_dev.apk') +} + /** * Copy the generated 'android_release.apk' binary template into the Godot bin directory. * Depends on the app build task to ensure the binary is generated prior to copying. @@ -71,7 +82,7 @@ task copyReleaseBinaryToBin(type: Copy) { * Depends on the library build task to ensure the AAR file is generated prior to copying. */ task copyDebugAARToAppModule(type: Copy) { - dependsOn ':lib:assembleToolsDisabledDebug' + dependsOn ':lib:assembleTemplateDebug' from('lib/build/outputs/aar') into('app/libs/debug') include('godot-lib.debug.aar') @@ -82,18 +93,40 @@ task copyDebugAARToAppModule(type: Copy) { * Depends on the library build task to ensure the AAR file is generated prior to copying. */ task copyDebugAARToBin(type: Copy) { - dependsOn ':lib:assembleToolsDisabledDebug' + dependsOn ':lib:assembleTemplateDebug' from('lib/build/outputs/aar') into(binDir) include('godot-lib.debug.aar') } +/** + * Copy the Godot android library archive dev file into the app module dev libs directory. + * Depends on the library build task to ensure the AAR file is generated prior to copying. + */ +task copyDevAARToAppModule(type: Copy) { + dependsOn ':lib:assembleTemplateDev' + from('lib/build/outputs/aar') + into('app/libs/dev') + include('godot-lib.dev.aar') +} + +/** + * Copy the Godot android library archive dev file into the root bin directory. + * Depends on the library build task to ensure the AAR file is generated prior to copying. + */ +task copyDevAARToBin(type: Copy) { + dependsOn ':lib:assembleTemplateDev' + from('lib/build/outputs/aar') + into(binDir) + include('godot-lib.dev.aar') +} + /** * Copy the Godot android library archive release file into the app module release libs directory. * Depends on the library build task to ensure the AAR file is generated prior to copying. */ task copyReleaseAARToAppModule(type: Copy) { - dependsOn ':lib:assembleToolsDisabledRelease' + dependsOn ':lib:assembleTemplateRelease' from('lib/build/outputs/aar') into('app/libs/release') include('godot-lib.release.aar') @@ -104,7 +137,7 @@ task copyReleaseAARToAppModule(type: Copy) { * Depends on the library build task to ensure the AAR file is generated prior to copying. */ task copyReleaseAARToBin(type: Copy) { - dependsOn ':lib:assembleToolsDisabledRelease' + dependsOn ':lib:assembleTemplateRelease' from('lib/build/outputs/aar') into(binDir) include('godot-lib.release.aar') @@ -112,7 +145,7 @@ task copyReleaseAARToBin(type: Copy) { /** * Generate Godot custom build template by zipping the source files from the app directory, as well - * as the AAR files generated by 'copyDebugAAR' and 'copyReleaseAAR'. + * as the AAR files generated by 'copyDebugAAR', 'copyDevAAR' and 'copyReleaseAAR'. * The zip file also includes some gradle tools to allow building of the custom build. */ task zipCustomBuild(type: Zip) { @@ -132,7 +165,13 @@ def templateExcludedBuildTask() { if (!isAndroidStudio()) { logger.lifecycle("Excluding Android studio build tasks") for (String flavor : supportedFlavors) { - for (String buildType : supportedTargets) { + for (String buildType : supportedTargetsMap.keySet()) { + if (buildType == "release" && flavor == "editor") { + // The editor can't be used with target=release as debugging tools are then not + // included, and it would crash on errors instead of reporting them. + continue + } + for (String abi : selectedAbis) { excludedTasks += ":lib:" + getSconsTaskName(flavor, buildType, abi) } @@ -146,11 +185,7 @@ def templateBuildTasks() { def tasks = [] // Only build the apks and aar files for which we have native shared libraries. - for (String target : supportedTargets) { - if (target == "release_debug") { - // 'release_debug' is not supported for generating templates. - continue - } + for (String target : supportedTargetsMap.keySet()) { File targetLibs = new File("lib/libs/" + target) if (targetLibs != null && targetLibs.isDirectory() @@ -180,21 +215,14 @@ task copyEditorDebugBinaryToBin(type: Copy) { dependsOn ':editor:assembleDebug' from('editor/build/outputs/apk/debug') into(binDir) - include('android_editor_debug.apk') + include('android_editor.apk') } -task copyEditorRelease_debugBinaryToBin(type: Copy) { - dependsOn ':editor:assembleRelease_debug' - from('editor/build/outputs/apk/release_debug') +task copyEditorDevBinaryToBin(type: Copy) { + dependsOn ':editor:assembleDev' + from('editor/build/outputs/apk/dev') into(binDir) - include('android_editor_release_debug.apk') -} - -task copyEditorReleaseBinaryToBin(type: Copy) { - dependsOn ':editor:assembleRelease' - from('editor/build/outputs/apk/release') - into(binDir) - include('android_editor_release.apk') + include('android_editor_dev.apk') } /** @@ -209,9 +237,10 @@ task generateGodotEditor { def tasks = [] - for (String target : supportedTargets) { + for (String target : supportedTargetsMap.keySet()) { if (target == "release") { - // Skip release for now since we need to provide signing information. + // The editor can't be used with target=release as debugging tools are then not + // included, and it would crash on errors instead of reporting them. continue } File targetLibs = new File("lib/libs/tools/" + target) @@ -250,7 +279,27 @@ task generateDevTemplate { } /** - * Clean the generated artifacts. + * Clean the generated editor artifacts. + */ +task cleanGodotEditor(type: Delete) { + // Delete the generated native tools libs + delete("lib/libs/tools") + + // Delete the library generated AAR files + delete("lib/build/outputs/aar") + + // Delete the generated binary apks + delete("editor/build/outputs/apk") + + // Delete the Godot editor apks in the Godot bin directory + delete("$binDir/android_editor.apk") + delete("$binDir/android_editor_dev.apk") + + finalizedBy getTasksByName("clean", true) +} + +/** + * Clean the generated template artifacts. */ task cleanGodotTemplates(type: Delete) { // Delete the generated native libs @@ -267,9 +316,11 @@ task cleanGodotTemplates(type: Delete) { // Delete the Godot templates in the Godot bin directory delete("$binDir/android_debug.apk") + delete("$binDir/android_dev.apk") delete("$binDir/android_release.apk") delete("$binDir/android_source.zip") delete("$binDir/godot-lib.debug.aar") + delete("$binDir/godot-lib.dev.aar") delete("$binDir/godot-lib.release.aar") finalizedBy getTasksByName("clean", true) diff --git a/platform/android/java/editor/build.gradle b/platform/android/java/editor/build.gradle index f5a658b7614..d95cf62cbc4 100644 --- a/platform/android/java/editor/build.gradle +++ b/platform/android/java/editor/build.gradle @@ -21,7 +21,7 @@ android { //noinspection ExpiredTargetSdkVersion - Restrict to version 29 until https://github.com/godotengine/godot/pull/51815 is submitted targetSdkVersion 29 // versions.targetSdk - missingDimensionStrategy 'tools', 'toolsEnabled' + missingDimensionStrategy 'products', 'editor' } compileOptions { @@ -30,13 +30,22 @@ android { } buildTypes { - debug { - applicationIdSuffix ".debug" + dev { + initWith debug + applicationIdSuffix ".dev" } - release_debug { - initWith debug - applicationIdSuffix ".releaseDebug" + debug { + initWith release + + // Need to swap with the release signing config when this is ready for public release. + signingConfig signingConfigs.debug + } + + release { + // This buildtype is disabled below. + // The editor can't be used with target=release only, as debugging tools are then not + // included, and it would crash on errors instead of reporting them. } } @@ -47,9 +56,19 @@ android { } } + // Disable 'release' buildtype. + // The editor can't be used with target=release only, as debugging tools are then not + // included, and it would crash on errors instead of reporting them. + variantFilter { variant -> + if (variant.buildType.name == "release") { + setIgnore(true) + } + } + applicationVariants.all { variant -> variant.outputs.all { output -> - output.outputFileName = "android_editor_${variant.name}.apk" + def suffix = variant.name == "dev" ? "_dev" : "" + output.outputFileName = "android_editor${suffix}.apk" } } } diff --git a/platform/android/java/editor/src/debug/res/values/strings.xml b/platform/android/java/editor/src/debug/res/values/strings.xml deleted file mode 100644 index 4871bcfc091..00000000000 --- a/platform/android/java/editor/src/debug/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Godot Editor (debug) - diff --git a/platform/android/java/editor/src/dev/res/values/strings.xml b/platform/android/java/editor/src/dev/res/values/strings.xml new file mode 100644 index 00000000000..f3a31365546 --- /dev/null +++ b/platform/android/java/editor/src/dev/res/values/strings.xml @@ -0,0 +1,4 @@ + + + Godot Editor (dev) + diff --git a/platform/android/java/editor/src/release_debug/res/values/strings.xml b/platform/android/java/editor/src/release_debug/res/values/strings.xml deleted file mode 100644 index c2629aac983..00000000000 --- a/platform/android/java/editor/src/release_debug/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Godot Editor (release-debug) - diff --git a/platform/android/java/lib/build.gradle b/platform/android/java/lib/build.gradle index ee28f44b4e4..f5433ae7185 100644 --- a/platform/android/java/lib/build.gradle +++ b/platform/android/java/lib/build.gradle @@ -35,15 +35,15 @@ android { } buildTypes { - release_debug { + dev { initWith debug } } - flavorDimensions "tools" + flavorDimensions "products" productFlavors { - toolsEnabled {} - toolsDisabled {} + editor {} + template {} } lintOptions { @@ -71,32 +71,43 @@ android { } debug.jniLibs.srcDirs = ['libs/debug'] - release_debug.jniLibs.srcDirs = ['libs/release_debug'] + dev.jniLibs.srcDirs = ['libs/dev'] release.jniLibs.srcDirs = ['libs/release'] - // Tools enabled jni library - toolsEnabledDebug.jniLibs.srcDirs = ['libs/tools/debug'] - toolsEnabledRelease_debug.jniLibs.srcDirs = ['libs/tools/release_debug'] - toolsEnabledRelease.jniLibs.srcDirs = ['libs/tools/release'] + // Editor jni library + editorDebug.jniLibs.srcDirs = ['libs/tools/debug'] + editorDev.jniLibs.srcDirs = ['libs/tools/dev'] + } + + // Disable 'editorRelease'. + // The editor can't be used with target=release as debugging tools are then not + // included, and it would crash on errors instead of reporting them. + variantFilter { variant -> + if (variant.name == "editorRelease") { + setIgnore(true) + } } libraryVariants.all { variant -> def flavorName = variant.getFlavorName() - def buildType = variant.buildType.name.capitalize() - if (flavorName == null || flavorName == "") { throw new GradleException("Invalid product flavor: $flavorName") } - boolean toolsFlag = flavorName == "toolsEnabled" + boolean toolsFlag = flavorName == "editor" - def releaseTarget = buildType.toLowerCase() - if (releaseTarget == null || releaseTarget == "") { - throw new GradleException("Invalid build type: " + buildType) + def buildType = variant.buildType.name + if (buildType == null || buildType == "" || !supportedTargetsMap.containsKey(buildType)) { + throw new GradleException("Invalid build type: $buildType") + } + + def sconsTarget = supportedTargetsMap[buildType] + if (sconsTarget == null || sconsTarget == "") { + throw new GradleException("Invalid scons target: $sconsTarget") } // Update the name of the generated library - def outputSuffix = "${releaseTarget}.aar" + def outputSuffix = "${buildType}.aar" if (toolsFlag) { outputSuffix = "tools.$outputSuffix" } @@ -138,24 +149,24 @@ android { for (String selectedAbi : selectedAbis) { if (!supportedAbis.contains(selectedAbi)) { - throw new GradleException("Invalid selected abi: " + selectedAbi) + throw new GradleException("Invalid selected abi: $selectedAbi") } // Creating gradle task to generate the native libraries for the selected abi. def taskName = getSconsTaskName(flavorName, buildType, selectedAbi) tasks.create(name: taskName, type: Exec) { executable sconsExecutableFile.absolutePath - args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${releaseTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() + args "--directory=${pathToRootDir}", "platform=android", "tools=${toolsFlag}", "target=${sconsTarget}", "android_arch=${selectedAbi}", "-j" + Runtime.runtime.availableProcessors() } // Schedule the tasks so the generated libs are present before the aar file is packaged. - tasks["merge${flavorName.capitalize()}${buildType}JniLibFolders"].dependsOn taskName + tasks["merge${flavorName.capitalize()}${buildType.capitalize()}JniLibFolders"].dependsOn taskName } } // TODO: Enable when issues with AGP 7.1+ are resolved (https://github.com/GodotVR/godot_openxr/issues/187). // publishing { -// singleVariant("release") { +// singleVariant("templateRelease") { // withSourcesJar() // withJavadocJar() // } diff --git a/platform/android/java/scripts/publish-module.gradle b/platform/android/java/scripts/publish-module.gradle index 6b2aea5caf9..32b749e493d 100644 --- a/platform/android/java/scripts/publish-module.gradle +++ b/platform/android/java/scripts/publish-module.gradle @@ -7,20 +7,15 @@ version = PUBLISH_VERSION afterEvaluate { publishing { publications { - release(MavenPublication) { + templateRelease(MavenPublication) { + from components.templateRelease + // The coordinates of the library, being set from variables that // we'll set up later groupId ossrhGroupId artifactId PUBLISH_ARTIFACT_ID version PUBLISH_VERSION - // Two artifacts, the `aar` (or `jar`) and the sources - if (project.plugins.findPlugin("com.android.library")) { - from components.release - } else { - from components.java - } - // Mostly self-explanatory metadata pom { name = PUBLISH_ARTIFACT_ID