From b0bac43d89686f9488e431b40c421f689ce31d63 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 26 Jun 2023 15:20:58 -0500 Subject: [PATCH 1/2] [build] create `xamarin-android-tools.override.props` If you installed the `android` workload via: dotnet workload install android --skip-sign-check \ --from-rollback-file https://maui.blob.core.windows.net/metadata/rollbacks/net8.0.json \ --source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json \ --source https://api.nuget.org/v3/index.json `dotnet new android` & `dotnet build` succeeds. But `MSBuild.exe` fails with: D:\src\dotnet-sdk-8.0.100-preview.6.23318.1-win-x64\packs\Microsoft.Android.Sdk.Windows\34.0.0-preview.6.323\tools\Xamarin.Android.EmbeddedResource.targets(39,5): error XARLP7028: System.IO.FileNotFoundException: Could not load file or assembly 'libZipSharp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=276db85bc4e20efc' or one of its dependencies. The system cannot find the file specified. File name: 'libZipSharp, Version=2.1.0.0, Culture=neutral, PublicKeyToken=276db85bc4e20efc' at Xamarin.Android.Tasks.ResolveLibraryProjectImports.Extract(IDictionary`2 jars, ICollection`1 resolvedResourceDirectories, ICollection`1 resolvedAssetDirectories, ICollection`1 resolvedEnvironments, ICollection`1 proguardConfigFiles) at Xamarin.Android.Tasks.ResolveLibraryProjectImports.RunTask() at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25 WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure logging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog]. It turns out that for references to `libZipSharp.dll`: * `Microsoft.Android.Build.BaseTasks.dll` references 2.1.0.0 * `Xamarin.Android.Build.Tasks.dll` references 3.0.0.0 However, this appears to already be solved in the 34.0.0-preview.6.355 version of the `android` workload. It is broken in `34.0.0-preview.6.323`. In that time window, we updated `$(LibZipSharpVersion)` in xamarin/xamarin-android, but not yet bumped to the latest xamarin/xamarin-android-tools: https://github.com/xamarin/xamarin-android/commit/f1d59181c8daaa8d2abcdfd151b592ece49155ca To solve this issue, we can use the extension points we added to: https://github.com/xamarin/xamarin-android-tools/commit/34e98e2b65917d105169f868b5648f67e68b6784 And import xamarin-android's `Directory.Build.props` from `xamarin-android-tools.override.props`. With this change in place, I can set the value of `$(LibZipSharpVersion)` to any value and the value from xamarin-android overrides it. This probably slipped through because we dropped the "classic" Xamarin.Android test suite that used .NET framework MSBuild on Windows. All tests now use `dotnet build`. I added a test that builds an Android project in Debug & Release with `MSBuild.exe`, and updated Xamarin.ProjectTools to support doing this. --- external/xamarin-android-tools.override.props | 3 ++ .../Xamarin.Android.Build.Tests/BuildTest.cs | 22 +++++++++++++ .../Android/MSBuildSdkExtrasProject.cs | 5 --- .../Xamarin.ProjectTools/Common/Builder.cs | 33 ++++++++++++------- .../Common/DotNetStandard.cs | 3 -- .../Common/ProjectBuilder.cs | 2 +- .../Common/SolutionBuilder.cs | 2 +- .../Common/XamarinProject.cs | 1 - 8 files changed, 48 insertions(+), 23 deletions(-) create mode 100644 external/xamarin-android-tools.override.props diff --git a/external/xamarin-android-tools.override.props b/external/xamarin-android-tools.override.props new file mode 100644 index 00000000000..05002e1cacc --- /dev/null +++ b/external/xamarin-android-tools.override.props @@ -0,0 +1,3 @@ + + + diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index b17f7beafbb..f3df17b4c1c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -2577,5 +2577,27 @@ public void SimilarAndroidXAssemblyNames ([Values(true, false)] bool publishTrim using var builder = CreateApkBuilder (); Assert.IsTrue (builder.Build (proj), "Build should have succeeded."); } + + /// + /// Build with MSBuild.exe on .NET framework, instead of 'dotnet build' + /// + [Test] + public void BuildWithMSBuild ([Values (true, false)] bool isRelease) + { + if (!IsWindows) + Assert.Ignore ("Test is only valid on Windows platforms"); + + var proj = new XamarinAndroidApplicationProject { + IsRelease = isRelease, + }; + using var builder = CreateApkBuilder (); + + // Use MSBuild.exe, setting %PATH% to our local 'dotnet' directory + builder.BuildTool = TestEnvironment.GetVisualStudioInstance ().MSBuildPath; + var environment = new Dictionary (); + environment ["PATH"] = $"{TestEnvironment.DotNetPreviewDirectory};{Environment.GetEnvironmentVariable ("PATH")}"; + + Assert.IsTrue (builder.Build (proj, environmentVariables: environment), "Build should have succeeded."); + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/MSBuildSdkExtrasProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/MSBuildSdkExtrasProject.cs index 2c8304041de..249549f0465 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/MSBuildSdkExtrasProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/MSBuildSdkExtrasProject.cs @@ -20,11 +20,6 @@ public MSBuildSdkExtrasProject () public string StringsXml { get; set; } - /// - /// /t:Restore or /restore is always required - /// - public override bool ShouldRestorePackageReferences => true; - public string TargetFrameworks { get => GetProperty (nameof (TargetFrameworks)); set => SetProperty (nameof (TargetFrameworks), value); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index 334aa28ddfb..9a6f7ec88cf 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -53,16 +53,22 @@ public IEnumerable LastBuildOutput { /// public bool AutomaticNuGetRestore { get; set; } = true; + string _buildTool; + public string BuildTool { - get { - if (UseDotNet) - return Path.Combine (TestEnvironment.DotNetPreviewDirectory, "dotnet"); + get => _buildTool ??= FindBuildTool (); + set => _buildTool = value; + } - string xabuild = IsUnix ? XABuildPaths.XABuildScript : XABuildPaths.XABuildExe; - if (File.Exists (xabuild) && TestEnvironment.UseLocalBuildOutput) - return xabuild; - return IsUnix ? "msbuild" : TestEnvironment.GetVisualStudioInstance ().MSBuildPath; - } + string FindBuildTool () + { + if (UseDotNet) + return Path.Combine (TestEnvironment.DotNetPreviewDirectory, "dotnet"); + + string xabuild = IsUnix ? XABuildPaths.XABuildScript : XABuildPaths.XABuildExe; + if (File.Exists (xabuild) && TestEnvironment.UseLocalBuildOutput) + return xabuild; + return IsUnix ? "msbuild" : TestEnvironment.GetVisualStudioInstance ().MSBuildPath; } public bool CrossCompilerAvailable (string supportedAbis) @@ -186,7 +192,7 @@ protected virtual void Dispose (bool disposing) RegexOptions.Multiline | RegexOptions.Compiled ); - protected bool BuildInternal (string projectOrSolution, string target, string [] parameters = null, Dictionary environmentVariables = null, bool restore = true, string binlogName = "msbuild") + protected bool BuildInternal (string projectOrSolution, string target, string [] parameters = null, Dictionary environmentVariables = null, string binlogName = "msbuild") { buildLogFullPath = (!string.IsNullOrEmpty (BuildLogFile)) ? Path.GetFullPath (Path.Combine (XABuildPaths.TestOutputDirectory, Path.GetDirectoryName (projectOrSolution), BuildLogFile)) @@ -204,8 +210,11 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] var args = new StringBuilder (); var psi = new ProcessStartInfo (BuildTool); var responseFile = Path.Combine (XABuildPaths.TestOutputDirectory, Path.GetDirectoryName (projectOrSolution), "project.rsp"); + var isMSBuild = string.Equals (Path.GetFileNameWithoutExtension (psi.FileName), "MSBuild", StringComparison.OrdinalIgnoreCase); if (UseDotNet) { - args.Append ("build "); + if (!isMSBuild) { + args.Append ("build "); + } if (TestEnvironment.UseLocalBuildOutput) { psi.SetEnvironmentVariable ("DOTNETSDK_WORKLOAD_MANIFEST_ROOTS", TestEnvironment.WorkloadManifestOverridePath); psi.SetEnvironmentVariable ("DOTNETSDK_WORKLOAD_PACK_ROOTS", TestEnvironment.WorkloadPackOverridePath); @@ -213,11 +222,11 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] } args.AppendFormat ("{0} /t:{1} {2}", QuoteFileName (Path.Combine (XABuildPaths.TestOutputDirectory, projectOrSolution)), target, logger); - if (UseDotNet) { + if (UseDotNet && !isMSBuild) { if (!AutomaticNuGetRestore) { args.Append (" --no-restore"); } - } else if (AutomaticNuGetRestore && restore) { + } else if (AutomaticNuGetRestore) { args.Append (" /restore"); } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs index cc396f31c0f..4a1d15c1711 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetStandard.cs @@ -23,9 +23,6 @@ public DotNetStandard () Language = XamarinAndroidProjectLanguage.CSharp; } - // NetStandard projects always need to restore - public override bool ShouldRestorePackageReferences => true; - public string PackageTargetFallback { get { return GetProperty ("PackageTargetFallback"); } set { SetProperty ("PackageTargetFallback", value); } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs index 6118fc6a0c8..702c3845cb7 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs @@ -70,7 +70,7 @@ public bool Build (XamarinProject project, bool doNotCleanupOnUpdate = false, st project.NuGetRestore (Path.Combine (XABuildPaths.TestOutputDirectory, ProjectDirectory), PackagesDirectory); } - bool result = BuildInternal (Path.Combine (ProjectDirectory, project.ProjectFilePath), Target, parameters, environmentVariables, restore: project.ShouldRestorePackageReferences, binlogName: Path.GetFileNameWithoutExtension (BuildLogFile)); + bool result = BuildInternal (Path.Combine (ProjectDirectory, project.ProjectFilePath), Target, parameters, environmentVariables, binlogName: Path.GetFileNameWithoutExtension (BuildLogFile)); built_before = true; if (CleanupAfterSuccessfulBuild) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/SolutionBuilder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/SolutionBuilder.cs index 6485a65c7b5..2bd2b8f7834 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/SolutionBuilder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/SolutionBuilder.cs @@ -67,7 +67,7 @@ public void Save () public bool BuildProject(XamarinProject project, string target = "Build") { - BuildSucceeded = BuildInternal(Path.Combine (SolutionPath, project.ProjectName, project.ProjectFilePath), target, restore: project.ShouldRestorePackageReferences); + BuildSucceeded = BuildInternal(Path.Combine (SolutionPath, project.ProjectName, project.ProjectFilePath), target); return BuildSucceeded; } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs index 7ce6c520bfe..2a18c5d8f9f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/XamarinProject.cs @@ -33,7 +33,6 @@ public abstract class XamarinProject public string GlobalPackagesFolder { get; set; } = FileSystemUtils.FindNugetGlobalPackageFolder (); public IList ExtraNuGetConfigSources { get; set; } = new List (); - public virtual bool ShouldRestorePackageReferences => PackageReferences?.Count > 0; /// /// If true, the ProjectDirectory will be deleted and populated on the first build /// From 47dc515799e39ba1db2af710349136848bc797f2 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 10 Jul 2023 16:55:58 -0500 Subject: [PATCH 2/2] [Xamarin.ProjectTools] $MSBUILDLOGALLENVIRONMENTVARIABLES=1 MSBuild .binlog files no longer contain environment variables by default. --- .../Tests/Xamarin.ProjectTools/Common/Builder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs index 9a6f7ec88cf..d3d2b31d9d4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/Builder.cs @@ -265,6 +265,7 @@ protected bool BuildInternal (string projectOrSolution, string target, string [] } psi.SetEnvironmentVariable ("MSBUILD", "msbuild"); + psi.SetEnvironmentVariable ("MSBUILDLOGALLENVIRONMENTVARIABLES", "1"); // So .binlog files contain all env vars sw.WriteLine ($"/bl:\"{Path.GetFullPath (Path.Combine (XABuildPaths.TestOutputDirectory, Path.GetDirectoryName (projectOrSolution), $"{binlogName}.binlog"))}\""); if (environmentVariables != null) {