-
Notifications
You must be signed in to change notification settings - Fork 538
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
Bindings via Gradle/Maven? #4528
Comments
@jonpryor That's something @EgorBo did awhile back: https://github.com/EgorBo/Xamarin.GradleBindings https://marketplace.visualstudio.com/items?itemName=EgorBogatov.XamarinGradleBindings It's definitely something we hear from users often. In other words, a tool that could generate a binding project based on a maven package & it's dependencies. How feasible is it to create a binding project that gets a user say 90% the way there with their |
Was just going to open an issue about the same feature and found this.. I really miss the VS extension as it doesn't support VS 2019 but having the functionality built-in would be much better. The think I missed in the extension however was that it was just for generating a new binding project. There was no way (or I didn't find it) to update the So the imo best approach for this would be to make it work similarly to how NuGets are consumed by adding an MSBuild item like |
GradleReference is a good idea. Before I bind such a library, I had to download all gradle dependent AAR or jar files. If we do this through msbuild, I think it will greatly reduce our work of binding Android library. |
here is also a similar thing: IKVM.Maven.Sdk - IKVM support for Maven dependencies
|
Interesting IKVM link. This is what I'm currently considering: Moved above ^^ |
This is a good idea. However, I think if .NET for Android can run as a part of the gradle process, it'll be much better. The same way that Flutter/RN do its job. We don't have to bind everything if we don't need to. I am in process of building my library to support resolve native libraries using Gradle, so we don't have to embed them within the nuget packages. ETA: July 2023 |
Forks, I finally made my approach public for everyone to use and enhance. Please check it out here. P/S: Sorry for no documentation yet, I am going to publish a how-to post in next few days. |
I don't guess I ever posted a link on this issue. Here is the prototype of the approach mentioned in the issue description: |
@jpobst I checked your link previously, but it doesn't leverage Gradle yet. By downloading manually ourself, we recreate the wheel. Your prototype will far from complete if you also want to have maven repository authentication as well. In my findings, many dependencies aren't even listed in POM, but still understood by gradle when building using Android Studio :D . Xamarin.Android/.NET Android has to adopt. |
…#8420) Context: #4528 Add support for the `@(AndroidMavenLibrary)` item group, which will download the requested Java artifact version from a Maven repository and add it as an `@(AndroidLibrary)` for binding. For example, to download the Maven package [pkg:maven/com.google.auto.value/[email protected]][0] from Maven Central and create an Android binding for it: <ItemGroup> <AndroidMavenLibrary Include="com.google.auto.value:auto-value-annotations" Version="1.10.4" /> </ItemGroup> ~~ Specification ~~ The `//AndroidMavenLibrary/@Include` format is `{GroupId}:{ArtifactId}`. Any additional attributes such as `%(Bind)` or `%(Pack)` will be copied to the created `@(AndroidLibrary)` item. `%(Bind)` and `%(Pack)` default to `true` and control the binding process as specified for [`@(AndroidLibrary)`][1]. `%(Repository)` controls which Maven Repository to download artifacts from. Supported values include: * `Central` for [Maven Central][2]. This is the default value if `%(Repository)` is not specified. * `Google` for [Google's Maven][3]. * A URL, for downloading from a custom Maven instance. *Note*: Maven authentication is *not* supported. ~~Examples:~~ <ItemGroup> <AndroidMavenLibrary Include="androidx.core:core" Version="1.9.0" Repository="Google" Bind="false" /> <AndroidMavenLibrary Include="com.github.chrisbanes:PhotoView" Version="2.3.0" Repository="https://repository.mulesoft.org/nexus/content/repositories/public" Pack="false" /> </ItemGroup> There are 2 parts to #4528: 1. Downloading artifacts from Maven 2. Ensuring all dependencies specified in the POM file are met Only (1) is currently addressed. (2) will be addressed in the future. [0]: https://repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.10.4/ [1]: https://github.com/xamarin/xamarin-android/blob/main/Documentation/guides/OneDotNetEmbeddedResources.md#msbuild-item-groups [2]: https://repo1.maven.org/maven2/ [3]: https://maven.google.com/web/index.html
I found that we have a great progress to have a new CSPROJ item to include a native lib from a Maven repo directly. However,
I managed to create my own NuGet package, Dependency.Gradle which we can use Gradle to download the dependencies for us and already use that one for all my recent binding libraries which can be found the source in the repo Dotnet Binding Utils. I believe by using Gradle, it's much better and more aligned with the Android native. |
Fixes: #4528 Context: 3659766 Context: dotnet/java-interop@1c9c8c9 Commit 3659766 mentioned: > There are 2 parts to #4528: > > 1. Downloading artifacts from Maven > 2. Ensuring all dependencies specified in the POM file are met > > Only (1) is currently addressed. (2) will be addressed in the future. Implement support for (2): use `Java.Interop.Tools.Maven.dll` from dotnet/java-interop@1c9c8c9c to download and parse [Maven POM files][0] and ensure that all required Java dependencies are fulfilled. POM files are downloaded into `$(MavenCacheDirectory)` (3659766). Java dependency verification is a critical step that users often miss or make mistakes, resulting in non-functional bindings. Consider a classlib project with the following snippet: <ItemGroup> <AndroidMavenLibrary Include="com.squareup.okhttp3:okhttp" Version="4.9.3" /> </ItemGroup> With the new POM verification features, the above snippet will produce the following errors: error XA4242: Java dependency 'com.squareup.okio:okio:2.8.0' is not satisfied. Microsoft maintains the NuGet package 'Square.OkIO' that could fulfill this dependency. error XA4242: Java dependency 'org.jetbrains.kotlin:kotlin-stdlib:1.4.10' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.Kotlin.StdLib' that could fulfill this dependency. This is accomplished by automatically downloading the POM file (and any needed parent/imported POM files) for the specified artifact and using them to determine all required dependencies. There are many documented ways of fixing these errors, the best way is using the latest versions of the suggested NuGet packages: <ItemGroup> <PackageReference Include="Square.OkIO" Version="3.6.0.1" /> <PackageReference Include="Xamarin.Kotlin.StdLib" Version="1.9.22" /> </ItemGroup> Note this commit replaces our previous usage of `MavenNet` with `Java.Interop.Tools.Maven`. Thus it removes the `MavenNet` TPN. Some future concerns: - Can we automatically determine which dependencies are met by a `@(ProjectReference)`? Today, the user must manually add the metadata `%(ProjectReference.JavaArtifact)` and `%(ProjectReference.JavaVersion)` to specify this. - We use the link https://aka.ms/ms-nuget-packages to download [`microsoft-packages.json`][1], which is used to provide NuGet suggestions. We need to figure out a permanent home for this file and a process for generating it. Luckily we can ship a preview for now and change the `aka.ms` link to point to the permanent home later. [0]: https://maven.apache.org/pom.html [1]: https://raw.githubusercontent.com/jpobst/Prototype.Android.MavenBindings/main/microsoft-packages.json
It would be "interesting"/cool if, instead of binding a
.jar
or.aar
file, we could instead bind a gradle or maven "artifact name" and all dependencies within one binding project.Is this at all practical or possible?
jpobst:
I've been giving this some thought recently, and maybe we should do less automatically for the user (since that's where the dragons live), and focus first on helping the user ensure they are creating correct bindings.
TL:DR
We will initially focus on tackling two pain points of binding from Maven:
.jar
/.aar
and the related.pom
from Maven.pom
to verify that required Java dependencies are being fulfilledLet's take an example: Square's
okhttp3
version4.10.0
available in Maven.Target Package
For the sake of simplicity, let's work from Maven directly instead of
gradlew
:With this information, we can use MavenNet to download:
We can also allow this to come from somewhere on the file system if the user provides a
.jar
/.aar
and a.pom
:Because we are retrieving a
.pom
, we can start to do some dependency work for the user with a custom MSBuild task, and if they compile at this point they will receive the following build errors:Dependencies
In our example above, we saw that we can prevent the user from missing dependencies by requiring a
.pom
file. Dependencies can be fulfilled in 4 ways:<PackageReference>
<MavenAndroidLibrary>
or<LocalAndroidLibrary>
<ProjectReference>
NuGet
<PackageReference>
Automatically finding matching NuGet packages is out of scope, but no matter how they get here, we can validate that they meet the required dependency. This is the preferred mechanism because it uses a single canonical package and won't cause multiple versions of Java artifacts to conflict in our application. Additionally, NuGet packages have already taken care of transitive dependencies, so the user doesn't need to worry about them.
We definitely have a package for
Kotlin Stdlib
>=1.6.20
, so let's use that:Ideally, we'll use package metadata or a metadata file inside the package to tell us the Java version that this package binds (
1.7.10
). This will appease our tooling and when the user rebuilds, the Kotlin dependency error will disappear.We can also allow the user to manually specify what Java dependency a NuGet package fulfills if needed:
Included in this binding via
<MavenAndroidLibrary>
or<LocalAndroidLibrary>
If there isn't a NuGet package for our Java dependency, we can use the same mechanism to add an additional artifact to this project:
Unlike NuGet packages, this package's dependencies are not covered, so adding this package adds new dependency errors:
These will now need to be resolved too.
Another bindings project
<ProjectReference>
The user could also have a
<ProjectReference>
to another Android Bindings library that fulfills a dependency.TODO: Would the user need to specify
JavaArtifact
andJavaVersion
or could we fish it out of the project somehow?In this scenario, transitive dependencies would not be checked, the referenced project is expected to take care of itself.
Explicitly ignored
Sometimes the user knows better than us (or thinks they do), and we should allow them to explicitly ignore a dependency.
Benefits
Updateable
Unlike a "build it once" system, when a new version of the package is released the user simply needs to change the version number:
If the new version needs newer dependencies, the user will be required to update them rather than be allowed to build a package with bad dependencies.
Extensible
This system currently avoids the dragons of "find dependencies for the user", but that could be added later when we think we've solved it. The dependency verification outlined here would still be essential in that scenario as well.
Simpler?
Does not involve
gradlew
or Android Studio.Limitations
The text was updated successfully, but these errors were encountered: