Android gradle plugin generates tons of .rawproto
files in build/android-profile
directory. What are they used for? Is there a way to disable this madness or automatically delete them?
I've been bugged by it for a long time, and now that I noticed there's gigabytes of this hogging my smallish SSD, I've decided to figure out a way to disable it. For me the most annoying thing before occupying too much space was gradlew clean
leaving a build
folder behind.
Only tested with com.android.tools.build:gradle:3.0.1
, so YMMV.
TL;DR
For global application read last section, per-project use this in rootProject
's build.gradle
:
com.android.build.gradle.internal.profile.ProfilerInitializer.recordingBuildListener =
new com.android.build.gradle.internal.profile.RecordingBuildListener(
com.android.builder.profile.ProcessProfileWriter.get());
// and then `gradlew --stop && gradlew clean` to verify no build folder is left behind
Investigation
Thanks to https://stackoverflow.com/a/43910084/253468 linked by @JeffRichards mentioning ProcessProfileWriterFactory.java
, I've put a breakpoint there and checked who's calling it by running gradlew -Dorg.gradle.debug=true --info
(not to be confused with --debug
) and attaching a remote debugger.
I followed the trail and found that ProcessProfileWriter.finishAndMaybeWrite
creates the folder and writes. Backtracing on method calls I found that ProfilerInitializer.recordingBuildListener
controls whether it's called ... and that is initialized directly by BasePlugin
(apply plugin: 'com.android.*'
).
So in order to prevent anything from happening I opted to try to disable the guard, by pre-initialized that static field. Thankfully Groovy (and hence Gradle) doesn't give a * about JVM visibility modifiers, so without reflection here's the magic line:
com.android.build.gradle.internal.profile.ProfilerInitializer.recordingBuildListener =
new com.android.build.gradle.internal.profile.RecordingBuildListener(
com.android.builder.profile.ProcessProfileWriter.get());
I know, it's a bit verbose, but it works, and if you import stuff it looks better:
ProfilerInitializer.recordingBuildListener = new RecordingBuildListener(ProcessProfileWriter.get());
Applying the magic
In a single-project build (one build.gradle
) you must apply this before
apply plugin: 'com.android.application'
In multi-project builds (most template projects: app
folder, settings.gradle
, and many build.gradle
s) I suggest you apply it around the buildscript
block:
buildscript {
// ...
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
// magic line here
Make sure it's before any apply plugin:
s, and not inside a buildscript
block.
Applying the magic globally
Obviously if it bothers us in one project, it will in all cases, so following Gradle's manual, create a file in ~/.gradle/init.gradle
or %USERPROFILE%\.gradle\init.gradle
(mind you this folder can be relocated with GRADLE_USER_HOME
) with the following contents:
// NB: any changes to this script require a new daemon (`gradlew --stop` or `gradlew --no-daemon <tasks>`)
rootProject { rootProject -> // see https://stackoverflow.com/a/48087543/253468
// listen for lifecycle events on the project's plugins
rootProject.plugins.whenPluginAdded { plugin ->
// check if any Android plugin is being applied (not necessarily just 'com.android.application')
// this plugin is actually exactly for this purpose: to get notified
if (plugin.class.name == 'com.android.build.gradle.api.AndroidBasePlugin') {
logger.info 'Turning off `build/android-profile/profile-*.(rawproto|json)` generation.'
// execute the hack in the context of the buildscript, not in this initscript
new GroovyShell(plugin.class.classLoader).evaluate("""
com.android.build.gradle.internal.profile.ProfilerInitializer.recordingBuildListener =
new com.android.build.gradle.internal.profile.RecordingBuildListener(
com.android.builder.profile.ProcessProfileWriter.get());
""")
}
}
}
来源:https://stackoverflow.com/questions/43521979/how-to-prevent-rawproto-file-generation-or-delete-them-automatically