From 3901e89c0f79752ae9fa09873c31b42edd17d85f Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Tue, 31 May 2022 13:23:54 -0500 Subject: [PATCH] [One .NET] pack AndroidLibrary .aar files in .nupkg Fixes: https://github.com/xamarin/xamarin-android/issues/7040 It appears we were missing a test case of: 1. `dotnet new androidlib` 2. Add an `.aar` file 3. `dotnet pack` 4. Assert that `lib\net6.0-android31.0\MyAndroidLibrary.aar` exists in the `.nupkg` output We instead end up with "weird" output in the `.nupkg` like: lib\net6.0-android31.0\MyDotNetAssembly.dll lib\net6.0-android31.0\MyDotNetAssembly.xml lib\net6.0-android31.0\MyDotNetAssembly.aar content\MyAndroidLibrary.aar contentFiles\any\net6.0-android31.0\MyAndroidLibrary.aar `MyDotNetAssembly.aar` would contain any `.jar` files or `AndroidResource` files packed inside. However, *other* `.aar` files are supposed to sit next to `MyDotNetAssembly.dll`. It was surprisingly difficult to work alongside NuGet's MSBuild targets to get this to work. 1. In the `_CategorizeAndroidLibraries` MSBuild target, mark `TfmSpecificPackageFile="%(Pack)"` to be used in our `_IncludeAarInNuGetPackage` MSBuild target. 2. Add these files to `@(TfmSpecificPackageFileWithRecursiveDir)` and set `%(NuGetRecursiveDir)` to empty. Otherwise, these items can have `%(RecursiveDir)` set to some path, and this causes sub-directories in the `.nupkg` output. I updated several tests for this case. I also updated usage of `XASdkProject.OtherBuildItems` to use `Sources` instead. `OtherBuildItems` adds the files to the `.csproj`, and we should be testing our wildcards in `AutoImport.props`. Previously, some of these items were being added twice in these tests. --- .../Xamarin.Android.AvailableItems.targets | 2 +- ...osoft.Android.Sdk.AndroidLibraries.targets | 6 +- .../Xamarin.Android.Build.Tests/XASdkTests.cs | 73 ++++++++++++------- 3 files changed, 52 insertions(+), 29 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.AvailableItems.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.AvailableItems.targets index 4d11ec2c80d..4fa14aa75be 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.AvailableItems.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.AvailableItems.targets @@ -97,7 +97,7 @@ This item group populates the Build Action drop-down in IDEs. - + diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets index 94cfa5eed8a..3de503c9924 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets @@ -91,14 +91,16 @@ projects. $(TargetsForTfmSpecificContentInPackage);_IncludeAarInNuGetPackage + Condition=" '$(IncludeBuildOutput)' != 'false' and '$(AndroidApplication)' != 'true' " + DependsOnTargets="_CategorizeAndroidLibraries"> - + + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs index a8358494966..55e1a165bf3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/XASdkTests.cs @@ -89,27 +89,30 @@ public Foo () TextContent = () => { return "\n"; } - } + }, + new AndroidItem.AndroidAsset ("Assets\\foo\\foo.txt") { + BinaryContent = () => Array.Empty (), + }, + new AndroidItem.AndroidResource ("Resources\\layout\\MyLayout.axml") { + TextContent = () => "" + }, + new AndroidItem.AndroidResource ("Resources\\raw\\bar.txt") { + BinaryContent = () => Array.Empty (), + }, + new AndroidItem.AndroidLibrary ("sub\\directory\\foo.jar") { + BinaryContent = () => ResourceData.JavaSourceJarTestJar, + }, + new AndroidItem.AndroidLibrary ("sub\\directory\\bar.aar") { + WebContent = "https://repo1.maven.org/maven2/com/balysv/material-menu/1.1.0/material-menu-1.1.0.aar", + }, } }; - libB.OtherBuildItems.Add (new AndroidItem.AndroidAsset ("Assets\\foo\\foo.txt") { - BinaryContent = () => Array.Empty (), - }); - libB.OtherBuildItems.Add (new AndroidItem.AndroidResource ("Resources\\layout\\MyLayout.axml") { - TextContent = () => "" - }); - libB.OtherBuildItems.Add (new AndroidItem.AndroidResource ("Resources\\raw\\bar.txt") { - BinaryContent = () => Array.Empty (), - }); libB.OtherBuildItems.Add (new AndroidItem.AndroidEnvironment ("env.txt") { TextContent = () => $"{env_var}={env_val}", }); libB.OtherBuildItems.Add (new AndroidItem.AndroidEnvironment ("sub\\directory\\env.txt") { TextContent = () => $"{env_var}={env_val}", }); - libB.OtherBuildItems.Add (new AndroidItem.AndroidLibrary ("sub\\directory\\foo.jar") { - BinaryContent = () => ResourceData.JavaSourceJarTestJar, - }); libB.OtherBuildItems.Add (new AndroidItem.AndroidLibrary ("sub\\directory\\arm64-v8a\\libfoo.so") { BinaryContent = () => Array.Empty (), }); @@ -127,8 +130,10 @@ public Foo () Assert.IsTrue (libBBuilder.Build (), $"{libB.ProjectName} should succeed"); // Check .aar file for class library - var aarPath = Path.Combine (FullProjectDirectory, libB.OutputPath, $"{libB.ProjectName}.aar"); + var libBOutputPath = Path.Combine (FullProjectDirectory, libB.OutputPath); + var aarPath = Path.Combine (libBOutputPath, $"{libB.ProjectName}.aar"); FileAssert.Exists (aarPath); + FileAssert.Exists (Path.Combine (libBOutputPath, "bar.aar")); using (var aar = ZipHelper.OpenZip (aarPath)) { aar.AssertContainsEntry (aarPath, "assets/foo/foo.txt"); aar.AssertContainsEntry (aarPath, "res/layout/mylayout.xml"); @@ -237,18 +242,21 @@ public void DotNetPack (string targetFramework, int apiLevel) Sources = { new BuildItem.Source ("Foo.cs") { TextContent = () => "public class Foo { }", - } - } + }, + new AndroidItem.AndroidResource ("Resources\\raw\\bar.txt") { + BinaryContent = () => Array.Empty (), + }, + new AndroidItem.AndroidLibrary ("sub\\directory\\foo.jar") { + BinaryContent = () => ResourceData.JavaSourceJarTestJar, + }, + new AndroidItem.AndroidLibrary ("sub\\directory\\bar.aar") { + WebContent = "https://repo1.maven.org/maven2/com/balysv/material-menu/1.1.0/material-menu-1.1.0.aar", + }, + }, }; if (IsPreviewFrameworkVersion (targetFramework)) { proj.SetProperty ("EnablePreviewFeatures", "true"); } - proj.OtherBuildItems.Add (new AndroidItem.AndroidResource ("Resources\\raw\\bar.txt") { - BinaryContent = () => Array.Empty (), - }); - proj.OtherBuildItems.Add (new AndroidItem.AndroidLibrary ("sub\\directory\\foo.jar") { - BinaryContent = () => ResourceData.JavaSourceJarTestJar, - }); proj.OtherBuildItems.Add (new AndroidItem.AndroidLibrary ("sub\\directory\\arm64-v8a\\libfoo.so") { BinaryContent = () => Array.Empty (), }); @@ -257,16 +265,29 @@ public void DotNetPack (string targetFramework, int apiLevel) MetadataValues = "Link=x86\\libfoo.so", BinaryContent = () => Array.Empty (), }); + proj.OtherBuildItems.Add (new AndroidItem.AndroidLibrary (default (Func)) { + Update = () => "nopack.aar", + WebContent = "https://repo1.maven.org/maven2/com/balysv/material-menu/1.1.0/material-menu-1.1.0.aar", + MetadataValues = "Pack=false;Bind=false", + }); + const string dotnetVersion = "net6.0"; var dotnet = CreateDotNetBuilder (proj); Assert.IsTrue (dotnet.Pack (), "`dotnet pack` should succeed"); var nupkgPath = Path.Combine (FullProjectDirectory, proj.OutputPath, "..", $"{proj.ProjectName}.1.0.0.nupkg"); FileAssert.Exists (nupkgPath); - using (var nupkg = ZipHelper.OpenZip (nupkgPath)) { - nupkg.AssertContainsEntry (nupkgPath, $"lib/net6.0-android{apiLevel}.0/{proj.ProjectName}.dll"); - nupkg.AssertContainsEntry (nupkgPath, $"lib/net6.0-android{apiLevel}.0/{proj.ProjectName}.aar"); - } + using var nupkg = ZipHelper.OpenZip (nupkgPath); + nupkg.AssertContainsEntry (nupkgPath, $"lib/{dotnetVersion}-android{apiLevel}.0/{proj.ProjectName}.dll"); + nupkg.AssertContainsEntry (nupkgPath, $"lib/{dotnetVersion}-android{apiLevel}.0/{proj.ProjectName}.aar"); + + nupkg.AssertContainsEntry (nupkgPath, $"lib/{dotnetVersion}-android{apiLevel}.0/bar.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, "content/bar.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, "content/sub/directory/bar.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, $"contentFiles/any/{dotnetVersion}-android{apiLevel}.0/sub/directory/bar.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, $"lib/{dotnetVersion}-android{apiLevel}.0/nopack.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, "content/nopack.aar"); + nupkg.AssertDoesNotContainEntry (nupkgPath, $"contentFiles/any/{dotnetVersion}-android{apiLevel}.0/nopack.aar"); } [Test]