diff options
author | Raul Santos <raulsntos@gmail.com> | 2024-02-09 17:26:53 +0100 |
---|---|---|
committer | Raul Santos <raulsntos@gmail.com> | 2024-09-16 17:07:03 +0200 |
commit | 0aa46e19c5a1864454451891fb3f40f5ef3ff742 (patch) | |
tree | 3842d592644353d5bdd79af2eb8c34f72cf35aaa /platform/android/java | |
parent | a75bacebef979a17b549c6577defbbfd2f7ef2e0 (diff) | |
download | redot-engine-0aa46e19c5a1864454451891fb3f40f5ef3ff742.tar.gz |
C#: Fallback to CoreCLR/MonoVM hosting APIs when hostfxr/NativeAOT fails
Some platforms don't support hostfxr but we can use the coreclr/monosgen library directly to initialize the runtime.
Android exports now use the `android` runtime identifier instead of `linux-bionic`, this removes the restrictions we previously had:
- Adds support for all Android architectures (arm32, arm64, x32, and x64), previously only the 64-bit architectures were supported.
- Loads `System.Security.Cryptography.Native.Android` (the .NET library that binds to the Android OS crypto functions).
Diffstat (limited to 'platform/android/java')
-rw-r--r-- | platform/android/java/app/build.gradle | 40 | ||||
-rw-r--r-- | platform/android/java/app/config.gradle | 8 | ||||
-rw-r--r-- | platform/android/java/app/src/com/godot/game/GodotApp.java | 15 | ||||
-rw-r--r-- | platform/android/java/build.gradle | 40 |
4 files changed, 89 insertions, 14 deletions
diff --git a/platform/android/java/app/build.gradle b/platform/android/java/app/build.gradle index b9d15deec9..fdc5753798 100644 --- a/platform/android/java/app/build.gradle +++ b/platform/android/java/app/build.gradle @@ -29,6 +29,8 @@ allprojects { configurations { // Initializes a placeholder for the devImplementation dependency configuration. devImplementation {} + // Initializes a placeholder for the monoImplementation dependency configuration. + monoImplementation {} } dependencies { @@ -42,9 +44,9 @@ dependencies { } else { // Godot gradle 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']) + debugImplementation fileTree(dir: 'libs/debug', include: ['**/*.jar', '*.aar']) + devImplementation fileTree(dir: 'libs/dev', include: ['**/*.jar', '*.aar']) + releaseImplementation fileTree(dir: 'libs/release', include: ['**/*.jar', '*.aar']) } // Godot user plugins remote dependencies @@ -60,6 +62,12 @@ dependencies { if (pluginsBinaries != null && pluginsBinaries.size() > 0) { implementation files(pluginsBinaries) } + + // .NET dependencies + String jar = '../../../../modules/mono/thirdparty/libSystem.Security.Cryptography.Native.Android.jar' + if (file(jar).exists()) { + monoImplementation files(jar) + } } android { @@ -155,6 +163,10 @@ android { } } + buildFeatures { + buildConfig = true + } + buildTypes { debug { @@ -192,6 +204,13 @@ android { } } + flavorDimensions 'edition' + + productFlavors { + standard {} + mono {} + } + sourceSets { main { manifest.srcFile 'AndroidManifest.xml' @@ -207,7 +226,8 @@ android { applicationVariants.all { variant -> variant.outputs.all { output -> - output.outputFileName = "android_${variant.name}.apk" + String filenameSuffix = variant.flavorName == "mono" ? variant.name : variant.buildType.name + output.outputFileName = "android_${filenameSuffix}.apk" } } } @@ -220,12 +240,20 @@ task copyAndRenameBinary(type: Copy) { String exportPath = getExportPath() String exportFilename = getExportFilename() + String exportEdition = getExportEdition() String exportBuildType = getExportBuildType() + String exportBuildTypeCapitalized = exportBuildType.capitalize() String exportFormat = getExportFormat() boolean isAab = exportFormat == "aab" - String sourceFilepath = isAab ? "$buildDir/outputs/bundle/$exportBuildType/build-${exportBuildType}.aab" : "$buildDir/outputs/apk/$exportBuildType/android_${exportBuildType}.apk" - String sourceFilename = isAab ? "build-${exportBuildType}.aab" : "android_${exportBuildType}.apk" + boolean isMono = exportEdition == "mono" + String filenameSuffix = exportBuildType + if (isMono) { + filenameSuffix = isAab ? "${exportEdition}-${exportBuildType}" : "${exportEdition}${exportBuildTypeCapitalized}" + } + + String sourceFilename = isAab ? "build-${filenameSuffix}.aab" : "android_${filenameSuffix}.apk" + String sourceFilepath = isAab ? "$buildDir/outputs/bundle/${exportEdition}${exportBuildTypeCapitalized}/$sourceFilename" : "$buildDir/outputs/apk/$exportEdition/$exportBuildType/$sourceFilename" from sourceFilepath into exportPath diff --git a/platform/android/java/app/config.gradle b/platform/android/java/app/config.gradle index 611a9c4a40..597a4d5c14 100644 --- a/platform/android/java/app/config.gradle +++ b/platform/android/java/app/config.gradle @@ -224,6 +224,14 @@ ext.getExportFilename = { return exportFilename } +ext.getExportEdition = { + String exportEdition = project.hasProperty("export_edition") ? project.property("export_edition") : "" + if (exportEdition == null || exportEdition.isEmpty()) { + exportEdition = "standard" + } + return exportEdition +} + ext.getExportBuildType = { String exportBuildType = project.hasProperty("export_build_type") ? project.property("export_build_type") : "" if (exportBuildType == null || exportBuildType.isEmpty()) { diff --git a/platform/android/java/app/src/com/godot/game/GodotApp.java b/platform/android/java/app/src/com/godot/game/GodotApp.java index 22e617f6e7..9d4991e120 100644 --- a/platform/android/java/app/src/com/godot/game/GodotApp.java +++ b/platform/android/java/app/src/com/godot/game/GodotApp.java @@ -33,14 +33,29 @@ package com.godot.game; import org.godotengine.godot.GodotActivity; import android.os.Bundle; +import android.util.Log; import androidx.core.splashscreen.SplashScreen; +import com.godot.game.BuildConfig; + /** * Template activity for Godot Android builds. * Feel free to extend and modify this class for your custom logic. */ public class GodotApp extends GodotActivity { + static { + // .NET libraries. + if (BuildConfig.FLAVOR.equals("mono")) { + try { + Log.v("GODOT", "Loading System.Security.Cryptography.Native.Android library"); + System.loadLibrary("System.Security.Cryptography.Native.Android"); + } catch (UnsatisfiedLinkError e) { + Log.e("GODOT", "Unable to load System.Security.Cryptography.Native.Android library"); + } + } + } + @Override public void onCreate(Bundle savedInstanceState) { SplashScreen.installSplashScreen(this); diff --git a/platform/android/java/build.gradle b/platform/android/java/build.gradle index d60f97e3e7..9184e8c5d5 100644 --- a/platform/android/java/build.gradle +++ b/platform/android/java/build.gradle @@ -30,6 +30,7 @@ ext { "editor": ["dev", "debug", "release"], "template": ["dev", "debug", "release"] ] + supportedEditions = ["standard", "mono"] // Used by gradle to specify which architecture to build for by default when running // `./gradlew build` (this command is usually used by Android Studio). @@ -53,7 +54,7 @@ def getSconsTaskName(String flavor, String buildType, String abi) { * The zip file also includes some gradle tools to enable gradle builds from the Godot Editor. */ task zipGradleBuild(type: Zip) { - onlyIf { generateGodotTemplates.state.executed || generateDevTemplate.state.executed } + onlyIf { generateGodotTemplates.state.executed || generateGodotMonoTemplates.state.executed || generateDevTemplate.state.executed } doFirst { logger.lifecycle("Generating Godot gradle build template") } @@ -94,15 +95,22 @@ def templateExcludedBuildTask() { /** * Generates the build tasks for the given flavor * @param flavor Must be one of the supported flavors ('template' / 'editor') + * @param edition Must be one of the supported editions ('standard' / 'mono') * @param androidDistro Must be one of the supported Android distributions ('android' / 'horizonos') */ -def generateBuildTasks(String flavor = "template", String androidDistro = "android") { +def generateBuildTasks(String flavor = "template", String edition = "standard", String androidDistro = "android") { if (!supportedFlavors.contains(flavor)) { throw new GradleException("Invalid build flavor: $flavor") } if (!supportedAndroidDistributions.contains(androidDistro)) { throw new GradleException("Invalid Android distribution: $androidDistro") } + if (!supportedEditions.contains(edition)) { + throw new GradleException("Invalid build edition: $edition") + } + if (edition == "mono" && flavor != "template") { + throw new GradleException("'mono' edition only supports the 'template' flavor.") + } String capitalizedAndroidDistro = androidDistro.capitalize() def buildTasks = [] @@ -126,6 +134,7 @@ def generateBuildTasks(String flavor = "template", String androidDistro = "andro && targetLibs.listFiles().length > 0)) { String capitalizedTarget = target.capitalize() + String capitalizedEdition = edition.capitalize() if (isTemplate) { // Copy the Godot android library archive file into the app module libs directory. // Depends on the library build task to ensure the AAR file is generated prior to copying. @@ -157,15 +166,16 @@ def generateBuildTasks(String flavor = "template", String androidDistro = "andro // Copy the generated binary template into the Godot bin directory. // Depends on the app build task to ensure the binary is generated prior to copying. - String copyBinaryTaskName = "copy${capitalizedTarget}BinaryToBin" + String copyBinaryTaskName = "copy${capitalizedEdition}${capitalizedTarget}BinaryToBin" if (tasks.findByName(copyBinaryTaskName) != null) { buildTasks += tasks.getByName(copyBinaryTaskName) } else { buildTasks += tasks.create(name: copyBinaryTaskName, type: Copy) { - dependsOn ":app:assemble${capitalizedTarget}" - from("app/build/outputs/apk/${target}") + String filenameSuffix = edition == "mono" ? "${edition}${capitalizedTarget}" : target + dependsOn ":app:assemble${capitalizedEdition}${capitalizedTarget}" + from("app/build/outputs/apk/${edition}/${target}") into(binDir) - include("android_${target}.apk") + include("android_${filenameSuffix}.apk") } } } else { @@ -212,7 +222,7 @@ def generateBuildTasks(String flavor = "template", String androidDistro = "andro */ task generateGodotEditor { gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = generateBuildTasks("editor", "android") + dependsOn = generateBuildTasks("editor", "standard", "android") } /** @@ -224,7 +234,7 @@ task generateGodotEditor { */ task generateGodotHorizonOSEditor { gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() - dependsOn = generateBuildTasks("editor", "horizonos") + dependsOn = generateBuildTasks("editor", "standard", "horizonos") } /** @@ -238,6 +248,17 @@ task generateGodotTemplates { } /** + * Master task used to coordinate the tasks defined above to generate the set of Godot templates + * for the 'mono' edition of the engine. + */ +task generateGodotMonoTemplates { + gradle.startParameter.excludedTaskNames += templateExcludedBuildTask() + dependsOn = generateBuildTasks("template", "mono") + + finalizedBy 'zipGradleBuild' +} + +/** * Generates the same output as generateGodotTemplates but with dev symbols */ task generateDevTemplate { @@ -295,6 +316,9 @@ task cleanGodotTemplates(type: Delete) { delete("$binDir/android_debug.apk") delete("$binDir/android_dev.apk") delete("$binDir/android_release.apk") + delete("$binDir/android_monoDebug.apk") + delete("$binDir/android_monoDev.apk") + delete("$binDir/android_monoRelease.apk") delete("$binDir/android_source.zip") delete("$binDir/godot-lib.template_debug.aar") delete("$binDir/godot-lib.template_debug.dev.aar") |