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

Add ability to resolve transitive dependencies for native libraries #204

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,12 @@ private <T extends NativeDependency> void addNativeDependencyType(Class<T> cls,
});
}

private <T extends NativeDependency> void addNativeDependencyType(Class<T> cls, Object arg0, Object arg1) {
dependencyContainer.registerFactory(cls, name -> {
return objectFactory.newInstance(cls, name, arg0, arg1);
});
}

@Inject
public NativeUtilsExtension(Project project, ToolchainExtension tcExt) {
this.project = project;
Expand All @@ -105,8 +111,8 @@ public NativeUtilsExtension(Project project, ToolchainExtension tcExt) {
});

dependencyContainer = objectFactory.polymorphicDomainObjectContainer(NativeDependency.class);
addNativeDependencyType(WPIStaticMavenDependency.class, project);
addNativeDependencyType(WPISharedMavenDependency.class, project);
addNativeDependencyType(WPIStaticMavenDependency.class, project, dependencyContainer);
addNativeDependencyType(WPISharedMavenDependency.class, project, dependencyContainer);
addNativeDependencyType(WPIHeaderOnlyMavenDependency.class, project);

addNativeDependencyType(CombinedIgnoreMissingPlatformNativeDependency.class, dependencyContainer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.HashSet;
import java.util.Map;

import javax.inject.Inject;
Expand Down Expand Up @@ -197,6 +199,7 @@ public WPIVendorDepsExtension getVendorDeps() {
}

private final Project project;
private final Map<String, Set<String>> transitiveDependencyLookup;

@Inject
public WPINativeUtilsExtension(NativeUtilsExtension nativeExt, Project project) {
Expand Down Expand Up @@ -248,6 +251,8 @@ public WPINativeUtilsExtension(NativeUtilsExtension nativeExt, Project project)

osxuniversal.getPlatformPath().set("osx/universal");
addMacArgs(osxuniversal);

this.transitiveDependencyLookup = configuretransitiveDependencies();
}

public void addGcc11CrossArgs(String platform) {
Expand Down Expand Up @@ -383,6 +388,9 @@ public void addWarningsAsErrors(String... platforms) {
private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContainer<NativeDependency> configs,
String name, String groupId, String artifactId, Property<String> version) {
configs.register(name + "_shared", WPISharedMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_shared");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand All @@ -394,6 +402,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain
c.getTargetPlatforms().addAll(this.platforms.allPlatforms);
});
configs.register(name + "_static", WPIStaticMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_static");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand All @@ -409,6 +420,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain
private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContainer<NativeDependency> configs,
String name, Provider<String> groupId, String artifactId, Property<String> version) {
configs.register(name + "_shared", WPISharedMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_shared");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand All @@ -420,6 +434,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain
c.getTargetPlatforms().addAll(this.platforms.allPlatforms);
});
configs.register(name + "_static", WPIStaticMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_static");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand All @@ -436,6 +453,9 @@ private void registerSharedOnlyStandardDependency(
ExtensiblePolymorphicDomainObjectContainer<NativeDependency> configs,
String name, String groupId, String artifactId, Property<String> version) {
configs.register(name + "_shared", WPISharedMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_shared");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand All @@ -452,6 +472,9 @@ private void registerStaticOnlyStandardDependency(
ExtensiblePolymorphicDomainObjectContainer<NativeDependency> configs,
String name, Provider<String> groupId, String artifactId, Property<String> version) {
configs.register(name + "_static", WPIStaticMavenDependency.class, c -> {
Set<String> transitiveDependencies = gettransitiveDependencies(name + "_static");
c.getDependencies().set(transitiveDependencies);

c.getGroupId().set(groupId);
c.getArtifactId().set(artifactId);
c.getHeaderClassifier().set("headers");
Expand Down Expand Up @@ -578,14 +601,12 @@ public void configureDependencies(Action<DependencyVersions> dependencies) {

configs.register("wpilib_static", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("wpilibc_static", "ntcore_static", "hal_static", "wpimath_static", "wpinet_static",
"wpiutil_static", "ni_link_libraries"));
d.set(List.of("wpilibc_static"));
});

configs.register("wpilib_shared", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("wpilibc_shared", "ntcore_shared", "hal_shared", "wpimath_shared", "wpinet_shared",
"wpiutil_shared", "ni_link_libraries"));
d.set(List.of("wpilibc_shared"));
});

configs.register("driver_static", AllPlatformsCombinedNativeDependency.class, c -> {
Expand All @@ -600,32 +621,88 @@ public void configureDependencies(Action<DependencyVersions> dependencies) {

configs.register("wpilib_executable_shared", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("wpilib_shared", "ni_link_libraries", "ni_runtime_libraries"));
d.set(List.of("wpilibc_shared", "ni_runtime_libraries"));
});

configs.register("wpilib_executable_static", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("wpilib_static", "ni_link_libraries", "ni_runtime_libraries"));
d.set(List.of("wpilibc_static", "ni_runtime_libraries"));
});

configs.register("vision_jni_shared", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("cscore_shared", "apriltag_shared", "opencv_shared"));
d.set(List.of("cscore_shared", "apriltag_shared"));
});

