Compile program for the Android platform

Introduced classes

Redefined classes

redef class JavaClassTemplate

nitc :: android $ JavaClassTemplate

Java class source template
redef class ToolContext

nitc :: android $ ToolContext

Global context for tools

All class definitions

redef class JavaClassTemplate

nitc :: android $ JavaClassTemplate

Java class source template
redef class ToolContext

nitc :: android $ ToolContext

Global context for tools
package_diagram nitc::android android nitc::abstract_compiler abstract_compiler nitc::android->nitc::abstract_compiler nitc\>ffi\> ffi nitc::android->nitc\>ffi\> nitc::android_annotations android_annotations nitc::android->nitc::android_annotations nitc\>platform\> platform nitc::abstract_compiler->nitc\>platform\> nitc::mixin mixin nitc::abstract_compiler->nitc::mixin counter counter nitc::abstract_compiler->counter nitc::pkgconfig pkgconfig nitc::abstract_compiler->nitc::pkgconfig nitc\>ffi\>->nitc\>platform\> nitc\>modelize\> modelize nitc\>ffi\>->nitc\>modelize\> nitc\>nitni\> nitni nitc\>ffi\>->nitc\>nitni\> nitc nitc nitc\>ffi\>->nitc nitc::app_annotations app_annotations nitc::android_annotations->nitc::app_annotations ...nitc\>platform\> ... ...nitc\>platform\>->nitc\>platform\> ...nitc::mixin ... ...nitc::mixin->nitc::mixin ...counter ... ...counter->counter ...nitc::pkgconfig ... ...nitc::pkgconfig->nitc::pkgconfig ...nitc\>modelize\> ... ...nitc\>modelize\>->nitc\>modelize\> ...nitc\>nitni\> ... ...nitc\>nitni\>->nitc\>nitni\> ...nitc ... ...nitc->nitc ...nitc::app_annotations ... ...nitc::app_annotations->nitc::app_annotations nitc::compiler compiler nitc::compiler->nitc::android nitc::nitc nitc nitc::nitc->nitc::compiler nitc::nitc... ... nitc::nitc...->nitc::nitc

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module annotation

nitc :: annotation

Management and utilities on annotations
module app_annotations

nitc :: app_annotations

Annotations to gather metadata on app.nit projects
module array

core :: array

This module introduces the standard array structure.
module auto_super_init

nitc :: auto_super_init

Computing of super-constructors that must be implicitly called at the begin of constructors.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module c

nitc :: c

Support for nesting C code within a Nit program using its FFI
module c_compiler_options

nitc :: c_compiler_options

Offers the annotations cflags and ldflags to specify
module c_tools

nitc :: c_tools

provides tools to write C .c and .h files
module caching

serialization :: caching

Services for caching serialization engines
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module console

console :: console

Defines some ANSI Terminal Control Escape Sequences.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module counter

counter :: counter

Simple numerical statistical analysis and presentation
module cpp

nitc :: cpp

Supports the use of the C++ language through the FFI
module csv

csv :: csv

CSV document handling.
module digraph

graph :: digraph

Implementation of directed graphs, also called digraphs.
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module explain_assert_api

nitc :: explain_assert_api

Explain failed assert to the console (service declaration only)
module extern_classes

nitc :: extern_classes

Manages all extern classes and their associated foreign type.
module extra_java_files

nitc :: extra_java_files

Intro the annotation extra_java_files to compile extra java files
module ffi_base

nitc :: ffi_base

Tools and utilities for implement FFI with different languages
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module flow

nitc :: flow

Intraprocedural static flow.
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module header_dependency

nitc :: header_dependency

Tracks which modules has public header code that must be imported
module ini

ini :: ini

Read and write INI configuration files
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module java

nitc :: java

FFI support for the Java language
module kernel

core :: kernel

Most basic classes and methods.
module lexer

nitc :: lexer

Lexer and its tokens.
module lexer_work

nitc :: lexer_work

Internal algorithm and data structures for the Nit lexer
module light_c

nitc :: light_c

Support for nesting C code within a Nit program using its FFI
module light_ffi

nitc :: light_ffi

Light FFI support, independent of the compiler
module light_ffi_base

nitc :: light_ffi_base

Tools and utilities for implement FFI with different languages
module list

core :: list

This module handle double linked lists
module literal

nitc :: literal

Parsing of literal values in the abstract syntax tree.
module loader

nitc :: loader

Loading of Nit source files
module local_var_init

nitc :: local_var_init

Verify that local variables are initialized before their usage
module location

nitc :: location

Nit source-file and locations in source-file
module math

core :: math

Mathematical operations
module mdoc

nitc :: mdoc

Documentation of model entities
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module mixin

nitc :: mixin

Loading and additional module refinements at link-time.
module mmodule

nitc :: mmodule

modules and module hierarchies in the metamodel
module mmodule_data

nitc :: mmodule_data

Define and retrieve data in modules
module model

nitc :: model

Classes, types and properties
module model_base

nitc :: model_base

The abstract concept of model and related common things
module modelbuilder_base

nitc :: modelbuilder_base

Load nit source files and build the associated model
module modelize

nitc :: modelize

Create a model from nit source files
module modelize_class

nitc :: modelize_class

Analysis and verification of class definitions to instantiate model element
module modelize_property

nitc :: modelize_property

Analysis and verification of property definitions to instantiate model element
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module mpackage

nitc :: mpackage

Modelisation of a Nit package
module native

core :: native

Native structures for text and bytes
module nitni

nitc :: nitni

Native interface related services (used underneath the FFI)
module nitni_base

nitc :: nitni_base

Native interface related services (used underneath the FFI)
module nitni_callbacks

nitc :: nitni_callbacks

nitni services related to callbacks (used underneath the FFI)
module nitpm_shared

nitc :: nitpm_shared

Services related to the Nit package manager
module numeric

core :: numeric

Advanced services for Numeric types
module objc

nitc :: objc

FFI support for Objective-C
module opts

opts :: opts

Management of options on the command line
module ordered_tree

ordered_tree :: ordered_tree

Manipulation and presentation of ordered trees.
module parser

nitc :: parser

Parser.
module parser_nodes

nitc :: parser_nodes

AST nodes of the Nit language
module parser_prod

nitc :: parser_prod

Production AST nodes full definition.
module parser_util

nitc :: parser_util

Utils and tools related to parsers and AST
module parser_work

nitc :: parser_work

Internal algorithm and data structures for the Nit parser
module phase

nitc :: phase

Phases of the processing of nit programs
module pkgconfig

nitc :: pkgconfig

Offers the PkgconfigPhase to use the external program "pkg-config" in order
module platform

nitc :: platform

Platform system, used to customize the behavior of the compiler.
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module rapid_type_analysis

nitc :: rapid_type_analysis

Rapid type analysis on the AST
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module scope

nitc :: scope

Identification and scoping of local variables and labels.
module semantize

nitc :: semantize

Process bodies of methods in regard with the model.
module serialization

serialization :: serialization

General serialization services
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module tables

nitc :: tables

Module that interfaces the parsing tables.
module template

template :: template

Basic template system
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module toolcontext

nitc :: toolcontext

Common command-line tool infrastructure than handle options and error messages
module typing

nitc :: typing

Intraprocedural resolution of static types and OO-services
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O
module version

nitc :: version

This file was generated by git-gen-version.sh

Parents

module abstract_compiler

nitc :: abstract_compiler

Abstract compiler
module android_annotations

nitc :: android_annotations

Additionnal annotations to gather metadata on Android projects
module ffi

nitc :: ffi

Full FFI support, independent of the compiler

Children

module compiler

nitc :: compiler

Compilation to C

Descendants

module a_star-m

a_star-m

module nitc

nitc :: nitc

A Nit compiler
# Compile program for the Android platform
module android

import platform
import compiler::abstract_compiler
import ffi
intrude import ffi::extra_java_files
import android_annotations

redef class ToolContext
	redef fun platform_from_name(name)
	do
		if name == "android" then return new AndroidPlatform
		return super
	end
end

class AndroidPlatform
	super Platform

	redef fun name do return "android"

	redef fun supports_libgc do return true

	redef fun supports_libunwind do return false

	redef fun supports_linker_script do return false

	redef fun toolchain(toolcontext, compiler) do return new AndroidToolchain(toolcontext, compiler)
end

class AndroidToolchain
	super MakefileToolchain

	var android_project_root: nullable String = null

	redef fun compile_dir
	do
		var android_project_root = "{root_compile_dir}/android/"
		self.android_project_root = android_project_root
		return "{android_project_root}/app/src/main/cpp/"
	end

	redef fun default_outname do return "{super}.apk"

	private fun share_dir: Text
	do
		var nit_dir = toolcontext.nit_dir or else "."
		return (nit_dir/"share").realpath
	end

	private fun gradlew_dir: Text do return share_dir / "android-gradlew"

	redef fun write_files(compile_dir, cfiles)
	do
		var android_project_root = android_project_root.as(not null)
		var android_app_root = android_project_root/"app"
		var project = new AndroidProject(toolcontext.modelbuilder, compiler.mainmodule)
		var release = toolcontext.opt_release.value

		# Compute the root of the project where could be assets and resources
		var project_root = "."
		var mpackage = compiler.mainmodule.first_real_mmodule.mpackage
		if mpackage != null then
			var root = mpackage.root
			if root != null then
				var filepath = root.filepath
				if filepath != null then
					project_root = filepath
				end
			end
		end

		# Gather app configs
		# ---

		var app_name = project.name
		var app_package = project.namespace
		var app_version = project.version

		var app_min_api = project.min_api
		if app_min_api == null then app_min_api = 10

		var app_target_api = project.target_api
		if app_target_api == null then app_target_api = app_min_api

		var app_max_api = ""
		if project.max_api != null then app_max_api = "maxSdkVersion  {project.max_api.as(not null)}"

		# Create basic directory structure
		# ---

		android_project_root.mkdir
		android_app_root.mkdir
		(android_app_root/"libs").mkdir

		var android_app_main = android_app_root / "src/main"
		android_app_main.mkdir
		(android_app_main / "java").mkdir

		# /app/build.gradle
		# ---

		# Use the most recent build_tools_version
		var android_home = "ANDROID_HOME".environ
		if android_home.is_empty then android_home = "HOME".environ / "Android/Sdk"
		var build_tools_dir = android_home / "build-tools"
		var available_versions = build_tools_dir.files

		var build_tools_version
		if available_versions.is_empty then
			print_error "Error: found no Android build-tools, install one or set ANDROID_HOME."
			return
		else
			alpha_comparator.sort available_versions
			build_tools_version = available_versions.last
		end

		# Gather ldflags for Android
		var ldflags = new Array[String]
		var platform_name = "android"
		for mmodule in compiler.mainmodule.in_importation.greaters do
			if mmodule.ldflags.keys.has(platform_name) then
				ldflags.add_all mmodule.ldflags[platform_name]
			end
		end

		# Platform version for OpenGL ES
		var platform_version = ""
		if ldflags.has("-lGLESv3") then
			platform_version = "def platformVersion = 18"
		else if ldflags.has("-lGLESv2") then
			platform_version = "def platformVersion = 12"
		end

		# TODO make configurable client-side
		var compile_sdk_version = app_target_api

		var local_build_gradle = """
apply plugin: 'com.android.application'

{{{platform_version}}}

android {
    compileSdkVersion {{{compile_sdk_version}}}
    buildToolsVersion "{{{build_tools_version}}}"

    defaultConfig {
        applicationId "{{{app_package}}}"
        minSdkVersion {{{app_min_api}}}
        {{{app_max_api}}}
        targetSdkVersion {{{app_target_api}}}
        versionCode {{{project.version_code}}}
        versionName "{{{app_version}}}"
        ndk {
            abiFilters 'armeabi-v7a', 'x86'
        }
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_TOOLCHAIN=gcc"
            }
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
        }
    }

    lintOptions {
       abortOnError false
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
}
"""
		local_build_gradle.write_to_file "{android_project_root}/app/build.gradle"

		# TODO add 'arm64-v8a' and 'x86_64' to `abiFilters` when the min API is available

		# ---
		# Other, smaller files

		# /build.gradle
		var global_build_gradle = """
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.0.0'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}
"""
		global_build_gradle.write_to_file "{android_project_root}/build.gradle"

		# /settings.gradle
		var settings_gradle = """
include ':app'
"""
		settings_gradle.write_to_file "{android_project_root}/settings.gradle"

		# /gradle.properties
		var gradle_properties = """
org.gradle.jvmargs=-Xmx1536m
"""
		gradle_properties.write_to_file "{android_project_root}/gradle.properties"

		# Insert an importation of the generated R class to all Java files from the FFI
		for mod in compiler.mainmodule.in_importation.greaters do
			var java_ffi_file = mod.java_file
			if java_ffi_file != null then java_ffi_file.add "import {app_package}.R;"
		end

		# compile normal C files
		super

		# ---
		# /app/src/main/cpp/CMakeLists.txt

		# Gather extra C files generated elsewhere than in super
		for f in compiler.extern_bodies do
			if f isa ExternCFile then cfiles.add(f.filename.basename)
		end

		# Prepare for the CMakeLists format
		var target_link_libraries = new Array[String]
		for flag in ldflags do
			if flag.has_prefix("-l") then
				target_link_libraries.add flag.substring_from(2)
			end
		end

		# Download the libgc/bdwgc sources
		var share_dir = share_dir
		if not share_dir.file_exists then
			print "Android project error: Nit share directory not found, please use the environment variable NIT_DIR"
			exit 1
		end

		var bdwgc_dir = "{share_dir}/android-bdwgc/bdwgc"
		if not bdwgc_dir.file_exists then
			toolcontext.exec_and_check(["{share_dir}/android-bdwgc/setup.sh"], "Android project error")
		end

		# Compile the native app glue lib if used
		var add_native_app_glue = ""
		if target_link_libraries.has("native_app_glue") then
			add_native_app_glue = """
add_library(native_app_glue STATIC ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c)
"""
		end

		var cmakelists = """
cmake_minimum_required(VERSION 3.4.1)

{{{add_native_app_glue}}}


# libgc/bdwgc

## The source is in the Nit repo
set(lib_src_DIR {{{bdwgc_dir}}})
set(lib_build_DIR ../libgc/outputs)
file(MAKE_DIRECTORY ${lib_build_DIR})

## Config
add_definitions("-DALL_INTERIOR_POINTERS -DGC_THREADS -DUSE_MMAP -DUSE_MUNMAP -DJAVA_FINALIZATION -DNO_EXECUTE_PERMISSION -DGC_DONT_REGISTER_MAIN_STATIC_DATA")
set(enable_threads TRUE)
set(CMAKE_USE_PTHREADS_INIT TRUE)

## link_map is already defined in Android
add_definitions("-DGC_DONT_DEFINE_LINK_MAP")

## Silence warning
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99")

add_subdirectory(${lib_src_DIR} ${lib_build_DIR} )
include_directories(${lib_src_DIR}/include)


# Nit generated code

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DANDROID -DWITH_LIBGC")

# Export ANativeActivity_onCreate(),
# Refer to: https://github.com/android-ndk/ndk/issues/381.
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -u ANativeActivity_onCreate")

#           name      so       source
add_library(nit_app   SHARED   {{{cfiles.join("\n\t")}}} )

target_include_directories(nit_app PRIVATE ${ANDROID_NDK}/sources/android/native_app_glue)


# Link!

target_link_libraries(nit_app gc-lib
	{{{target_link_libraries.join("\n\t")}}})
"""
		cmakelists.write_to_file "{android_app_main}/cpp/CMakeLists.txt"

		# ---
		# /app/src/main/res/values/strings.xml for app name

		# Set the default pretty application name
		var res_values_dir = "{android_app_main}/res/values/"
		res_values_dir.mkdir
