Allow setting Gradle JVM args in Project.xml
Some projects will require to allocate more memory for the gradle build, and it is a little annoying to have to restore the changed gradle.properties file each build.
For less-common changes, I'd recommend using a template. No need to make everything configurable from project.xml.
I perfectly agree that it is not the case to add every Gradle parameter to project.xml. Exposing more parameters could seem handy but it ultimately carries the need to maintain and devote time to them through releases.
I'll make the case for this one.
Personally, I do not want to care if Gradle exists at all. I just want to build and publish my games, and Lime is doing a lovely work in all the other targets. Unfortunately, Gradle is unable to asses its own ram requirements during a build, and the requirements themselves are a bit unpredictable. In my experience, Gradle did complain about wrong ram requirements when I inserted a bunch of image assets, or when I added some extensions (like hxcodec), or when i tried to build a bundle. But what's bad about this, is that in those cases Gradle will just exit to the command line, giving small pointers to how you need to set a certain precise "jvmargs" parameter: "you need to re-launch with these arguments because I tried to use 128M and your project didn't fit".
So, the real PR here should be that I would want Lime to shield me from this insanity, like all the other targets. That, unfortunately, is nearly impossible because of Gradle. It would be the best if Gradle could use all the ram it needs without complaining.
The second best next thing that Lime can do is: if Gradle is telling me to "please set jvmargs as: 'xxxx'", I would like Lime to give me a parameter where i can copy&paste these arguments, without having to ever know what they are or what Gradle is, and without having to define and maintain several templates for a single string that I need to set for certain builds but not others. In a perfect world we shouldn't have to do this, but Gradle is what it is.
I'm sure this is the same reasoning behind the existence of gradle-version and gradle-plugin arguments in project.xml. It's not that people developed a certain taste in different Gradle version, like fine wine, so that they're going with "hmm... for this project... I believe the best gradle version is 7.6.2... but I'll match it with a plugin version 6.5". In my case it's 100% because if I try to open my android project with android studio, it will start complaining that your gradle is obsolete, that a certain plugin version is the best, and then crashing with absurd errors until you convert you project to that gradle version.
Surely you could define a template for those to, but it would make maintaining you project through the years more complex, and this just to pass an argument that won't impact your game.
So with this context in mind, in short:
- it's a build parameter that may be required for a certain "build task" in your project.xml, but not others: for example some of my projects are fine with the default jvmargs, unless I'm building an AAB package or targeting a different gradle version;
- different gradle version/plugin version may have incompatible jvm args, so if you have multiple build targets that require different gradle versions (for example to target different Android Studio versions) you'll have to maintain one template for each build target;
- libraries/extensions might want to set a different default value. Especially if they have multiple build configurations (as in
if feature_is_present, then set gradle_plugin=x.x.x and increase gradle memory requirements); - having to maintain a separate template could be error prone and would potentially require adjusting it for every new release of lime: fine, if you have an already complex project; not really fine, if just to give more memory to the build system, once;
- if someone has an automated build system or is using github actions, having at least an environment variable (if not a project.xml attribute) would be less messy than a template. As Gradle does not support an environment variable for this, it's great when "downstream" build systems add this as a feature. Cordova for example allows it to be set via the
cordova build android --jvmargscommand line (while, notably, all the other gradle parameters require defining a template). - it would be great to have
gradle-jvmargsin the same<section>as these other build directives, to enable/disable them at once.
In conclusion, I believe that jvmargs is not in the same league of all the other possible gradle parameters. I agree with you that if someone wants to configure the gradle cache, or how many processes, and fine-tune their priority then, man, you have requirements well above the common user, please use a template (for your own sake). On the contrary, jvmargs would be useful to be set in project.xml mostly for people that don't even know what Gradle is.
Do you believe it would be better to have it as an env variable that is then passed to the gradle command line (in the same spirit of ANDROID_GRADLE_TASK)?
Here's an idea: allow passing arbitrary key-value pairs to gradle.properties. Saves us having to hash out what is and isn't important. It may not be the prettiest, but it works just like how you pass extra attributes to AndroidManifest.xml, so there's consistency.
<config:android>
<application android:appCategory="game" android:supportsRtl="true" />
<activity android:immersive="false" />
<gradle-properties org.gradle.jvmargs='-Xmx512m "-XX:MaxMetaspaceSize=384m"' />
</config:android>
And there's another more verbose option if string escaping is a problem.
<config:android>
<gradle-properties>
<org.gradle.jvmargs>-Xmx512m "-XX:MaxMetaspaceSize=384m"</org.gradle.jvmargs>
</gradle-properties>
</config:android>
Yeah, I believe your idea is more complete. Totally cool!
Is there still time to merge this for 8.3.0 release?
A bit unrelated comment:
Would be also cool to be able to add something to build.gradle files, both root level and app level. Had to do so when integrating Firebase (https://firebase.google.com/docs/android/setup#groovy) . I needed to add a classpath to the dependencies section, right where this notice is placed :)) :
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
Without this the Google Services gradle plugin just doesn't work.
Then I needed to add implementation (to dependencies) and the Google Services plugin activation to the app level build.gradle. I made the copies of the files and set my templates dir, as suggested, but this is not a good approach, because a) the developer has to check the template build.gradle files to keep them up-to-date with each Lime release and b) another integration may also require the same approach so one of the templates will be overwritten.
By the way, the Google Services plugin works only in the build.gradle file that has com.android.application plugin applied, meaning there is no way to make it work in an extension (that has 'com.android.library' plugin applied).
Adding plugins to app/build.gradle makes sense and generalizes to a lot of use cases, so I've submitted #1999.
Less sure about the root-level dependency. How common is it that someone will need to add something there?
Adding plugins to app/build.gradle makes sense and generalizes to a lot of use cases, so I've submitted #1999.
Wow, cool, thank! That was fast )))
Any chance to have the ability to add implementation dependencies to app level build.gradle too, like these required by Firebase integration:
dependencies {
implementation(platform("com.google.firebase:firebase-bom:34.5.0"))
. . . // other FireBase API implementations may go here
}
The template already has the section to copy the dependencies from the libs:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
::if (ANDROID_LIBRARY_PROJECTS)::::foreach (ANDROID_LIBRARY_PROJECTS)::implementation project(':deps:::name::')
::end::::end::
}
It would be helpful to be able to add custom implementations here.
Less sure about the root-level dependency. How common is it that someone will need to add something there?
To be honest, this is the first time I had to add anything to the root-level build.gradle. And some time ago the FireBase integration worked will without this and it even worked when integration as a library. But for now it seems that this is a must for FireBase integration, because the GoogleServices plugin is very... I would say fragile - it fails to process the project if anything is incorrect in the integration flow.
Any chance to have the ability to add implementation dependencies to app level
build.gradletoo
I'm fairly certain a plugin can do that, and the PR allows you to specify plugins. I know it's an extra step, but it keeps the template cleaner.
I'm fairly certain a plugin can do that, and the PR allows you to specify plugins. I know it's an extra step, but it keeps the template cleaner.
In fact, you're probably right and the plugin will process the implementation dependencies inheritd from the lbs. I will try this set-up next week and share here.