configs.register("vision_jni_static", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("cscore_static", "opencv_static"));
d.set(List.of("cscore_static"));
});

configs.register("vision_shared", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("cameraserver_shared", "cscore_shared", "apriltag_shared", "opencv_shared"));
d.set(List.of("cameraserver_shared", "cscore_shared", "apriltag_shared"));
});

configs.register("vision_static", AllPlatformsCombinedNativeDependency.class, c -> {
ListProperty<String> d = c.getDependencies();
d.set(List.of("cameraserver_static", "cscore_static", "opencv_static"));
d.set(List.of("cameraserver_static", "cscore_static"));
});
}

private Map<String, Set<String>> configuretransitiveDependencies() {

Map<String, Set<String>> standardtransitiveDependencyLookup = new HashMap<>();
standardtransitiveDependencyLookup.put("wpiutil", Set.of());
standardtransitiveDependencyLookup.put("wpinet", Set.of("wpiutil"));
standardtransitiveDependencyLookup.put("ntcore", Set.of("wpinet"));
standardtransitiveDependencyLookup.put("hal", Set.of("wpiutil"));
standardtransitiveDependencyLookup.put("cscore", Set.of("opencv"));
// standardtransitiveDependencyLookup.put("cameraserver", Set.of("wpiutil"));
standardtransitiveDependencyLookup.put("wpilibc", Set.of("wpiutil", "ntcore", "hal", "wpimath"));

Map<String, Set<String>> transitiveDependencyLookup = new HashMap<>();
for (var entryPair : standardtransitiveDependencyLookup.entrySet()) {
Set<String> sharedDeps = new HashSet<>();
Set<String> staticDeps = new HashSet<>();

for (String dep : entryPair.getValue()) {
sharedDeps.add(dep + "_shared");
staticDeps.add(dep + "_static");
}

transitiveDependencyLookup.put(entryPair.getKey() + "_shared", sharedDeps);
transitiveDependencyLookup.put(entryPair.getKey() + "_static", staticDeps);
}

transitiveDependencyLookup.get("hal_shared").add("ni_link_libraries");
transitiveDependencyLookup.get("hal_static").add("ni_link_libraries");

return transitiveDependencyLookup;
}

private Set<String> gettransitiveDependencies(String libraryName) {
return gettransitiveDependencies(libraryName, new HashSet<>(), "");
}

