Switching to Gradle

OpenFL currently uses Ant to build for Android, but that’s deprecated. The new system is called Gradle, and from all accounts it’s both easier to use and more powerful. Plus, Android libraries tell you how to add them to a Gradle project, but usually don’t have instructions for Ant.

Gradle can import Ant projects, but that isn’t a perfect solution. Ideally, OpenFL should create a proper Gradle project, using Gradle’s folder structure and letting Gradle handle dependencies.

Also, there needs to be a mechanism to add to the build.gradle file. This could be a tag in project.xml, or part of an Android extension, or both.

I’m going to try and work through all these things, and I’ll post my progress in this thread. If you’d like to help, I’d appreciate it.

(That’s all for now; I’ll make a sample project later today.)

2 Likes

You’re in for a challenging path. Last time I checked, the Gradle plugin to work with JNI stuff was still in early alpha.
Maybe this could help you a bit, if it’s actually working:

Simple Gradle build

I’m going to try to do the absolute bare minimum that can be considered a “Gradle build.” But even before that, I need to install Gradle.

Installation

Follow the instructions here to install Gradle. However, I decided to install Android Studio instead, because it’ll come in handy later on. (Android Studio comes with Gradle.)

Once you install either of those, add Gradle’s bin folder to your system path, and run “gradle -v” to make sure everything’s set up properly. Assuming OpenFL can compile for Android, you should have everything you need.

Sample project

I’m going to use DisplayingABitmap as my test project. I want to build it using OpenFL, but I don’t need to install it yet. The build process sets up an Android project, and that’s what I’m going to convert to Gradle.

> openfl create DisplayingABitmap
> cd DisplayingABitmap
> openfl build android

Once that finishes, the Android project will be located under DisplayingABitmap/Export/android/bin.

You might wonder about the haxe and obj folders, but they aren’t part of the Android project; they’re used to create the Android project. If you look inside obj, you’ll find C++ source files, plus one big C++ binary named libApplicationMain-v7.so. This binary has already been copied into bin/libs/armeabi, so you could delete it if you wanted. It might slow down your next build, but it wouldn’t stop this one.

Anyway, back to the bin folder with the Android project. This is an Ant project, with an Ant build file: build.xml. I could build it using Ant (which is what Lime does), but my goal right now is to build with Gradle.

The build

The quickest, easiest way to do this is to tell Gradle “import the existing Ant build file.” I’m going to make a file named build.gradle containing one line of code:

ant.importBuild 'build.xml'

Now I check what tasks Gradle can perform:

> cd Export/android/bin
> gradle tasks
...
android_rules.clean - Removes output files created by other targets.
android_rules.debug - Builds the application and signs it with a debug key.
android_rules.emma
android_rules.help
android_rules.install - Installs the newly build package. Must be used in conjunction with a build target (debug/release/instrument). If the application was previously installed, the application is reinstalled if the signature matches.
...

First, I’m going to have it “clean” the project (this will only delete a few files; it won’t recompile all the C++ code like a clean OpenFL build does). Otherwise, Gradle will just reuse OpenFL’s build.

Next, I want to build and install a debug version. (No need to worry about release keys, which are a whole different can of worms.)

> gradle debug install

The output doesn’t include an “install success” message, but when I check my device…

Problems to work on

  • No one wants to manually run the Gradle build every time.
  • The build.gradle file is at risk of being deleted by openfl clean.
  • The Ant build is part of Lime’s build process, coming right after Lime finishes making the Android project. We need that Android project, but we’d prefer to skip the Ant build.

That won’t solve your problem. You want to be able to do everything that the current Ant script does but using Gradle itself. Importing the Ant build script isn’t a solution IMHO. You’re only adding a wrapper around it that way.

Right, I’m aware that it’ll be a lot harder than this. Later on, I’ll be restructuring the Android project, adding a build.gradle template, messing with Lime’s build tools, and possibly more. But for that post, my only goal was to test the simplest possible case and make sure everything worked.

Think of it as a “Hello World” exercise, or perhaps “Hello Gradle.”

1 Like

Updating Lime’s build process

It’s time to make Lime run Gradle instead of Ant. Everything I did manually in my above post, I want Lime to do automatically.

I forked Lime and made a Gradle branch, so keep an eye on that.

Creating build.gradle

Lime uses templates when creating an Android project. In other words, it takes all the files in <Lime directory>/templates/android/template, and copies them over. (It does some processing first, but that isn’t important here.)

To make Lime create build.gradle, all I need to do is add it to that folder, like so.

Running Gradle

This part is a little trickier, but not much. The file that calls Ant is AndroidHelper.hx, and as it turns out that the two tools are similar enough that all I have to do is replace “ant” with “gradle.”. (It might be safe to get rid of that part that deletes a file, but I don’t know.)

