Skip to content

Commit

Permalink
WIP: Kotlin support
Browse files Browse the repository at this point in the history
Signed-off-by: Patryk Wrobel <[email protected]>
  • Loading branch information
pwrobeldev committed Feb 4, 2025
1 parent a18a561 commit 739218e
Show file tree
Hide file tree
Showing 68 changed files with 3,890 additions and 27 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/functional-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,61 @@ jobs:
./scripts/build-android-namerules --publish
working-directory: functional-tests

android-kotlin:
name: Android-Kotlin
runs-on: ubuntu-20.04

steps:
- uses: actions/checkout@v2
- name: Install JDK
uses: actions/setup-java@v1
with:
java-version: 17
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: |
~/.gradle/caches
!*gluecodium*
!*lime-*
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Install GCC
uses: egor-tensin/setup-gcc@v1
with:
version: 8
- name: Install CMake
uses: jwlawson/[email protected]
with:
cmake-version: '3.19.3'
- name: Install ninja
run: sudo apt install -y ninja-build
- name: Install Android SDK
run: |
ANDROID_API_LEVEL=android-28
ANDROID_BUILD_TOOLS_VERSION=28.0.3
ANDROID_HOME=${HOME}/android-sdk-linux
PATH=${PATH}:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/cmdline-tools/latest/bin
mkdir -p "${ANDROID_HOME}/cmdline-tools"
wget -q "https://dl.google.com/android/repository/commandlinetools-linux-7583922_latest.zip" -O android-sdk-tools.zip
unzip -q android-sdk-tools.zip -d ${ANDROID_HOME}/cmdline-tools
mv "${ANDROID_HOME}/cmdline-tools/cmdline-tools" "${ANDROID_HOME}/cmdline-tools/latest"
mkdir -p ~/.android
touch ~/.android/repositories.cfg
yes | sdkmanager --licenses
yes | sdkmanager "platforms;${ANDROID_API_LEVEL}" > /dev/null
yes | sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSION}" > /dev/null
- name: Build and run functional tests
run: |
export ANDROID_HOME=${HOME}/android-sdk-linux
export ANDROID_SDK_ROOT=${ANDROID_HOME}
export PATH=${PATH}:${ANDROID_HOME}/tools:${ANDROID_HOME}/tools/bin:${ANDROID_HOME}/platform-tools
./scripts/build-android-kotlin-functional --publish --hostOnly
working-directory: functional-tests
- name: Clean build dir
run: ./scripts/clean
working-directory: functional-tests

