Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/android support #101

Merged
merged 20 commits into from
Mar 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
3159f4d
Add jvm cpp distinction by platforms
piiertho Mar 7, 2021
6d50751
Differentiate jvm init arguments for android and desktop, android one…
piiertho Mar 7, 2021
408fb9c
Remove exceptions in favor of error crash. Make android implem of Ini…
piiertho Mar 8, 2021
6a7f44d
avoid copy jre for android export
piiertho Mar 8, 2021
f8964d4
Exclude java 9+ module-info for android support
chippmann Mar 8, 2021
0e6f72d
Make difference between dex jars and standard jars
piiertho Mar 8, 2021
2f73b2e
create class loader that load bootstrap jar for android
piiertho Mar 8, 2021
9606ab0
Set bootstrap classloader as parent classloader for main jar loader o…
piiertho Mar 8, 2021
d3f6626
Automate dex conversion and update docs
chippmann Mar 9, 2021
681e0be
Update supported targets
chippmann Mar 9, 2021
7fc3dde
Fixed dex jar path in tests project
piiertho Mar 9, 2021
cfb254a
First try to add android build to CI using debug export
piiertho Mar 10, 2021
139463f
Add android build to exports template Check PR CI
piiertho Mar 10, 2021
10fa9c3
Remove android specific create class loader method
piiertho Mar 10, 2021
af8793f
Replace `ANDROID_HOME` with `ANDROID_SDK_ROOT` and update docs
chippmann Mar 10, 2021
888152e
Remove println import
chippmann Mar 10, 2021
5086273
Make jvm exception crash engine only when in debug and not TOOL
piiertho Mar 10, 2021
0a0d5a6
Add aar to jre export in export plugin
piiertho Mar 10, 2021
6f63cc8
Fix android export condition in export plugin
piiertho Mar 11, 2021
d34984c
Use parent class loader when creating a new desktop classloader on cp…
piiertho Mar 11, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/check-pr-engine-editor-debug-and-tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@ jobs:
build-editor-debug:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
name: [ Linux, OSX, Windows ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because on exports I had to rename it to not have confusions between x11 and android. So to keep it coherent, I renamed for all cpp jobs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this should contain Android as well?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no editor build for android.

include:
- os: ubuntu-latest
- name: Linux
os: ubuntu-latest
platform: x11
- os: macos-latest
- name: OSX
os: macos-latest
platform: osx
- os: windows-latest
- name: Windows
os: windows-latest
platform: windows
runs-on: ${{ matrix.os }}
steps:
Expand Down
11 changes: 7 additions & 4 deletions .github/workflows/check-pr-engine-editor-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ jobs:
build-editor-release:
strategy:
matrix:
os: [ ubuntu-latest, macos-latest, windows-latest ]
name: [ Linux, OSX, Windows ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here - I don't think this is necessary.

include:
- os: ubuntu-latest
- name: Linux
os: ubuntu-latest
platform: x11
- os: macos-latest
- name: OSX
os: macos-latest
platform: osx
- os: windows-latest
- name: Windows
os: windows-latest
platform: windows
runs-on: ${{ matrix.os }}
steps:
Expand Down
35 changes: 31 additions & 4 deletions .github/workflows/check-pr-engine-export-template-debug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ jobs:
build-export-debug:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
name: [ Linux, OSX, Windows, Android ]
include:
- os: ubuntu-latest
- name: Linux
os: ubuntu-latest
platform: x11
- os: macos-latest
- name: OSX
os: macos-latest
platform: osx
- os: windows-latest
- name: Windows
os: windows-latest
platform: windows
- name: Android
os: ubuntu-latest
platform: android
runs-on: ${{ matrix.os }}
steps:
- name: Configure dependencies
Expand All @@ -39,6 +45,27 @@ jobs:
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons
- name: Set up JDK 1.8
if: matrix.platform == 'android'
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Setup Android SDK
if: matrix.platform == 'android'
uses: android-actions/setup-android@v2
- name: Build debug export template
if: matrix.platform != 'android'
run: |
scons platform=${{ matrix.platform }} tools=no target=release_debug bits=64
- name: Build android debug binary armv7
if: matrix.platform == 'android'
run: |
scons platform=${{ matrix.platform }} target=release_debug android_arch=armv7
- name: Build android debug binary arm64v8
if: matrix.platform == 'android'
run: |
scons platform=${{ matrix.platform }} target=release_debug android_arch=arm64v8
- name: Build android debug export template
if: matrix.platform == 'android'
run: |
cd platform/android/java/ && ./gradlew generateGodotTemplates
35 changes: 31 additions & 4 deletions .github/workflows/check-pr-engine-export-template-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,20 @@ jobs:
build-export-release:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
name: [ Linux, OSX, Windows, Android ]
include:
- os: ubuntu-latest
- name: Linux
os: ubuntu-latest
platform: x11
- os: macos-latest
- name: OSX
os: macos-latest
platform: osx
- os: windows-latest
- name: Windows
os: windows-latest
platform: windows
- name: Android
os: ubuntu-latest
platform: android
runs-on: ${{ matrix.os }}
steps:
- name: Configure dependencies
Expand All @@ -39,6 +45,27 @@ jobs:
run: |
python -c "import sys; print(sys.version)"
python -m pip install scons
- name: Set up JDK 1.8
if: matrix.platform == 'android'
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Setup Android SDK
if: matrix.platform == 'android'
uses: android-actions/setup-android@v2
- name: Build release export template
if: matrix.platform != 'android'
run: |
scons platform=${{ matrix.platform }} tools=no target=release bits=64
- name: Build android release binary armv7
if: matrix.platform == 'android'
run: |
scons platform=${{ matrix.platform }} target=release android_arch=armv7
- name: Build android release binary arm64v8
if: matrix.platform == 'android'
run: |
scons platform=${{ matrix.platform }} target=release android_arch=arm64v8
- name: Build android release export template
if: matrix.platform == 'android'
run: |
cd platform/android/java/ && ./gradlew generateGodotTemplates
12 changes: 9 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ set(GODOT_ROOT_DIR ../../)
# Get sources
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp)

add_library(${PROJECT_NAME} SHARED register_types.cpp ${SOURCES} src/gd_kotlin.cpp src/gd_kotlin.h src/godotkotlin_defs.h src/jni/wrapper.h src/kt_function.cpp src/kt_function.h src/kt_property.cpp src/kt_property.h src/jni/local_frame.cpp src/jni/local_frame.h src/kt_signal_info.cpp src/kt_signal_info.h src/bridges/memory_bridge.cpp src/bridges/memory_bridge.h src/jni/java_method_signature.cpp src/jni/java_method_signature.h src/java_instance_wrapper.h src/shared_buffer.h src/shared_buffer.cpp src/type_manager.cpp src/type_manager.h src/bridges_manager.cpp src/bridges_manager.h src/bridges/variant_array_bridge.cpp src/bridges/variant_array_bridge.h src/bridges/constants.h src/bridges/dictionary_bridge.cpp src/bridges/dictionary_bridge.h src/bridges/bridges_utils.h src/bridges/rid_bridge.cpp src/bridges/rid_bridge.h src/bridges/node_path_bridge.cpp src/bridges/node_path_bridge.h src/bridges/pool_byte_array_bridge.h src/bridges/pool_byte_array_bridge.cpp src/bridges/pool_color_array_bridge.h src/bridges/pool_color_array_bridge.cpp src/bridges/pool_int_array_bridge.h src/bridges/pool_int_array_bridge.cpp src/bridges/pool_real_array_bridge.h src/bridges/pool_real_array_bridge.cpp src/bridges/pool_string_array_bridge.h src/bridges/pool_string_array_bridge.cpp src/bridges/pool_vector2_array_bridge.h src/bridges/pool_vector2_array_bridge.cpp src/bridges/pool_vector3_array_bridge.h src/bridges/pool_vector3_array_bridge.cpp src/logging.h src/kt_constructor.cpp src/kt_constructor.h src/bridges/gd_print_bridge.cpp src/bridges/gd_print_bridge.h src/kotlin_editor_export_plugin.cpp src/kotlin_editor_export_plugin.h)
add_library(${PROJECT_NAME} SHARED register_types.cpp ${SOURCES} src/gd_kotlin.cpp src/gd_kotlin.h src/godotkotlin_defs.h src/jni/wrapper.h src/kt_function.cpp src/kt_function.h src/kt_property.cpp src/kt_property.h src/jni/local_frame.cpp src/jni/local_frame.h src/kt_signal_info.cpp src/kt_signal_info.h src/bridges/memory_bridge.cpp src/bridges/memory_bridge.h src/jni/java_method_signature.cpp src/jni/java_method_signature.h src/java_instance_wrapper.h src/shared_buffer.h src/shared_buffer.cpp src/type_manager.cpp src/type_manager.h src/bridges_manager.cpp src/bridges_manager.h src/bridges/variant_array_bridge.cpp src/bridges/variant_array_bridge.h src/bridges/constants.h src/bridges/dictionary_bridge.cpp src/bridges/dictionary_bridge.h src/bridges/bridges_utils.h src/bridges/rid_bridge.cpp src/bridges/rid_bridge.h src/bridges/node_path_bridge.cpp src/bridges/node_path_bridge.h src/bridges/pool_byte_array_bridge.h src/bridges/pool_byte_array_bridge.cpp src/bridges/pool_color_array_bridge.h src/bridges/pool_color_array_bridge.cpp src/bridges/pool_int_array_bridge.h src/bridges/pool_int_array_bridge.cpp src/bridges/pool_real_array_bridge.h src/bridges/pool_real_array_bridge.cpp src/bridges/pool_string_array_bridge.h src/bridges/pool_string_array_bridge.cpp src/bridges/pool_vector2_array_bridge.h src/bridges/pool_vector2_array_bridge.cpp src/bridges/pool_vector3_array_bridge.h src/bridges/pool_vector3_array_bridge.cpp src/logging.h src/kt_constructor.cpp src/kt_constructor.h src/bridges/gd_print_bridge.cpp src/bridges/gd_print_bridge.h src/kotlin_editor_export_plugin.cpp src/kotlin_editor_export_plugin.h src/jni/platforms/jvm_desktop.cpp src/jni/platforms/jvm_android.cpp src/jni/platforms/init_args_desktop.cpp src/jni/platforms/init_args_android.cpp)

# JNI
find_package(JNI REQUIRED)
Expand All @@ -21,5 +21,11 @@ target_include_directories(${PROJECT_NAME}
)

# Uncomment to pass auto completion in TOOLS mode
add_compile_definitions(TOOLS_ENABLED)
add_compile_definitions(DEBUG_ENABLED)
#add_compile_definitions(TOOLS_ENABLED)
add_compile_definitions(DEBUG_ENABLED)

# platforms
#add_compile_definitions(WINDOWS_ENABLED)
#add_compile_definitions(X11_ENABLED)
#add_compile_definitions(OSX_ENABLED)
add_compile_definitions(__ANDROID__)
19 changes: 12 additions & 7 deletions SCsub
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,21 @@ Import("env")

java_home = os.environ["JAVA_HOME"]

java_include_dirs = [
java_home + "/include",
java_home + "/include/linux",
java_home + "/include/win32",
java_home + "/include/darwin"
]
if env["platform"] != "android":
java_include_dirs = [
java_home + "/include",
java_home + "/include/linux",
java_home + "/include/win32",
java_home + "/include/darwin"
]

module_env = env.Clone()
module_env.Append(CPPPATH=[java_include_dirs])

if env["platform"] != "android":
module_env.Append(CPPPATH=[java_include_dirs])

module_env.add_source_files(module_env.modules_sources, "register_types.cpp")
module_env.add_source_files(module_env.modules_sources, "src/jni/*.cpp")
module_env.add_source_files(module_env.modules_sources, "src/jni/platforms/*.cpp")
module_env.add_source_files(module_env.modules_sources, "src/bridges/*.cpp")
module_env.add_source_files(module_env.modules_sources, "src/*.cpp")
1 change: 1 addition & 0 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ nav:
- Properties: user-guide/properties.md
- Signals: user-guide/signals.md
- Functions: user-guide/functions.md
- Exporting: user-guide/exporting.md
- Advanced:
- Custom Src dirs: advanced/custom-src-dirs.md
- Commandline args: advanced/commandline-args.md
Expand Down
3 changes: 2 additions & 1 deletion docs/src/doc/supported-platforms.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ While Kotlin and Godot supports a wide range of platforms, this module for the m
- Windows X64
- Linux X64
- MacOS X64
- Android (arm64v8 and armv7)

Mobile platforms such as Android and iOS will be supported at a later date.
iOS will be supported at a later date.
37 changes: 31 additions & 6 deletions docs/src/doc/user-guide/exporting.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Exporting games

To export game, you should copy exports in right template folder, which should be:
To export the game, you should copy exports into the correct template folder, which should be:
- Windows: `%APPDATA%\Godot\templates\<godot-version>`
- Linux: `~/.local/share/godot/templates/<godot-version>`

Expand All @@ -12,15 +12,40 @@ And `release_debug` to:
- Windows: `windows_64_debug.exe`
- Linux: `linux_x11_64_debug`

On osx use the script mentionned in [this issue](https://github.com/godotengine/godot-docs/issues/3194#issuecomment-588862977),
this will do the job for you.
On osx use the script mentioned in [this issue](https://github.com/godotengine/godot-docs/issues/3194#issuecomment-588862977). It will do the job for you.

Then you can export your game as usual, your game `jar` will be included in `pck`.
On desktop platforms, this also copies the jre folder of your project in the exported game folder.

## Particularities

`godot-bootstrap.jar` and `main.jar` are set into `pck` during the export process. Also, as a real file path is needed to
handle them, they are copied on the first game version start from `res://` to `user://` (We check if exists and also md5)
`godot-bootstrap.jar` and `main.jar` are set into `pck` during the export process. As a real file path is needed to
handle them, they are copied on the first game version start from `res://` to `user://` (We check if it exists and also check the md5 hash)
to only update when needed.
Don't forget to remove them when uninstalling the game.
Don't forget to remove them when writing an uninstaller for the game.

## Android
In order to build on android, set the `isAndroidExportEnabled` flag to true in the `build.gradle.kts`:
```kotlin
godot {
isAndroidExportEnabled.set(true)
}
```
On android we do not embedd a JVM. We use the existing DalvikVM of android.
In order for your game to load the necessary jar files, they need to be converted into dex format.
Our gradle plugin will handle this for you, but you need to fulfill the following requirements:

- Android SDK installed
- `dx` tool resolvable by doing one of the following:
- set the `PATH` environment variable to include `<android-sdk-dir>/build-tools/<version>/`
- set the path to the `dx` tool through gradle with the property `dxToolPath`:
```kotlin
godot {
isAndroidExportEnabled.set(true)
dxToolPath.set("${System.getenv("ANDROID_SDK_ROOT")}/build-tools/30.0.3/dx")
}
```

!!! warning "Important:"
Same as on the desktop targets, the game copies the needed jar files to the `user://` dir upon first execution or if the files have changed. On android this is the applications `files` folder.
If you do IO operations on android, never empty the whole `files` folder! Only delete what you have added or exclude the following two files when clearing the `files` folder: `godot-bootstrap-dex.jar` and `main-dex.jar`.
6 changes: 6 additions & 0 deletions harness/tests/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ repositories {
jcenter()
}

godot {
//uncomment to test android
// isAndroidExportEnabled.set(true)
// dxToolPath.set("${System.getenv("ANDROID_SDK_ROOT")}/build-tools/30.0.3/dx")
}

dependencies {
implementation("joda-time:joda-time:2.10.6") //external dependency to test dependency inclusion in dummyCompilation
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,22 @@ class MultiArgsConstructorTest : Node {
@RegisterConstructor
constructor(i: Int, s: String, obj: Object?, variantArray: VariantArray<Any?>?, navMesh: NavigationMesh) : this()

constructor(iShouldNOTFailAsImNotRegistered: String, s: Int, obj: Object?, variantArray: VariantArray<Any?>?, navMesh: NavigationMesh) : this()
constructor(i: Int, s: String, obj: Object?, variantArray: VariantArray<Any?>?, navMesh: NavigationMesh, tooManyArgsShouldWorkIfNotRegistered: String) : this()
constructor(
iShouldNOTFailAsImNotRegistered: String,
s: Int,
obj: Object?,
variantArray: VariantArray<Any?>?,
navMesh: NavigationMesh
) : this()

constructor(
i: Int,
s: String,
obj: Object?,
variantArray: VariantArray<Any?>?,
navMesh: NavigationMesh,
tooManyArgsShouldWorkIfNotRegistered: String
) : this()

// constructors which should fail:
// @RegisterConstructor
Expand Down
1 change: 1 addition & 0 deletions kt/godot-library/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ tasks {
archiveBaseName.set("godot-bootstrap")
archiveVersion.set("")
archiveClassifier.set("")
exclude("**/module-info.class") //for android support: excludes java 9+ module info which cannot be parsed by the dx tool
finalizedBy(copyBootstrapJar)
}

Expand Down
21 changes: 10 additions & 11 deletions kt/godot-runtime/src/main/kotlin/godot/runtime/Bootstrap.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,18 @@ import java.util.concurrent.TimeUnit

class Bootstrap {
private var registry: ClassRegistry? = null
private lateinit var classloader: URLClassLoader
private lateinit var classloader: ClassLoader
private lateinit var serviceLoader: ServiceLoader<Entry>
private var executor: ScheduledExecutorService? = null
private var watchService: WatchService? = null
private var engineTypesRegistered: Boolean = false

fun init(isEditor: Boolean, jarRootDir: String) {
fun init(isEditor: Boolean, jarRootDir: String, jarFile: String, loader: ClassLoader?) {
val libsDir = Paths.get(jarRootDir)
val mainJarPath = libsDir.resolve("main.jar")
val mainJarPath = libsDir.resolve(jarFile)

if (File(mainJarPath.toString()).exists()) {
doInit(mainJarPath.toUri().toURL())
doInit(mainJarPath.toUri().toURL(), loader)
} else {
if (isEditor) {
::warning
Expand Down Expand Up @@ -65,7 +65,7 @@ class Bootstrap {
clearClassesCache()

if (File(mainJarPath.toString()).exists()) {
doInit(mainJarPath.toUri().toURL())
doInit(mainJarPath.toUri().toURL(), classloader)
} else {
warning("No main.jar detected. No classes will be loaded. Build the project to load classes")
}
Expand All @@ -87,15 +87,14 @@ class Bootstrap {
Thread.currentThread().contextClassLoader = classloader
}

private fun doInit(mainJar: URL) {
private fun doInit(mainJar: URL, classLoader: ClassLoader?) {
registry = ClassRegistry()
classloader = URLClassLoader(arrayOf(mainJar), this::class.java.classLoader)
classloader = classLoader ?: URLClassLoader(arrayOf(mainJar), this::class.java.classLoader)
Thread.currentThread().contextClassLoader = classloader
serviceLoader = ServiceLoader.load(Entry::class.java, classloader)
val entry = serviceLoader.findFirst()

if (entry.isPresent) {
with(entry.get()) {
val entryIterator = serviceLoader.iterator()
if (entryIterator.hasNext()) {
with(entryIterator.next()) {
val context = Entry.Context(registry!!)

if (!engineTypesRegistered) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package godot.gradle

import org.gradle.api.model.ObjectFactory
import org.gradle.kotlin.dsl.property

open class GodotExtension(objects: ObjectFactory) {
val isAndroidExportEnabled = objects.property<Boolean>()
val dxToolPath = objects.property<String>()
}
Loading