Skip to content

Instantly share code, notes, and snippets.

@big-guy
Created March 4, 2016 06:32
Show Gist options
  • Save big-guy/3e0cc0a19771613e9367 to your computer and use it in GitHub Desktop.
Save big-guy/3e0cc0a19771613e9367 to your computer and use it in GitHub Desktop.
import org.gradle.api.Transformer;
import org.gradle.api.internal.resolve.ProjectModelResolver;
import org.gradle.model.ModelMap;
import org.gradle.model.internal.registry.ModelRegistry;
import org.gradle.nativeplatform.NativeBinarySpec;
import org.gradle.nativeplatform.NativeDependencySet;
import org.gradle.nativeplatform.NativeLibraryRequirement;
import org.gradle.nativeplatform.NativeLibrarySpec;
import org.gradle.nativeplatform.internal.NativeBinarySpecInternal;
import org.gradle.nativeplatform.internal.resolve.NativeBinaryRequirementResolveResult;
import org.gradle.nativeplatform.internal.resolve.NativeBinaryResolveResult;
import org.gradle.nativeplatform.internal.resolve.NativeDependencyResolver;
import org.gradle.platform.base.ComponentSpecContainer;
import org.gradle.util.CollectionUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Transitively resolves dependencies between native binaries.
* Does not attempt to cache any steps
* Does not attempt to prevent cycles
*/
public class TransitiveNativeDependencyResolver implements NativeDependencyResolver {
private final NativeDependencyResolver delegate;
private final ProjectModelResolver projectModelResolver;
public TransitiveNativeDependencyResolver(NativeDependencyResolver delegate, ProjectModelResolver projectModelResolver) {
this.delegate = delegate;
this.projectModelResolver = projectModelResolver;
}
@Override
public void resolve(NativeBinaryResolveResult nativeBinaryResolveResult) {
delegate.resolve(nativeBinaryResolveResult);
// do not try to transitively resolve dependencies if there are unresolved dependencies
if (nativeBinaryResolveResult.getPendingResolutions().isEmpty()) {
// only attempt to find transitive dependencies if there are dependencies
if (!nativeBinaryResolveResult.getAllResolutions().isEmpty()) {
List<NativeBinaryRequirementResolveResult> transitiveResults = new ArrayList<NativeBinaryRequirementResolveResult>();
for (NativeBinaryRequirementResolveResult resolution : nativeBinaryResolveResult.getAllResolutions()) {
transitiveResults.add(resolution);
transitiveResults.addAll(getTransitiveLibs(nativeBinaryResolveResult.getTarget(), resolution.getRequirement()));
}
// Replace the non-transitive resolution result with our transitive one
nativeBinaryResolveResult.getAllResolutions().clear();
nativeBinaryResolveResult.getAllResolutions().addAll(transitiveResults);
}
}
}
private List getTransitiveLibs(NativeBinarySpec target, final NativeLibraryRequirement requirement) {
NativeLibrarySpec librarySpec = findComponent(requirement);
if (librarySpec == null) {
// prebuilt library, no transitive dependencies for these
return Collections.emptyList();
}
ModelMap<NativeBinarySpecInternal> binaries = librarySpec.getBinaries().withType(NativeBinarySpecInternal.class);
NativeBinarySpecInternal matchingBinary = findBinary(binaries, target);
return CollectionUtils.collect(matchingBinary.getLibs(), new Transformer<NativeBinaryRequirementResolveResult, NativeDependencySet>() {
@Override
public NativeBinaryRequirementResolveResult transform(NativeDependencySet nativeDependencySet) {
NativeBinaryRequirementResolveResult transitiveResult = new NativeBinaryRequirementResolveResult("transitive from " + requirement);
transitiveResult.setNativeDependencySet(nativeDependencySet);
return transitiveResult;
}
});
}
private NativeLibrarySpec findComponent(NativeLibraryRequirement requirement) {
ModelRegistry projectModel = projectModelResolver.resolveProjectModel(requirement.getProjectPath());
ComponentSpecContainer components = projectModel.find("components", ComponentSpecContainer.class);
String libraryName = requirement.getLibraryName();
return components.withType(NativeLibrarySpec.class).get(libraryName);
}
private NativeBinarySpecInternal findBinary(ModelMap<NativeBinarySpecInternal> projectBinaries, NativeBinarySpec target) {
for (NativeBinarySpecInternal binary : projectBinaries) {
if (target.getFlavor() != null && !target.getFlavor().getName().equals(binary.getFlavor().getName())) {
continue;
}
if (target.getTargetPlatform() != null && !target.getTargetPlatform().getName().equals(binary.getTargetPlatform().getName())) {
continue;
}
if (target.getBuildType() != null && !target.getBuildType().getName().equals(binary.getBuildType().getName())) {
continue;
}
return binary;
}
return null; // something went wrong
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment