When I query the classpath of each Variant in an Android project using methods: com.android.build.gradle.AppExtension#getApplicationVariants#forEach#getJavaCompileProvider#getClasspath
, and that project depends on a non-Android project (i.e. Java only), and nothing has been compiled yet then I get an exception.
> Could not resolve all files for configuration ':myAndroidApp:debugCompileClasspath'.
> Failed to transform MyJavaLibrary.jar (project :MyJavaLibrary) to match attributes {artifactType=android-classes-jar, org.gradle.category=library, org.gradle.dependency.bundling=external, org.gradle.jvm.version=7, org.gradle.libraryelements=jar, org.gradle.usage=java-api}.
> Execution failed for IdentityTransform: E:\android\MyJava\build\libs\MyJava.jar.
> Expecting a file or a directory: E:\android\MyJava\build\libs\MyJava.jar
The exception is thrown in com.android.build.gradle.internal.dependency.IdentityTransform
as it has to translate an InputTransform
(the java-only project’s jar) which appears to be an instance of FileSystemLocation
into either a File
or a Directory
as the methods on org.gradle.api.artifacts.transform.TransformOutputs
force it to make this decision.
The code in IdentityTransform
is as follows…
val input = inputArtifact.get().asFile
when {
input.isDirectory -> transformOutputs.dir(input)
input.isFile -> transformOutputs.file(input)
else -> throw IOException("Expecting a file or a directory: ${input.canonicalPath}")
}
I was going to raise this in the Android bug list but it seems that the InputTransform
→ OutputTransform
contracts make them impossible to use unless the files/dirs exist.
Is it only possible to get a project’s classpath, in the case where transforms exist, by compiling it first? Or should I be using another method to query the classpath that purely transforms the names and doesn’t require the transform to be executed?
I can’t see why the OutputTransform
forces this contract on the transform. Why does it care if the FileSystemLocation
is a directory or a file or if it exists - isn’t that the responsibility of the transform? It seems feasible to run through a series of transforms without creating the files/directories and if the transform itself relied on files existing then the transform could throw exceptions rather than the DefaultTransformOutputs
class throwing them.
An option I thought of, to bypass this, was to create my own IdentityTransform
equivalent class with a higher transform priority so it would be picked over the Android one but looking at DefaultTransformOutputs
it seems that it would still run into the issue of the jar file not existing. Am I correct in thinking that?