Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try to use Artifact Transforms in the gradle plugin #6

Open
LunNova opened this issue Jan 8, 2020 · 0 comments
Open

Try to use Artifact Transforms in the gradle plugin #6

LunNova opened this issue Jan 8, 2020 · 0 comments
Assignees

Comments

@LunNova
Copy link
Member

LunNova commented Jan 8, 2020

Artifact transforms were added to gradle, and should be a clean way of applying our patches to dependencies. The current approach is fragile as it relies on internal API, and breaks transitive dependencies.

Unfortunately, there have been some issues implementing this.


Documentation

It's not clear what the possible values for built in gradle attributes are, or what to use. The examples use java and jar as values for artifactType. Where are those defined? jar is in ArtifactTypeDefinition but there's nothing for java.

https://github.com/gradle/gradle/blob/5bb0f7bf70c1311a07cf82677ed1b1660bfd8f87/subprojects/core-api/src/main/java/org/gradle/api/artifacts/type/ArtifactTypeDefinition.java#L30-L76

Source transformation?

Haven't been able to get transformation of sources working the same way as with jars. Using artifactType java or sources seems to result in nothing happening? The sources used when importing into IDEA don't get transformations applied.

if (useTransforms) {
registerTransform(project, ArtifactTypeDefinition.JAR_TYPE, applyMixinsMap);
registerTransform(project, ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, applyMixinsMap);
// TODO: this is intended to be for source jars but doesn't work?
registerTransform(project, "java", applyMixinsMap);

Looks like this is the same as gradle/gradle#11519 "DefauitArtifactResolutionQuery does not care for specified Transformers and ArtifactAttributes"

Per-dependency transformation

It doesn't seem to be possible to register a transformer for a specific set of dependencies, it gets ran on all of them. This means we need to pass a huge blob of parameters in registered once, and determine what to do per dependency. Extra work for gradle here as it's running the transform (and doing cache stuff) for every dep. Somewhat breaks caching, as if the input for any dep changes the cache is stale.

@Input
Map<String, ApplyMixins> getPerDependencyApplyMixins();

Once we've done that, it's hard to figure out what dependency the input file is from as only a File is provided. Raised gradle/gradle#11831 to ask about that.

// TODO this is awful but we don't get module data any other way? :C
private static String guessIdentifier(File input) {
for (int i = 0; i < 2; i++) {
val result = tryIdentifier(input, i);
if (result != null) {
return result;
}
}
return null;
}
private static String tryIdentifier(File input, int skips) {
File skipped = input;
for (int i = 0; i < skips; i++) {
skipped = skipped.getParentFile();
}
val version = skipped.getParentFile();
val name = version.getParentFile();
File groupFile = name.getParentFile();
if (!input.getName().startsWith(name.getName() + '-' + version.getName())) {
// name + version not as expected, fail
return null;
}
StringBuilder group = new StringBuilder(groupFile.getName());
// special case for mavenLocal()
if (!groupFile.getName().contains(".")) {
int tries = 7;
while (groupFile.exists()) {
groupFile = groupFile.getParentFile();
if (groupFile.getName().equals("repository") && groupFile.getParentFile().getName().equals(".m2")) {
break;
}
group.insert(0, groupFile.getName() + ".");
if (tries-- <= 0) {
return null;
}
}
}
return group.append(':').append(name.getName()).append(':').append(version.getName()).toString();
}

Transformer parameters can't reference task outputs or configs?

Only serializable values seem to work in the task parameters, so we have to do a horrible hack with static state and find the task again when running. This also means the dependency isn't being taken into account. Initially expected it would be, as for tasks you can do @InputFiles and a file dependency from another task's outputs will automatically depend on that task being ran first.

public interface Parameters extends TransformParameters {
@Input
Map<String, ApplyMixins> getPerDependencyApplyMixins();
void setPerDependencyApplyMixins(Map<String, ApplyMixins> value);
@Input
String getArtifactType();
void setArtifactType(String value);
}

@Classpath
@InputFiles
@NonNull
private transient FileCollection mixinSource;

if (mixinSource == null) {
logger.warn("mixinSource disappeared from ApplyMixins, trying to recreate it.");
mixinSource = HackyCurrentGradleSource.gradleWeakReference.get().getRootProject().findProject(mixinProjectPath).getTasks().getByPath("jar").getOutputs().getFiles();
}

Is there a better workaround than this static hack? Is pretty awful, so don't want to turn on using transformers at all as the generated dependency doesn't depend on that. Generated dep approach also has working dependency on the subproject task.

Raised gradle/gradle#11847

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant