-
Notifications
You must be signed in to change notification settings - Fork 520
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
[Xamarin.Android.Build.Tasks] Add support for @(AndroidMavenLibrary). #8420
Conversation
24219f5
to
693877e
Compare
|
||
<PropertyGroup> | ||
<!-- Maven cache directory, locations copied from XBD which should be sufficiently battle-tested --> | ||
<MavenCacheDirectory Condition="'$(OS)'=='Unix' and '$(MavenCacheDirectory)'==''">$(HOME)\Library\Caches\MavenCacheDirectory\</MavenCacheDirectory> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this specified/controlled by MavenNet, or is this something we control? If it's something we control, should we instead use Library/Caches/dotnet-android
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It reminds me of %GRADLE_USER_HOME%
.
I moved this to a Dev Drive to a location like D:\.gradle
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a location of our choosing. I feel like it should denote in some way that this contains Maven artifacts. We could go deeper if we also want to denote it comes from dotnet-android
, like:
Library/Caches/dotnet-android/MavenCacheDirectory
Another data point to consider is what NuGet uses:
- Windows:
%userprofile%\.nuget\packages
- Mac/Linux:
~/.nuget/packages
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too deep folder structure might cause issues on Windows. Do not forget that we need unpacking too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how to make this work in an MSBuild context, but I think that a subdirectory of Environment.SpecialFolder
. InternetCache
might be best:
The directory that serves as a common repository for temporary Internet files.
For macOS this is $HOME/Llibrary/Caches
.
For Windows this is Interop.Shell32.KnownFolders.InternetCache
which is CSIDL_INTERNET_CACHE
which is:
file system directory that serves as a common repository for temporary Internet files. A typical path is C:\Documents and Settings\username\Local Settings\Temporary Internet Files.
(which just reads like Vista, and presumably has changed since Windows 7…)
Looks like you should be able to use MSBuild property functions, a'la:
<MavenCacheDirectory Condition=" '$(MavenCacheDirectory)' == '' "
>$([System.IO.Path]::Combine($([System.Environment]::GetFolderPath(SpecialFolder.InternetCache)), "dotnet-android", "Maven"))</MavenCacheDirectory>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like on Windows 11, CSIDL_INTERNET_CACHE
is:
C:\Users\jopobst\AppData\Local\Microsoft\Windows\INetCache
I don't like that this is hidden underneath Microsoft\Windows
. If I'm looking for a dotnet-android
Maven cache directory I wouldn't be checking there.
It also appears to be largely unused, my folder has a few directories totaling less than 1MB.
Sounds like what we want is:
Mac/Linux: ($HOME)/Library/Caches/dotnet-android/MavenCacheDirectory/
Windows: $(LocalAppData)\dotnet-android\MavenCacheDirectory\
I will update to these values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds like what we want is:
Mac/Linux: ($HOME)/Library/Caches/dotnet-android/MavenCacheDirectory/
Not quite; $(HOME)/Library
is a macOS-ism, not a Unix-ism.
The closest Linux-ism would likely be $(XDG_CACHE_HOME)
, which defaults to $(HOME)/.cache
.
@grendello: what is System.Environment.GetFolderPath(System.Environment.SpecialFolder.InternetCache))
on Linux? Looks like it should be string.Empty
, which isn't helpful.
@jpobst: perhaps instead of using $(OS)
we need to use the MSBuild OS property functions, using OperatingSystem.IsOsPlatform(string)
, with Windows
first, macOS
second, and "Unix" as the fallback?
src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets
Outdated
Show resolved
Hide resolved
src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Maven.targets
Outdated
Show resolved
Hide resolved
static async Task<string?> TryDownloadPayload (Artifact artifact, string filename) | ||
{ | ||
try { | ||
using var src = await artifact.OpenLibraryFile (artifact.Versions.First (), Path.GetExtension (filename)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another place MavenNet might need overload for CancellationToken
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is basically a call to HttpClient.OpenStreamAsync
, which does not have a cancelable version in netstandard2.0
.
One mitigating factor is this only opens the connection, it does not download the file. So likely the only long operation here would be an HTTP connect timeout.
b328c52
to
a325863
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks pretty good. My remaining comments seem pretty minor. 👍
```xml | ||
<!-- Include format is {GroupId}:{ArtifactId} --> | ||
<ItemGroup> | ||
<AndroidMavenLibrary Include="com.squareup.okhttp3:okhttp" Version="4.9.3" /> | ||
</ItemGroup> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we show an example of how you'd copy paste from here:
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/4.9.3
And then turn it into our XML/MSBuild version?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/4.9.3
mvnrepository is agregate repo and most packages point to MavenCentral repo.
Pobst used proper maven name for artifactId
which is groupId:artifactId
https://maven.apache.org/guides/introduction/introduction-to-the-pom.html#minimal-pom
It would be nice to have FQ Maven Id with version too: groupId:artifactId:version
then MsBuild Version
attribute is not needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rationale for a separate Version
attribute is to mirror <PackageReference>
and to allow MSBuild central versioning strategies to work, like:
<AndroidMavenLibrary Include="com.squareup.okhttp3:okhttp" Version="$(OKHTTP3_VERSION)" />
or
<AndroidMavenLibrary Update="com.squareup.okhttp3:okhttp" Version="5.0.0" />
I suppose we could allow either format, but let's start with this one and see if there is any demand for alternative formats.
Thinking about:
…and it feels like Central and Google are special because MavenNet treats them special. But why? I'm partially inclined toward an "extensible" model that would use an <ItemGroup>
<AndroidMavenRepositoryInfo Identity="Google" Url="https://maven.google.com/web/" />
<AndroidMavenRepositoryInfo Identity="Central" Url="https://mvnrepository.com/repos/central" />
</ItemGroup> which would allow adding new names without requiring a MavenNet update or xamarin-android rebuild. Is this bananas? |
Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
a325863
to
c71b234
Compare
MavenNet does have custom code for Central and Google. I am not sure if these are purely optimizations or if they are actually required due to API differences. (How "standard" is the Maven protocol, particularly around package search?) Either way, they are probably beneficial to continue using.
While The current design could be extended in this way in the future without breaking existing usages. |
Code formatting
|
||
namespace Xamarin.Android.Tasks; | ||
|
||
public class MavenDownloadTask : AndroidAsyncTask |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Naming? Not sure we need to use Task
as a suffix. We usually don't.
Context: https://github.com/xamarin/xamarin-android/issues/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/auto-value-annotations@1.10.4][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 |
cfc65eb
to
1a3546d
Compare
1a3546d
to
2a0245b
Compare
Context: #4528
Description
Adds support for the
@(AndroidMavenLibrary)
item group, which will automatically download the requested Java artifact version from a Maven repository and add it as an@(AndroidLibrary)
for binding.For example, to download a library from Maven Central and create an Android binding for it:
Specification
The
@Include
format is{GroupId}:{ArtifactId}
.Any additional attributes such as
Bind
orPack
will be copied to the created@(AndroidLibrary)
item.Bind
andPack
default totrue
and control the binding process as specified for@(AndroidLibrary)
.Repository
controls which Maven to download the artifact from. It defaults toCentral
for Maven Central but also supportsGoogle
for Google's Maven. Additionally, it can be given a URL to download from a custom Maven. (Note that Maven authentication is not supported.)Examples:
Note
There are 2 parts to #4528:
This PR only addresses (1). (2) will be addressed in a future PR.