Closed jpobst closed 2 months ago
I have a "silly allergy" to lines which are "too wide", and I can see JavaArtifact="A:1;B:2;C:3;…"
as resulting in very wide lines. This can be somewhat improved by allowing newlines in the %(JavaArtifact)
value a'la https://github.com/xamarin/Java.Interop/pull/1086#discussion_r1126972799:
<PackageReference
Include="Xamarin.Kotlin.StdLib"
Version="1.7.10"
JavaArtifact="
org.jetbrains.kotlin:kotlin-stdlib:1.7.10
;org.jetbrains.kotlin:kotlin-stdlib-ktx:1.7.10
;insert.another:package.here:1.2.3"
/>
XML would permit this, it's just that whatever parses %(JavaArtifact)
would also need to support newlines.
Additionally, this doesn't feel "scalable"; it feels like it'll need to be copied "everywhere". For example, you have Binding.csproj
which binds multiple Java libraries, and then you have N projects which use <ProjectReference Include="…\Binding.csproj" />
. Presumably every one of these N projects would also need to be updated to mention %(JavaArtifact)
?
For existing NuGet packages, needing to mention %(JavaArtifact)
at every callsite may be unavoidable. For new NuGet packages and @(ProjectgReference)
, it should be possible to instead have Binding.csproj
provide the required information, instead of having every reference provide the required information.
A way to do this would be to use the <CallTarget/>
task. IIRC MSBuild internally does this for lots of things, e.g. to compute the list of output @(Content)
items which need to be copied into the referencing project, etc.
@jpobst asked:
Since we have only released this as a preview, would it be better to go further and scrap
%(JavaVersion)
altogether, and always use%(JavaArtifact)
with a version?
Yes. And also we should find a way to not need to mention %(JavaArtifact)
for most users.
And another plug for my above <CallTarget/>
suggestion, NuGet packages should also be able to provide the %(JavaArtifact)
information from .targets
files included within the NuGet package. This means that for new NuGet packages, "callers"/users of @(PackageReference)
wouldn't need to specify %(JavaArtifact)
at all. %(JavaArtifact)
would only need to be used for older packages.
Yes. And also we should find a way to not need to mention %(JavaArtifact) for most users.
Note that we already have this today. Users using updated NuGet packages do not need to specify %(JavaArtifact)
. We parse the NuGet metadata tags for a well-defined string (that we need to add documentation for) to determine what artifact it binds. The issue is we currently only support a single tag, we need to extend this to support multiple tags:
@(ProjectReference)
is more problematic, as you currently always have to specify %(JavaArtifact)
. Ideally we could scan the referenced project somehow and find them automatically but that doesn't exist yet. The currently existing mechanism of %(JavaArtifact)
only supports specifying a single artifact.
NOTE: @(ProjectReference)
enhancement has been moved to https://github.com/dotnet/android/issues/9093. This issue will only deal with supporting multiple libraries per deployment unit.
I vote in favor of this as a feature, especially for "framework" dependency scenarios.
Users using updated NuGet packages do not need to specify %(JavaArtifact). We parse the NuGet metadata tags for a well-defined string (that we need to add documentation for) to determine what artifact it binds.
You can see an example of how this could work in a package-project here.
I modded the prototype task to correctly resolve all dependencies in that package here. The usage is a standard package ref:
<PackageReference Include="XDev.IO.Ktor" Version="2.3.2.5" />
in the consuming project file.
@(ProjectReference) is more problematic, as you currently always have to specify %(JavaArtifact). Ideally we could scan the referenced project somehow and find them automatically but that doesn't exist yet. The currently existing mechanism of %(JavaArtifact) only supports specifying a single artifact.
That's one reason why I went the route of packing the project with multiple native libs that I had when trying to use the original prototype task. The change to the task code was fairly trivial.
Context: https://github.com/jpobst/Prototype.Android.MavenBindings/issues/13 Context: https://github.com/xamarin/xamarin-android/blob/main/Documentation/docs-mobile/features/maven/java-dependency-verification.md
Today, our Java Dependency Verification feature is built around our recommended practice of 1 binding library per project. This is reflected in the fact that
JavaArtifact
andJavaVersion
only support a single library:However a user may choose to place multiple Java libraries in a single package (or project), and we have no way to express that.
We should expand our support to allow expressing multiple Java libraries.
Note
<PackageReference>
is used as an example, but this extends to everywhere, like<ProjectReference>
and NuGet package tags.Solution 1
One possible way to do this is to allow
JavaArtifact
to contain theJavaVersion
, and then allow for multiple libraries to be specified, separated by a semicolon:Solution 2
Another possible way is to add a new
JavaArtifacts
(plural) metadata with the same semantics as theJavaArtifact
described in Solution 1. This new attribute would be mutually exclusive withJavaArtifact
/JavaVersion
.It feels like Solution 1 is better.
Since we have only released this as a preview, would it be better to go further and scrap
JavaVersion
altogether, and always useJavaArtifact
with a version? The original idea was that having them separate made it easier to maintain version numbers centrally usingUpdate
if desired, like:But I don't know if this is actually useful in practice? 🤷