swift:
name: Swift on Linux
runs-on: ubuntu-20.04
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ The general form of the command is::
gluecodium_add_generate_command(
<target> # The target to add custom build rules for.
[GENERATORS <generator> ...] # The list of source code generators.
# Known value are: cpp, swift, android, dart
# Known value are: cpp, swift, android, android-kotlin, dart
# Usually at least two generators needs to be defined
# the one for native code and another for platform,
# for example android;cpp or swift;cpp
Expand Down
16 changes: 16 additions & 0 deletions cmake/modules/gluecodium/gluecodium/KnownOptionalProperties.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ _gluecodium_define_target_property(
"This property is initialized by the value of the GLUECODIUM_JAVA_INTERNAL_PACKAGE_DEFAULT variable if it is set when the function gluecodium_add_generate_command is called."
)

_gluecodium_define_target_property(
GLUECODIUM_KOTLIN_PACKAGE
BRIEF_DOCS "The base Kotlin package to use for generated Kotlin sources"
FULL_DOCS
"The base Kotlin package to use for generated Kotlin sources, for example \"com.my_company\"."
"This property is initialized by the value of the GLUECODIUM_KOTLIN_PACKAGE_DEFAULT variable if it is set when the function gluecodium_add_generate_command is called."
)

_gluecodium_define_target_property(
GLUECODIUM_KOTLIN_INTERNAL_PACKAGE
BRIEF_DOCS "The package to use for internal Kotlin code"
FULL_DOCS
"The subpackage to use for internal Kotlin code. This value is appended with separator '.' to a value passed with GLUECODIUM_KOTLIN_PACKAGE"
"This property is initialized by the value of the GLUECODIUM_KOTLIN_INTERNAL_PACKAGE_DEFAULT variable if it is set when the function gluecodium_add_generate_command is called."
)

_gluecodium_define_target_property(
GLUECODIUM_JAVA_NAMERULES
BRIEF_DOCS "The path to a file with name rules for Java"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ function(gluecodium_get_target_include_directories _target)
"$<BUILD_INTERFACE:${_output_${_source_set_lower}_dir}/android/jni>")
endif()

if(android-kotlin IN_LIST _generators)
list(APPEND _result_list_public
"$<BUILD_INTERFACE:${_output_${_source_set_lower}_dir}/android-kotlin/jni>")
endif()

if(dart IN_LIST _generators)
list(APPEND _result_list_public
"$<BUILD_INTERFACE:${_output_${_source_set_lower}_dir}/dart/ffi>")
Expand All @@ -85,7 +90,7 @@ function(gluecodium_get_target_include_directories _target)

endforeach()

if(android IN_LIST _generators)
if((android IN_LIST _generators) OR (android-kotlin IN_LIST _generators))
# If we're not crosscompiling, we need to manually add JNI includes.
if(NOT CMAKE_CROSSCOMPILING)
find_package(JNI REQUIRED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ macro(gluecodium_init_variables_with_united_file_paths name_suffix)
set(GLUECODIUM_GENERATED_cpp_${_source_group} cpp/${name_suffix}_${_source_group}_glue.cpp)
set(GLUECODIUM_GENERATED_jni_${_source_group}
android/${name_suffix}_${_source_group}_jniglue.cpp)
set(GLUECODIUM_GENERATED_jni_kotlin_${_source_group}
android-kotlin/${name_suffix}_${_source_group}_jniglue.cpp)
set(GLUECODIUM_GENERATED_cbridge_${_source_group}
cbridge/${name_suffix}_${_source_group}_cglue.cpp)
set(GLUECODIUM_GENERATED_cbridge_header_${_source_group}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ function(gluecodium_list_generated_files _target)
list(APPEND _android_generated_files "${_unity_dir}/${GLUECODIUM_GENERATED_jni_${_group}}")
endif()

if(android-kotlin IN_LIST _generators)
list(APPEND _android_kotlin_generated_files "${_unity_dir}/${GLUECODIUM_GENERATED_jni_kotlin_${_group}}")
endif()

if(swift IN_LIST _generators)
list(APPEND _cbridge_generated_files
"${_unity_dir}/${GLUECODIUM_GENERATED_cbridge_${_group}}")
Expand All @@ -76,11 +80,12 @@ function(gluecodium_list_generated_files _target)
set(${_args_OUTPUT_ALL}
${_cpp_generated_files} ${_android_generated_files} ${_cbridge_generated_files}
${_cbridge_headers_generated_files} ${_swift_generated_files} ${_dart_generated_files}
${_android_kotlin_generated_files}
PARENT_SCOPE)
endif()

if(_args_OUTPUT_CPP)
set(${_args_OUTPUT_CPP} ${_cpp_generated_files} ${_android_generated_files}
set(${_args_OUTPUT_CPP} ${_cpp_generated_files} ${_android_generated_files} ${_android_kotlin_generated_files}
${_cbridge_generated_files} ${_dart_generated_files} PARENT_SCOPE)
endif()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ function(gluecodium_read_required_properties _target)
message(FATAL_ERROR "Specified target '${_target}' doesn't exist")
endif()

set(GLUECODIUM_SUPPORTED_GENERATORS cpp android swift dart)
set(GLUECODIUM_SUPPORTED_GENERATORS cpp android android-kotlin swift dart)

function(_read_required_property result _target property_name)
get_target_property(_property_value ${_target} ${property_name})
Expand Down
8 changes: 8 additions & 0 deletions cmake/modules/gluecodium/gluecodium/details/runGenerate.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ function(_prepare_gluecodium_config_file file_path)
_append_list_paths_option(input GLUECODIUM_LIME_SOURCES)
_append_list_paths_option(auxinput GLUECODIUM_LIME_SOURCES_AUX)

_append_option(kotlinpackage GLUECODIUM_KOTLIN_PACKAGE)
_append_option(kotlinintpackage GLUECODIUM_KOTLIN_INTERNAL_PACKAGE)
_append_option(javapackage GLUECODIUM_JAVA_PACKAGE)
_append_option(intpackage GLUECODIUM_JAVA_INTERNAL_PACKAGE)
_append_option(javanonnullannotation GLUECODIUM_JAVA_NONNULL_ANNOTATION)
Expand Down Expand Up @@ -251,6 +253,12 @@ function(_collect_all_files_in_single_compilation_units)
_include_all(jni "android/jni/*_Conversion.h" "android/jni/*.cpp")
endif()

if(android-kotlin IN_LIST GLUECODIUM_GENERATORS)
# Include all conversion headers first, so all later generic conversions relying on
# specialization have all these defined
_include_all(jni_kotlin "android-kotlin/jni/*_Conversion.h" "android-kotlin/jni/*.cpp")
endif()

if(swift IN_LIST GLUECODIUM_GENERATORS)
_include_all(cbridge "cbridge/*.cpp")
# Collect all includes to be used in the modulemap
Expand Down
14 changes: 13 additions & 1 deletion functional-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,19 @@ ext {
minSdkVersion = 24
cmakeVersion = '3.19.0+'

buildRoot = "${rootProject.projectDir}/build-android"
isAndroidKotlinBuild = {
return project.hasProperty("android-kotlin")
}

getAndroidBuildVariant = {
if (isAndroidKotlinBuild()) {
return "android-kotlin"
} else {
return "android"
}
}

buildRoot = "${rootProject.projectDir}/build-${getAndroidBuildVariant()}"
buildNativeRoot = "${buildRoot}/cpp"
generatedDir = "${buildRoot}/generated"

Expand Down
16 changes: 9 additions & 7 deletions functional-tests/functional/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ function(feature feature_name)
set(FUNCTIONAL_LIME_SOURCES "${FUNCTIONAL_LIME_SOURCES};${lime_sources}" PARENT_SCOPE)
endfunction()

feature(Strings cpp android swift dart SOURCES
feature(Strings cpp android android-kotlin swift dart SOURCES
input/src/cpp/StaticStringMethods.cpp
input/src/cpp/StringsWithCstring.cpp
input/src/cpp/CppRefReturnType.cpp
Expand All @@ -99,7 +99,7 @@ feature(Blob cpp android swift dart SOURCES
input/lime/StaticByteArrayMethods.lime
)

feature(BuiltinTypes cpp android swift dart SOURCES
feature(BuiltinTypes cpp android android-kotlin swift dart SOURCES
input/src/cpp/StaticBooleanMethods.cpp
input/src/cpp/StaticFloatDoubleMethods.cpp
input/src/cpp/StaticIntMethods.cpp
Expand All @@ -109,15 +109,15 @@ feature(BuiltinTypes cpp android swift dart SOURCES
input/lime/StaticIntMethods.lime
)

feature(Classes cpp android swift dart SOURCES
feature(Classes cpp android android-kotlin swift dart SOURCES
input/src/cpp/Instances.h
input/src/cpp/Instances.cpp
input/src/cpp/InstancesFactory.cpp

input/lime/Instances.lime
)

feature(Interfaces cpp android swift dart SOURCES
feature(Interfaces cpp android android-kotlin swift dart SOURCES
input/src/cpp/Interfaces.h
input/src/cpp/Interfaces.cpp
input/src/cpp/InterfacesFactory.cpp
Expand Down Expand Up @@ -165,7 +165,7 @@ feature(TypeDefs cpp android swift dart SOURCES
input/lime/StaticTypedef.lime
)

feature(Enums cpp android swift dart SOURCES
feature(Enums cpp android android-kotlin swift dart SOURCES
input/src/cpp/Enums.cpp
input/src/cpp/EnumsTypeCollection.cpp

Expand All @@ -175,7 +175,7 @@ feature(Enums cpp android swift dart SOURCES
input/lime/EnumsTypeCollection.lime
)

feature(Properties cpp android swift dart SOURCES
feature(Properties cpp android android-kotlin swift dart SOURCES
input/src/cpp/AttributesInterfaceImpl.h
input/src/cpp/AttributesInterfaceImpl.cpp
input/src/cpp/AttributesInterfaceFactory.cpp
Expand Down Expand Up @@ -443,7 +443,7 @@ feature(Nesting cpp android swift dart SOURCES
input/lime/NestedInheritance.lime
)

feature(Lambdas cpp android swift dart SOURCES
feature(Lambdas cpp android android-kotlin swift dart SOURCES
input/lime/Lambdas.lime

input/src/cpp/Lambdas.cpp
Expand Down Expand Up @@ -537,6 +537,8 @@ set_target_properties(functional_bindings PROPERTIES
GLUECODIUM_JAVA_INTERNAL_PACKAGE lorem.ipsum
GLUECODIUM_JAVA_NONNULL_ANNOTATION androidx.annotation.NonNull
GLUECODIUM_JAVA_NULLABLE_ANNOTATION androidx.annotation.Nullable
GLUECODIUM_KOTLIN_PACKAGE com.here.android
GLUECODIUM_KOTLIN_INTERNAL_PACKAGE lorem.ipsum
GLUECODIUM_CPP_INTERNAL_NAMESPACE "lorem_ipsum::test"
GLUECODIUM_CBRIDGE_INTERNAL_PREFIX "libfunctional_"
GLUECODIUM_DART_LIBRARY_NAME "functional"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright (C) 2016-2025 HERE Europe B.V.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
* License-Filename: LICENSE
*/

package com.here.android

import android.annotation.SuppressLint
import android.app.Application
import android.util.Log
import com.here.android.lorem.ipsum.NativeBase
import com.here.gluecodium.test.functional.BuildConfig
import org.powermock.reflect.Whitebox
import org.robolectric.shadows.ShadowLog
import java.io.File

class RobolectricApplication : Application() {
private val TAG: String = RobolectricApplication::class.java.getSimpleName()

override fun onCreate() {
super.onCreate()

if (isFirstTime) {
isFirstTime = false

loadNativeLibraries();
Runtime.getRuntime().addShutdownHook(Thread{
try {
Whitebox.invokeMethod(NativeBase::class.java, "cleanUpQueue")
} catch (e: Exception) {
e.printStackTrace()
}
})
}
}

/**
* Separate method to load libraries in case you want to subclass and can't load in onCreate().
*/
@SuppressLint("UnsafeDynamicallyLoadedCode")
private fun loadNativeLibraries() {
val appLibraryPath: java.io.File = java.io.File(BuildConfig.NATIVE_LIB_HOST_DIR)

Log.d(TAG, "loadNativeLibraries: Using app library path: " + appLibraryPath)

val files = appLibraryPath.listFiles {
dir, name -> name.contains(".so") || name.endsWith(".dylib")
}

for (sharedObject in files) {
Log.i(TAG, "loadNativeLibraries: Loading app library '" + sharedObject.getName() + "'...")
System.load(sharedObject.getAbsolutePath())
}
}

companion object {
private var isFirstTime: Boolean = true

init {
ShadowLog.stream = System.out // Android logcat output.
}
}
}
Loading

0 comments on commit 739218e

Please sign in to comment.