diff --git a/src/main/java/edu/wpi/first/nativeutils/NativeUtilsExtension.java b/src/main/java/edu/wpi/first/nativeutils/NativeUtilsExtension.java index 61c2215d..f43f354e 100644 --- a/src/main/java/edu/wpi/first/nativeutils/NativeUtilsExtension.java +++ b/src/main/java/edu/wpi/first/nativeutils/NativeUtilsExtension.java @@ -94,6 +94,12 @@ private void addNativeDependencyType(Class cls, }); } + private void addNativeDependencyType(Class 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; @@ -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); diff --git a/src/main/java/edu/wpi/first/nativeutils/WPINativeUtilsExtension.java b/src/main/java/edu/wpi/first/nativeutils/WPINativeUtilsExtension.java index ede766cc..12e20e91 100644 --- a/src/main/java/edu/wpi/first/nativeutils/WPINativeUtilsExtension.java +++ b/src/main/java/edu/wpi/first/nativeutils/WPINativeUtilsExtension.java @@ -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; @@ -197,6 +199,7 @@ public WPIVendorDepsExtension getVendorDeps() { } private final Project project; + private final Map> transitiveDependencyLookup; @Inject public WPINativeUtilsExtension(NativeUtilsExtension nativeExt, Project project) { @@ -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) { @@ -383,6 +388,9 @@ public void addWarningsAsErrors(String... platforms) { private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContainer configs, String name, String groupId, String artifactId, Property version) { configs.register(name + "_shared", WPISharedMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_shared"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -394,6 +402,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain c.getTargetPlatforms().addAll(this.platforms.allPlatforms); }); configs.register(name + "_static", WPIStaticMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_static"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -409,6 +420,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContainer configs, String name, Provider groupId, String artifactId, Property version) { configs.register(name + "_shared", WPISharedMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_shared"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -420,6 +434,9 @@ private void registerStandardDependency(ExtensiblePolymorphicDomainObjectContain c.getTargetPlatforms().addAll(this.platforms.allPlatforms); }); configs.register(name + "_static", WPIStaticMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_static"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -436,6 +453,9 @@ private void registerSharedOnlyStandardDependency( ExtensiblePolymorphicDomainObjectContainer configs, String name, String groupId, String artifactId, Property version) { configs.register(name + "_shared", WPISharedMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_shared"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -452,6 +472,9 @@ private void registerStaticOnlyStandardDependency( ExtensiblePolymorphicDomainObjectContainer configs, String name, Provider groupId, String artifactId, Property version) { configs.register(name + "_static", WPIStaticMavenDependency.class, c -> { + Set transitiveDependencies = gettransitiveDependencies(name + "_static"); + c.getDependencies().set(transitiveDependencies); + c.getGroupId().set(groupId); c.getArtifactId().set(artifactId); c.getHeaderClassifier().set("headers"); @@ -578,14 +601,12 @@ public void configureDependencies(Action dependencies) { configs.register("wpilib_static", AllPlatformsCombinedNativeDependency.class, c -> { ListProperty 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 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 -> { @@ -600,32 +621,88 @@ public void configureDependencies(Action dependencies) { configs.register("wpilib_executable_shared", AllPlatformsCombinedNativeDependency.class, c -> { ListProperty 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 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 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 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 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 d = c.getDependencies(); - d.set(List.of("cameraserver_static", "cscore_static", "opencv_static")); + d.set(List.of("cameraserver_static", "cscore_static")); }); } + + private Map> configuretransitiveDependencies() { + + Map> 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> transitiveDependencyLookup = new HashMap<>(); + for (var entryPair : standardtransitiveDependencyLookup.entrySet()) { + Set sharedDeps = new HashSet<>(); + Set 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 gettransitiveDependencies(String libraryName) { + return gettransitiveDependencies(libraryName, new HashSet<>(), ""); + } + + private Set gettransitiveDependencies(String libraryName, Set 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; + } } diff --git a/src/main/java/edu/wpi/first/nativeutils/dependencies/WPISharedMavenDependency.java b/src/main/java/edu/wpi/first/nativeutils/dependencies/WPISharedMavenDependency.java index b43b754c..9ac7072a 100644 --- a/src/main/java/edu/wpi/first/nativeutils/dependencies/WPISharedMavenDependency.java +++ b/src/main/java/edu/wpi/first/nativeutils/dependencies/WPISharedMavenDependency.java @@ -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 SHARED_MATCHERS = List.of("**/*.so", "**/*.so.*", "**/*.dylib", "**/*.lib"); public static final List RUNTIME_MATCHERS = List.of("**/*.so", "**/*.so.*", "**/*.dylib", "**/*.dll", "**/*.pdb"); public static final List SHARED_EXCLUDES = List.of("**/*.so.debug", "**/*.so.*.debug", "**/*jni*"); public static final List RUNTIME_EXCLUDES = List.of(); + protected final NamedDomainObjectCollection dependencyCollection; @Inject - public WPISharedMavenDependency(String name, Project project) { + public WPISharedMavenDependency(String name, Project project, NamedDomainObjectCollection dependencyCollection) { super(name, project); + this.dependencyCollection = dependencyCollection; } + + public abstract ListProperty getDependencies(); @Override public Optional resolveNativeDependency(NativePlatform platform, BuildType buildType, Optional loaderDependencySet) { @@ -58,6 +64,16 @@ public Optional resolveNativeDependency(NativePlatform runtimeFiles = getArtifactFiles(platformName, buildTypeName, RUNTIME_MATCHERS, RUNTIME_EXCLUDES, ArtifactType.RUNTIME, loaderDependencySet); } + + List 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); diff --git a/src/main/java/edu/wpi/first/nativeutils/dependencies/WPIStaticMavenDependency.java b/src/main/java/edu/wpi/first/nativeutils/dependencies/WPIStaticMavenDependency.java index ef261399..e49e4f5f 100644 --- a/src/main/java/edu/wpi/first/nativeutils/dependencies/WPIStaticMavenDependency.java +++ b/src/main/java/edu/wpi/first/nativeutils/dependencies/WPIStaticMavenDependency.java @@ -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 STATIC_MATCHERS = List.of("**/*.lib", "**/*.a"); public static final List EMPTY_LIST = List.of(); + protected final NamedDomainObjectCollection dependencyCollection; @Inject - public WPIStaticMavenDependency(String name, Project project) { + public WPIStaticMavenDependency(String name, Project project, NamedDomainObjectCollection dependencyCollection) { super(name, project); + this.dependencyCollection = dependencyCollection; } + + public abstract ListProperty getDependencies(); @Override public Optional resolveNativeDependency(NativePlatform platform, BuildType buildType, Optional loaderDependencySet) { @@ -40,6 +46,15 @@ public Optional resolveNativeDependency(NativePlatform FileCollection linkFiles = getArtifactFiles(platformName + "static", buildTypeName, STATIC_MATCHERS, EMPTY_LIST, ArtifactType.LINK, loaderDependencySet); FileCollection runtimeFiles = getProject().files(); + + List 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));