-
Notifications
You must be signed in to change notification settings - Fork 552
[Xamarin.Android.Build.Tasks] Enable POM verification features. #8649
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
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
3df037d
[Xamarin.Android.Build.Tasks] Enable POM verification features.
jpobst 4605751
Flush.
jpobst 655d753
Flush.
jpobst e5dc999
Begin error documentation.
jpobst 3d28c09
Error documentation.
jpobst 0dd3021
Address review feedback.
jpobst b3efd14
Add more documentation.
jpobst ccd9113
Track Java.Interop.Tools.Maven changes.
jpobst 6996ccc
Address docs review feedback.
jpobst f86d3e7
Update ResolvingJavaDependencies.md
jonpryor e132070
Review feedback.
jpobst 45c6feb
Fix XML formatting.
jonpryor File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Java Dependency Verification | ||
|
||
Note: This feature is only available in .NET 9+. | ||
|
||
## Description | ||
|
||
A common problem when creating Java binding libraries for .NET Android is not providing the required Java dependencies. The binding process ignores API that requires missing dependencies, so this can result in large portions of desired API not being bound. | ||
|
||
Unlike .NET assemblies, a Java library does not specify its dependencies in the package. The dependency information is stored in external files called POM files. In order to consume this information to ensure correct dependencies an additional layer of files must be added to a binding project. | ||
|
||
Note: the preferred way of interacting with this system is to use [`<AndroidMavenLibrary>`](AndroidMavenLibrary.md) which will automatically download any needed POM files. | ||
|
||
For example: | ||
|
||
```xml | ||
<AndroidMavenLibrary Include="com.squareup.okio:okio" Version="1.17.4" /> | ||
``` | ||
|
||
automatically gets expanded to: | ||
|
||
```xml | ||
<AndroidLibrary | ||
Include="<MavenCacheDir>/Central/com.squareup.okio/okio/1.17.4/com.squareup.okio_okio.jar" | ||
Manifest="<MavenCacheDir>/Central/com.squareup.okio/okio/1.17.4/com.squareup.okio_okio.pom" | ||
JavaArtifact="com.squareup.okio:okio" | ||
JavaVersion="1.17.4" /> | ||
|
||
<AndroidAdditionalJavaManifest | ||
Include="<MavenCacheDir>/Central/com.squareup.okio/okio-parent/1.17.4/okio-parent-1.17.4.pom" | ||
JavaArtifact="com.squareup.okio:okio-parent" | ||
JavaVersion="1.17.4" /> | ||
|
||
etc. | ||
``` | ||
|
||
However it is also possible to manually opt in to Java dependency verification using the build items documented here. | ||
|
||
## Specification | ||
|
||
To manually opt in to Java dependency verification, add the `Manifest`, `JavaArtifact`, and `JavaVersion` attributes to an `<AndroidLibrary>` item: | ||
|
||
```xml | ||
<!-- JavaArtifact format is {GroupId}:{ArtifactId} --> | ||
<ItemGroup> | ||
<AndroidLibrary | ||
Include="my_binding_library.jar" | ||
Manifest="my_binding_library.pom" | ||
JavaArtifact="com.example:mybinding" | ||
JavaVersion="1.0.0" /> | ||
</ItemGroup> | ||
``` | ||
|
||
Building the binding project now should result in verification errors if `my_binding_library.pom` specifies dependencies that are not met. | ||
|
||
For example: | ||
|
||
``` | ||
error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. | ||
``` | ||
|
||
Seeing these error(s) or no errors should indicate that the Java dependency verification is working. Follow the [Resolving Java Dependencies](ResolvingJavaDependencies.md) guide to fix any missing dependency errors. | ||
|
||
## Additional POM Files | ||
|
||
POM files can sometimes have some optional features in use that make them more complicated than the above example. | ||
|
||
That is, a POM file can depend on a "parent" POM file: | ||
|
||
```xml | ||
<parent> | ||
<groupId>com.squareup.okio</groupId> | ||
<artifactId>okio-parent</artifactId> | ||
<version>1.17.4</version> | ||
</parent> | ||
``` | ||
|
||
Additionally, a POM file can "import" dependency information from another POM file: | ||
|
||
```xml | ||
<dependencyManagement> | ||
<dependencies> | ||
<dependency> | ||
<groupId>com.squareup.okio</groupId> | ||
<artifactId>okio-bom</artifactId> | ||
<version>3.0.0</version> | ||
<type>pom</type> | ||
<scope>import</scope> | ||
</dependency> | ||
</dependencies> | ||
</dependencyManagement> | ||
``` | ||
|
||
Dependency information cannot be accurately determined without also having access to these additional POM files, and will results in an error like: | ||
|
||
``` | ||
error : Unable to resolve POM for artifact 'com.squareup.okio:okio-parent:1.17.4'. | ||
``` | ||
|
||
In this case, we need to provide the POM file for `com.squareup.okio:okio-parent:1.17.4`: | ||
|
||
```xml | ||
<!-- JavaArtifact format is {GroupId}:{ArtifactId} --> | ||
<ItemGroup> | ||
<AndroidAdditionalJavaManifest | ||
Include="com.square.okio.okio-parent.1.17.4.pom" | ||
JavaArtifact="com.squareup.okio:okio-parent" | ||
JavaVersion="1.17.4" /> | ||
</ItemGroup> | ||
``` | ||
|
||
Note that as "Parent" and "Import" POMs can themselves have parent and imported POMs, this step may need to be repeated until all POM files can be resolved. | ||
|
||
Note also that if using `<AndroidMavenLibrary>` this should all be handled automatically. | ||
|
||
At this point, if there are dependency errors, follow the [Resolving Java Dependencies](ResolvingJavaDependencies.md) guide to fix any missing dependency errors. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
# Resolving Java Dependencies | ||
|
||
Note: This feature is only available in .NET 9+. | ||
|
||
## Description | ||
|
||
Once Java dependency verification has been enabled for a bindings project, either automatically via `<AndroidMavenLibrary>` or manually via `<AndroidLibrary>`, there may be errors to resolve, such as: | ||
|
||
``` | ||
error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. | ||
``` | ||
|
||
These dependencies can be fulfilled in many different ways. | ||
|
||
## `<PackageReference>` | ||
|
||
In the best case scenario, there is already an existing binding of the Java dependency available on NuGet.org. This package may be provided by Microsoft or the .NET community. Packages maintained by Microsoft may be surfaced in the error message like this: | ||
|
||
``` | ||
error : Java dependency 'androidx.collection:collection' version '1.0.0' is not satisfied. Microsoft maintains the NuGet package 'Xamarin.AndroidX.Collection' that could fulfill this dependency. | ||
``` | ||
|
||
Adding the `Xamarin.AndroidX.Collection` package to the project should automatically resolve this error, as the package provides metadata to advertise that it provides the `androidx.collection:collection` dependency. This is done by looking for a specially crafted NuGet tag. For example, for the AndroidX Collection library, the tag looks like this: | ||
|
||
```xml | ||
<!-- artifact={GroupId}:{ArtifactId}:{Java Library Version} --> | ||
<PackageTags>artifact=androidx.collection:collection:1.0.0</PackageTags> | ||
``` | ||
|
||
However there may be NuGet packages which fulfill a dependency but have not had this metadata added to it. In this case, you will need to explicitly specify which dependency the package contains with `JavaArtifact` and `JavaVersion`: | ||
|
||
```xml | ||
<PackageReference | ||
Include="Xamarin.Kotlin.StdLib" | ||
Version="1.7.10" | ||
JavaArtifact="org.jetbrains.kotlin:kotlin-stdlib" | ||
JavaVersion="1.7.10" /> | ||
``` | ||
|
||
With this, the binding process knows the Java dependency is satisfied by the NuGet package. | ||
|
||
> Note: NuGet packages specify their own dependencies, so you will not need to worry about transitive dependencies. | ||
|
||
## `<ProjectReference>` | ||
|
||
If the needed Java dependency is provided by another project in your solution, you can annotate the `<ProjectReference>` to specify the dependency it fulfills: | ||
|
||
```xml | ||
<ProjectReference | ||
Include="..\My.Other.Binding\My.Other.Binding.csproj" | ||
JavaArtifact="my.other.binding:helperlib" | ||
JavaVersion="1.0.0" /> | ||
``` | ||
|
||
With this, the binding process knows the Java dependency is satisfied by the referenced project. | ||
|
||
> Note: Each project specifies their own dependencies, so you will not need to worry about transitive dependencies. | ||
|
||
## `<AndroidLibrary>` | ||
|
||
If you are creating a public NuGet package, you will want to follow NuGet's "one library per package" policy so that the NuGet dependency graph works. However, if creating a binding for private use, you may want to include your Java dependencies directly inside the parent binding. | ||
|
||
This can be done by adding additional `<AndroidLibrary>` items to the project: | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidLibrary Include="mydependency.jar" JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" /> | ||
</ItemGroup> | ||
``` | ||
|
||
To include the Java library but not produce C# bindings for it, mark it with `Bind="false"`: | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidLibrary Include="mydependency.jar" JavaArtifact="my.library:dependency-library" JavaVersion="1.0.0" Bind="false" /> | ||
</ItemGroup> | ||
``` | ||
|
||
Alternatively, `<AndroidMavenLibrary>` can be used to retrieve a Java library from a Maven repository: | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidMavenLibrary Include="my.library:dependency-library" Version="1.0.0" /> | ||
<!-- or, if the Java library doesn't need to be bound --> | ||
<AndroidMavenLibrary Include="my.library:dependency-library" Version="1.0.0" Bind="false" /> | ||
</ItemGroup> | ||
``` | ||
|
||
> Note: If the dependency library has its own dependencies, you will be required to ensure they are fulfilled. | ||
|
||
## `<AndroidIgnoredJavaDependency>` | ||
|
||
As a last resort, a needed Java dependency can be ignored. An example of when this is useful is if the dependency library is a collection of Java annotations that are only used at compile type and not runtime. | ||
|
||
Note that while the error message will go away, it does not mean the package will magically work. If the dependency is actually needed at runtime and not provided the Android application will crash with a `Java.Lang.NoClassDefFoundError` error. | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidIgnoredJavaDependency Include="com.google.errorprone:error_prone_annotations" Version="2.15.0" /> | ||
</ItemGroup> | ||
``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
--- | ||
title: .NET Android error XA4234 | ||
description: XA4234 error code | ||
ms.date: 02/26/2024 | ||
--- | ||
# .NET Android error XA4234 | ||
|
||
## Example message | ||
|
||
``` | ||
error XA4234: '<AndroidMavenLibrary>' item 'com.example:mylib' is missing required attribute 'Version'. | ||
``` | ||
|
||
## Issue | ||
|
||
The specified MSBuild XML item requires the specified XML attribute. | ||
|
||
For example the following item is missing the required 'Version' attribute: | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidMavenLibrary Include="com.example:mylib" /> | ||
</ItemGroup> | ||
``` | ||
|
||
## Solution | ||
|
||
To resolve this error, ensure that the specified XML contains the specified attribute: | ||
|
||
```xml | ||
<ItemGroup> | ||
<AndroidMavenLibrary Include="com.example:mylib" Version="1.0.0" /> | ||
</ItemGroup> | ||
``` |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.