private Set<String> gettransitiveDependencies(String libraryName, Set<String> transitiveDependencies, String indent) {
System.out.println(indent + "Getting transitive deps for " + libraryName);

if (transitiveDependencies.contains(libraryName)) {
System.out.println(indent + " " + libraryName + " already in list");
return transitiveDependencies;
}

if (!transitiveDependencyLookup.containsKey(libraryName)) {
System.out.println(indent + " " + libraryName + " is not in dependency lookup?");
return transitiveDependencies;
}

for (String directDependency : transitiveDependencyLookup.get(libraryName)) {
transitiveDependencies.addAll(gettransitiveDependencies(directDependency, transitiveDependencies, indent + " "));
transitiveDependencies.add(directDependency);
}

return transitiveDependencies;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,23 @@
import org.gradle.api.provider.Property;
import org.gradle.nativeplatform.BuildType;
import org.gradle.nativeplatform.platform.NativePlatform;
import org.gradle.api.NamedDomainObjectCollection;
import org.gradle.api.provider.ListProperty;

public abstract class WPISharedMavenDependency extends WPIMavenDependency {
public static final List<String> SHARED_MATCHERS = List.of("**/*.so", "**/*.so.*", "**/*.dylib", "**/*.lib");
public static final List<String> RUNTIME_MATCHERS = List.of("**/*.so", "**/*.so.*", "**/*.dylib", "**/*.dll", "**/*.pdb");
public static final List<String> SHARED_EXCLUDES = List.of("**/*.so.debug", "**/*.so.*.debug", "**/*jni*");
public static final List<String> RUNTIME_EXCLUDES = List.of();
protected final NamedDomainObjectCollection<NativeDependency> dependencyCollection;

@Inject
public WPISharedMavenDependency(String name, Project project) {
public WPISharedMavenDependency(String name, Project project, NamedDomainObjectCollection<NativeDependency> dependencyCollection) {
super(name, project);
this.dependencyCollection = dependencyCollection;
}

public abstract ListProperty<String> getDependencies();

@Override
public Optional<ResolvedNativeDependency> resolveNativeDependency(NativePlatform platform, BuildType buildType, Optional<FastDownloadDependencySet> loaderDependencySet) {
Expand Down Expand Up @@ -58,6 +64,16 @@ public Optional<ResolvedNativeDependency> resolveNativeDependency(NativePlatform
runtimeFiles = getArtifactFiles(platformName, buildTypeName, RUNTIME_MATCHERS, RUNTIME_EXCLUDES, ArtifactType.RUNTIME, loaderDependencySet);
}


List<String> dependencies = getDependencies().get();
for (String dep : dependencies) {
ResolvedNativeDependency resolved = dependencyCollection.getByName(dep).resolveNativeDependency(platform, buildType, loaderDependencySet).get();
headers = headers.plus(resolved.getIncludeRoots());
sources = sources.plus(resolved.getSourceRoots());
linkFiles = linkFiles.plus(resolved.getLinkFiles());
runtimeFiles = runtimeFiles.plus(resolved.getRuntimeFiles());
}

resolvedDep = Optional.of(new ResolvedNativeDependency(headers, sources, linkFiles, runtimeFiles));

addToCache(platform, buildType, resolvedDep);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,21 @@
import org.gradle.api.file.FileCollection;
import org.gradle.nativeplatform.BuildType;
import org.gradle.nativeplatform.platform.NativePlatform;
import org.gradle.api.NamedDomainObjectCollection;
import org.gradle.api.provider.ListProperty;

public abstract class WPIStaticMavenDependency extends WPIMavenDependency {
public static final List<String> STATIC_MATCHERS = List.of("**/*.lib", "**/*.a");
public static final List<String> EMPTY_LIST = List.of();
protected final NamedDomainObjectCollection<NativeDependency> dependencyCollection;

@Inject
public WPIStaticMavenDependency(String name, Project project) {
public WPIStaticMavenDependency(String name, Project project, NamedDomainObjectCollection<NativeDependency> dependencyCollection) {
super(name, project);
this.dependencyCollection = dependencyCollection;
}

public abstract ListProperty<String> getDependencies();

@Override
public Optional<ResolvedNativeDependency> resolveNativeDependency(NativePlatform platform, BuildType buildType, Optional<FastDownloadDependencySet> loaderDependencySet) {
Expand All @@ -40,6 +46,15 @@ public Optional<ResolvedNativeDependency> resolveNativeDependency(NativePlatform

FileCollection linkFiles = getArtifactFiles(platformName + "static", buildTypeName, STATIC_MATCHERS, EMPTY_LIST, ArtifactType.LINK, loaderDependencySet);
FileCollection runtimeFiles = getProject().files();

List<String> dependencies = getDependencies().get();
for (String dep : dependencies) {
ResolvedNativeDependency resolved = dependencyCollection.getByName(dep).resolveNativeDependency(platform, buildType, loaderDependencySet).get();
headers = headers.plus(resolved.getIncludeRoots());
sources = sources.plus(resolved.getSourceRoots());
linkFiles = linkFiles.plus(resolved.getLinkFiles());
runtimeFiles = runtimeFiles.plus(resolved.getRuntimeFiles());
}

resolvedDep = Optional.of(new ResolvedNativeDependency(headers, sources, linkFiles, runtimeFiles));

Expand Down