I believe GRADLE_HOME is set by Gradle’s installer, but I can confirm it isn’t set by Android Studio. Since I chose to install Android Studio rather than Gradle on its own, I have to set the it myself. After poking through Android Studio’s folder, I conclude that Android Studio/gradle/gradle-2.10 is the correct path, and add the environment variable. (I know the path is right because it contains a bin folder containing an executable named “gradle.”)

I also execute tools.hxml (inside <Lime directory>/tools) to apply the changes I made to AndroidHelper.hx, and I copy the ndlls from Lime 2.9.1 because those are a hassle to compile.

Result: lime build android worked on the first try, and used Gradle instead of Ant. Success!

Problems to work on

  • This is still, essentially, an Ant project; Gradle does nothing but emulate Ant.

GRADLE_HOME isn’t set on Mac and Linux. It’s a manual step that you have to do if you want to have a working command line environment on those platforms.

i.e. I do have a GRADLE_HOME defined in my .bashrc but it doesn’t point to the version distributed with Android Studio but to a different one I use to compile my projects from the command line.

I’d say you should warn the user if GRADLE_HOME isn’t set.

During the Android setup process you’re asked to input ant path (or choose openfl install it for you).

openfl setup android

@player_03 I’ll try to help on this later today, if you didn’t joined the openfl slack do it :slight_smile:

Another thing, maybe OT now but we can keep it in mind, is to add support to jumbo mode in the new template.
http://mutualmobile.com/posts/dex-64k-limit-not-problem-anymore-almost

If you’re talking about MultiDex, that’s painful. If you guys are going to add support for MultiDex, please do it in a way that it’s turned on only when you exceed the 64k methods limit because it slows down the compilation of Android projects by a huge factor. Just keep that in mind as well :smiley:

Yes, sure as an option. But I found that many people asked for it.

Agreed, this is probably the right time to set up Gradle. However, it might be good to add a warning in AndroidBuilder.hx, to let people know if they need to run the setup process again.

This doesn’t need to be officially supported. As long as you can insert code into build.gradle, you can add whatever plugins your project needs, including this one.

Please, do not run gradle that is installed in system or any specific gradle version. There is a thing calles gradle wrapper - https://guides.codepath.com/android/Getting-Started-with-Gradle

This thing allows to successfully compile gradle projects even if different gradle version is installed (or even not installed at all, however I not tested it).

I found a better explanation of the wrapper. It sounds good, but I think it’s meant for a different workflow.

The problem is, Gradle is required to generate the Gradle wrapper. If you’re sharing the Android project, that makes perfect sense. You’ll generate the wrapper, and then distribute it along with your project. Then when other people try to build your project, they’ll use the same version of Gradle as you are.

But OpenFL developers won’t share the Android project; they’ll share the OpenFL project. Lime will take that project and generate a brand-new Android project. Certainly, Lime can generate a Gradle wrapper in the Android project, but only if Gradle is already installed on the system.

On the plus side, it’s possible to build a wrapper targeting a Gradle version that isn’t currently installed. So one option is to let people set gradle-version from project.xml. Then Lime will build a Gradle wrapper for that version, and then that version of Gradle will build the project.

Alternately, we could include the Gradle wrapper files in templates/android/template. It looks like they don’t include any project-specific information, so copying them should work fine. Unfortunately, there’s no way to automatically use the latest version of Gradle. But that’s also what happens if you run without the wrapper, so maybe templates are the way to go.

You should put wrapper files inside android template.

Generating wrapper from lime is wrong idea. Imagine, that user has… say gradle v10 installed. But all your gradle scripts (including script that should generate wrapper) is targeting gradle v2. Probably you wouln’t be able even to generate wrapper.

On other side if you have wrapper files inside template - everything would work as expected.

There is really no reason to always use latest gradle version. Currently you can choose any gradle v2.x with new android plugin (because gradle 1.x has older android plugin with limited NDK support).

P.S. I work as Android developer for last 4 years, so feel free to ask me anything about Android :slight_smile:

How’s this look?

@player_03 I think that instead of importing build.xml (ant file) we should write our own build.gradle file.

Agree with @vidueirof

If you allow me to help, I can try to write grable build file at monday.

I was mostly asking about the wrapper implementation. Removing build.xml is on my list, but I didn’t have time for it last night.

Wrapper looks good. I would recommend one minor change to build.gradle - I will post tomorrow.

Something like this:

ant.importBuild 'build.xml'

task wrapper(type: Wrapper) {
    gradleVersion = '2.10'
}

This allow developers to re-generate wrapper files if they really need so.