"""<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">{{{app_name}}}</string>
</resources>""".write_to_file res_values_dir/"strings.xml"

		# ---
		# Copy assets, resources in the Android project

		## Collect path to all possible folder where we can find the `android` folder
		var app_files = [project_root]
		app_files.add_all project.files

		for path in app_files do
			# Copy the assets folder
			var assets_dir = path / "assets"
			if assets_dir.file_exists then
				assets_dir = assets_dir.realpath
				toolcontext.exec_and_check(["cp", "-r", assets_dir, android_app_main], "Android project error")
			end

			# Copy the whole `android` folder
			var android_dir = path / "android"
			if android_dir.file_exists then
				android_dir = android_dir.realpath
				for f in android_dir.files do
					toolcontext.exec_and_check(["cp", "-r", android_dir / f, android_app_main], "Android project error")
				end
			end
		end

		# ---
		# Generate AndroidManifest.xml

		# Is there an icon?
		var resolutions = ["ldpi", "mdpi", "hdpi", "xhdpi", "xxhdpi", "xxxhdpi", "anydpi", "anydpi-v26"]
		var icon_name = null
		var has_round = false

		for res in resolutions do
			# New style mipmap
			if "{project_root}/android/res/mipmap-{res}/ic_launcher_round.png".file_exists then
				has_round = true
			end
			if "{project_root}/android/res/mipmap-{res}/ic_launcher.png".file_exists then
				icon_name = "@mipmap/ic_launcher"
				break
			end
			if "{project_root}/android/res/mipmap-{res}/ic_launcher.xml".file_exists then
				icon_name = "@mipmap/ic_launcher"
				break
			end
		end
		if icon_name == null then
			# Old style drawable-hdpi/icon.png
			for res in resolutions do
				var path = project_root / "android/res/drawable-{res}/icon.png"
				if path.file_exists then
					icon_name = "@drawable/icon"
					break
				end
			end
		end

		var icon_declaration
		if icon_name != null then
			icon_declaration = "android:icon=\"{icon_name}\""
			if app_target_api >= 25 and has_round then
				icon_declaration += "\n\t\tandroid:roundIcon=\"@mipmap/ic_launcher_round\""
			end
		else icon_declaration = ""

		# TODO android:roundIcon

		# Copy the Java sources files
		var java_dir = android_app_main / "java/"
		java_dir.mkdir
		for mmodule in compiler.mainmodule.in_importation.greaters do
			var extra_java_files = mmodule.extra_java_files
			if extra_java_files != null then for file in extra_java_files do
				var path = file.src_path
				var dir = file.filename.dirname
				(java_dir/dir).mkdir
				path.file_copy_to(java_dir/file.filename)
			end
		end

		# ---
		# /app/src/main/AndroidManifest.xml

		var manifest_file = new FileWriter.open(android_app_main / "AndroidManifest.xml")
		manifest_file.write """
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="{{{app_package}}}">

    <application
		android:hasCode="true"
		android:allowBackup="true"
		android:label="@string/app_name"
		{{{icon_declaration}}}>
"""

		for activity in project.activities do
			manifest_file.write """
        <activity android:name="{{{activity}}}"
                {{{project.manifest_activity_attributes.join("\n")}}}
                {{{icon_declaration}}}>

            <meta-data android:name="android.app.lib_name" android:value="nit_app" />

            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
"""
		end

		manifest_file.write """
{{{project.manifest_application_lines.join("\n")}}}

    </application>

{{{project.manifest_lines.join("\n")}}}

</manifest>
"""
		manifest_file.close
	end

	redef fun write_makefile(compile_dir, cfiles)
	do
		# Do nothing, already done in `write_files`
	end

	redef fun compile_c_code(compile_dir)
	do
		var android_project_root = android_project_root.as(not null)
		var release = toolcontext.opt_release.value

		# Compile C and Java code into an APK file
		var verb = if release then "assembleRelease" else "assembleDebug"
		var args = [gradlew_dir/"gradlew", verb, "-p", android_project_root]
		if toolcontext.opt_verbose.value <= 1 then args.add "-q"
		toolcontext.exec_and_check(args, "Android project error")

		# Move the APK to the target
		var outname = outfile(compiler.mainmodule)
		if release then
			var apk_path = "{android_project_root}/app/build/outputs/apk/release/app-release-unsigned.apk"

			# Sign APK
			var keystore_path= "KEYSTORE".environ
			var key_alias= "KEY_ALIAS".environ
			var tsa_server= "TSA_SERVER".environ

			if key_alias.is_empty then
				toolcontext.warning(null, "key-alias",
					"Warning: the environment variable `KEY_ALIAS` is not set, the APK file will not be signed.")

				# Just move the unsigned APK to outname
				args = ["mv", apk_path, outname]
				toolcontext.exec_and_check(args, "Android project error")
				return
			end

			# We have a key_alias, try to sign the APK
			args = ["jarsigner", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", apk_path, key_alias]

			## Use a custom keystore
			if not keystore_path.is_empty then args.add_all(["-keystore", keystore_path])

			## Use a TSA server
			if not tsa_server.is_empty then args.add_all(["-tsa", tsa_server])

			toolcontext.exec_and_check(args, "Android project error")

			# Clean output file
			if outname.to_path.exists then outname.to_path.delete

			# Align APK
			args = ["zipalign", "4", apk_path, outname]
			toolcontext.exec_and_check(args, "Android project error")
		else
			# Move to the expected output path
			args = ["mv", "{android_project_root}/app/build/outputs/apk/debug/app-debug.apk", outname]
			toolcontext.exec_and_check(args, "Android project error")
		end
	end
end

redef class JavaClassTemplate
	redef fun write_to_files(compdir)
	do
		var jni_path = "cpp/"
		if compdir.has_suffix(jni_path) then
			var path = "{compdir.substring(0, compdir.length-jni_path.length)}/java/"
			return super(path)
		else return super
	end
end
src/platform/android.nit:17,1--543,3