diff --git a/Documentation/docs-mobile/messages/index.md b/Documentation/docs-mobile/messages/index.md index 6ccfa15d29f..468df94741c 100644 --- a/Documentation/docs-mobile/messages/index.md +++ b/Documentation/docs-mobile/messages/index.md @@ -220,8 +220,6 @@ Either change the value in the AndroidManifest.xml to match the $(SupportedOSPla + [XA4250](xa4250.md): Manifest-referenced type '{type}' was not found in any scanned assembly. It may be a framework type. + [XA4252](xa4252.md): Insecure HTTP Maven repository URL '{url}' is not allowed. Use an HTTPS URL, or set AllowInsecureHttp="true" metadata on the item to override this check. + [XA4253](xa4253.md): Generated Java callable wrapper code changed: '{path}' -+ [XA4254](xa4254.md): Trimmable type map Java source input directory '{input}' and output directory '{output}' must be different. -+ [XA4255](xa4255.md): Generated trimmable type map Java source '{path}' was not found. + XA4300: Native library '{library}' will not be bundled because it has an unsupported ABI. + [XA4301](xa4301.md): Apk already contains the item `xxx`. + [XA4302](xa4302.md): Unhandled exception merging \`AndroidManifest.xml\`: {ex} diff --git a/Documentation/docs-mobile/messages/xa4254.md b/Documentation/docs-mobile/messages/xa4254.md deleted file mode 100644 index 6997cf235b1..00000000000 --- a/Documentation/docs-mobile/messages/xa4254.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: .NET for Android error XA4254 -description: XA4254 error code -ms.date: 05/20/2026 -f1_keywords: - - "XA4254" ---- - -# .NET for Android error XA4254 - -## Example message - -```text -error XA4254: Trimmable type map Java source input directory 'obj/Release/net11.0-android/typemap/java' and output directory 'obj/Release/net11.0-android/typemap/java' must be different. -``` - -## Issue - -The trimmable type map build tried to clean the Java source output directory, but the configured input and output directories resolved to the same path. - -Cleaning the output directory in this configuration would delete the input Java sources before they can be copied. - -## Solution - -This error indicates an internal build configuration problem. File an issue at and include the full build log. diff --git a/Documentation/docs-mobile/messages/xa4255.md b/Documentation/docs-mobile/messages/xa4255.md deleted file mode 100644 index 633df761ecb..00000000000 --- a/Documentation/docs-mobile/messages/xa4255.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: .NET for Android error XA4255 -description: XA4255 error code -ms.date: 05/20/2026 -f1_keywords: - - "XA4255" ---- - -# .NET for Android error XA4255 - -## Example message - -```text -error XA4255: Generated trimmable type map Java source 'obj/Release/net11.0-android/typemap/java/my/app/MainActivity.java' was not found. -``` - -## Issue - -The post-trim trimmable type map scan expected to copy a generated Java source file from the pre-trim Java source directory, but the file was missing. - -This can happen if intermediate build outputs are stale or if the generated Java source list no longer matches the files on disk. - -## Solution - -Delete the project's `obj` and `bin` directories, then rebuild. - -If the error persists after a clean rebuild, file an issue at and include the full build log. diff --git a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs index 95d0446b205..e5c2a37be5a 100644 --- a/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs +++ b/src/Microsoft.Android.Sdk.TrimmableTypeMap/TrimmableTypeMapGenerator.cs @@ -34,8 +34,7 @@ public TrimmableTypeMapResult Execute ( ManifestConfig? manifestConfig = null, XDocument? manifestTemplate = null, string? packageNamingPolicy = null, - int maxArrayRank = 0, - bool generateTypeMapAssemblies = true) + int maxArrayRank = 0) { _ = assemblies ?? throw new ArgumentNullException (nameof (assemblies)); _ = systemRuntimeVersion ?? throw new ArgumentNullException (nameof (systemRuntimeVersion)); @@ -55,9 +54,7 @@ public TrimmableTypeMapResult Execute ( PropagateDeferredRegistrationToBaseClasses (allPeers); PropagateCannotRegisterToDescendants (allPeers); - var generatedAssemblies = generateTypeMapAssemblies - ? GenerateTypeMapAssemblies (allPeers, systemRuntimeVersion, useSharedTypemapUniverse, maxArrayRank) - : []; + var generatedAssemblies = GenerateTypeMapAssemblies (allPeers, systemRuntimeVersion, useSharedTypemapUniverse, maxArrayRank); var jcwPeers = allPeers.Where (ShouldGenerateJcw).ToList (); logger.LogGeneratingJcwFilesInfo (jcwPeers.Count, allPeers.Count); var generatedJavaSources = GenerateJcwJavaSources (jcwPeers); diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets index 293f19585ef..a76819a61a1 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.CoreCLR.targets @@ -48,45 +48,6 @@ OutputFile="$(_ProguardProjectConfiguration)" /> - - - <_PostTrimTrimmableTypeMapInputAssemblies Include="@(ResolvedFileToPublish)" - Condition=" '%(Extension)' == '.dll' " /> - - - - - - - - - - - - - - - <_PostTrimTrimmableTypeMapInputAssemblies Remove="@(_PostTrimTrimmableTypeMapInputAssemblies)" /> - <_PostTrimGeneratedJavaFiles Remove="@(_PostTrimGeneratedJavaFiles)" /> - - $(_TypeMapBaseOutputDir)typemap/ <_TypeMapJavaOutputDirectory>$(_TypeMapBaseOutputDir)typemap/java <_TypeMapAssembliesListFile>$(_TypeMapOutputDirectory)typemap-assemblies.txt - <_PostTrimTypeMapJavaOutputDirectory>$(_TypeMapBaseOutputDir)typemap/linked-java - <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' and '$(_AndroidRuntime)' == 'CoreCLR' and '$(PublishTrimmed)' == 'true' ">$(_PostTrimTypeMapJavaOutputDirectory) - <_TypeMapJavaStubsSourceDirectory Condition=" '$(_TypeMapJavaStubsSourceDirectory)' == '' ">$(_TypeMapJavaOutputDirectory) - <_PostTrimTrimmableTypeMapJavaStamp>$(_TypeMapBaseOutputDir)stamp/_GeneratePostTrimTrimmableTypeMapJavaSources.stamp - <_TrimmableJavaSourceStamp Condition=" '$(_TrimmableJavaSourceStamp)' == '' and '$(_AndroidRuntime)' == 'CoreCLR' and '$(PublishTrimmed)' == 'true' ">$(_PostTrimTrimmableTypeMapJavaStamp) - <_TrimmableJavaSourceStamp Condition=" '$(_TrimmableJavaSourceStamp)' == '' ">$(_TypeMapOutputDirectory)$(_TypeMapAssemblyName).dll @@ -257,7 +251,7 @@ Outputs="$(_AndroidStampDirectory)_GenerateJavaStubs.stamp"> - <_TypeMapJavaFiles Include="$(_TypeMapJavaStubsSourceDirectory)/**/*.java" /> + <_TypeMapJavaFiles Include="$(_TypeMapJavaOutputDirectory)/**/*.java" /> diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs index 5cac2796ba4..ade630a75b1 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs @@ -1560,24 +1560,6 @@ public static string XA4251 { } } - /// - /// Looks up a localized string similar to Trimmable type map Java source input directory '{0}' and output directory '{1}' must be different.. - /// - public static string XA4254 { - get { - return ResourceManager.GetString("XA4254", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Generated trimmable type map Java source '{0}' was not found.. - /// - public static string XA4255 { - get { - return ResourceManager.GetString("XA4255", resourceCulture); - } - } - /// /// Looks up a localized string similar to Native library '{0}' will not be bundled because it has an unsupported ABI. Move this file to a directory with a valid Android ABI name such as 'libs/armeabi-v7a/'.. /// diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx index c32ef056881..db4965aed50 100644 --- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx +++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx @@ -1145,17 +1145,6 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS Generated Java callable wrapper code changed: '{0}' {0} - The path to the generated Java callable wrapper file - - Trimmable type map Java source input directory '{0}' and output directory '{1}' must be different. - The following are literal names and should not be translated: Trimmable type map, Java. -{0} - Full path to the Java source input directory -{1} - Full path to the Java source output directory - - - Generated trimmable type map Java source '{0}' was not found. - The following are literal names and should not be translated: trimmable type map, Java. -{0} - Full path to the generated Java source file - Command '{0}' failed.\n{1} '{0}' is a failed command name (potentially with path) followed by all the arguments passed to it. {1} is the combined output on the standard error and standard output streams. diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs index 9a03ef4ff21..6184f36b467 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTrimmableTypeMap.cs @@ -57,7 +57,6 @@ public void LogJniAddNativeMethodRegistrationAttributeError (string managedTypeN public string OutputDirectory { get; set; } = ""; [Required] public string JavaSourceOutputDirectory { get; set; } = ""; - public string? JavaSourceInputDirectory { get; set; } [Required] public string TargetFrameworkVersion { get; set; } = ""; @@ -93,8 +92,6 @@ public void LogJniAddNativeMethodRegistrationAttributeError (string managedTypeN public string? ManifestPlaceholders { get; set; } public string? CheckedBuild { get; set; } public string? ApplicationJavaClass { get; set; } - public bool GenerateTypeMapAssemblies { get; set; } = true; - public bool CleanJavaSourceOutputDirectory { get; set; } [Output] public ITaskItem [] GeneratedAssemblies { get; set; } = []; @@ -119,19 +116,8 @@ public override bool RunTask () foreach (var assemblyName in FrameworkAssemblyNames) { frameworkAssemblyNames.Add (assemblyName); } - if (CleanJavaSourceOutputDirectory && !JavaSourceInputDirectory.IsNullOrEmpty ()) { - var inputDirectory = Path.GetFullPath (JavaSourceInputDirectory); - var outputDirectory = Path.GetFullPath (JavaSourceOutputDirectory); - if (string.Equals (inputDirectory, outputDirectory, StringComparison.OrdinalIgnoreCase)) { - Log.LogCodedError ("XA4254", Properties.Resources.XA4254, inputDirectory, outputDirectory); - return false; - } - } Directory.CreateDirectory (OutputDirectory); - if (CleanJavaSourceOutputDirectory && Directory.Exists (JavaSourceOutputDirectory)) { - Directory.Delete (JavaSourceOutputDirectory, recursive: true); - } Directory.CreateDirectory (JavaSourceOutputDirectory); var peReaders = new List (); @@ -182,16 +168,11 @@ public override bool RunTask () manifestConfig: manifestConfig, manifestTemplate: manifestTemplate, packageNamingPolicy: PackageNamingPolicy, - maxArrayRank: MaxArrayRank, - generateTypeMapAssemblies: GenerateTypeMapAssemblies); + maxArrayRank: MaxArrayRank); - if (GenerateTypeMapAssemblies) { - GeneratedAssemblies = WriteAssembliesToDisk (result.GeneratedAssemblies, assemblyInputs.Select (i => i.Path).ToList ()); - WriteGeneratedAssembliesListFile (GeneratedAssemblies); - } - GeneratedJavaFiles = JavaSourceInputDirectory.IsNullOrEmpty () - ? WriteJavaSourcesToDisk (result.GeneratedJavaSources) - : CopyJavaSourcesFromInputDirectory (result.GeneratedJavaSources); + GeneratedAssemblies = WriteAssembliesToDisk (result.GeneratedAssemblies, assemblyInputs.Select (i => i.Path).ToList ()); + WriteGeneratedAssembliesListFile (GeneratedAssemblies); + GeneratedJavaFiles = WriteJavaSourcesToDisk (result.GeneratedJavaSources); // Write manifest to disk if generated if (result.Manifest is not null && !MergedAndroidManifestOutput.IsNullOrEmpty ()) { @@ -266,29 +247,6 @@ void WriteGeneratedAssembliesListFile (IReadOnlyList assemblies) Files.CopyIfStringChanged (text, GeneratedAssembliesListFile); } - ITaskItem [] CopyJavaSourcesFromInputDirectory (IReadOnlyList javaSources) - { - var items = new List (); - foreach (var source in javaSources) { - string inputPath = Path.Combine (JavaSourceInputDirectory ?? "", source.RelativePath); - if (!File.Exists (inputPath)) { - Log.LogCodedError ("XA4255", Properties.Resources.XA4255, inputPath); - continue; - } - - string outputPath = Path.Combine (JavaSourceOutputDirectory, source.RelativePath); - string? dir = Path.GetDirectoryName (outputPath); - if (!string.IsNullOrEmpty (dir)) { - Directory.CreateDirectory (dir); - } - using (var stream = File.OpenRead (inputPath)) { - Files.CopyIfStreamChanged (stream, outputPath); - } - items.Add (new TaskItem (outputPath)); - } - return items.ToArray (); - } - ITaskItem [] WriteAssembliesToDisk (IReadOnlyList assemblies, IReadOnlyList assemblyPaths) { // Build a map from assembly name -> source path for timestamp comparison diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs index 6b693640cfa..705dea7c7e4 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs @@ -318,11 +318,6 @@ public void ReleaseCoreClrTrimmableTypeMap_SingleRuntimeIdentifier_PackagesLinke var typeMapDirectory = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "typemap")); var linkedAssemblyDirectory = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "linked")); var readyToRunAssemblyDirectory = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "R2R")); - var javaSourceDirectory = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "android", "src")); - var dexFile = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "android", "bin", "classes.dex")); - var acwMapPath = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "acw-map.txt")); - var proguardPrimaryPath = builder.Output.GetIntermediaryPath (Path.Combine ("android-arm64", "proguard", "proguard_project_primary.cfg")); - DirectoryAssert.Exists (typeMapDirectory, "trimmable build should generate typemap assemblies."); DirectoryAssert.Exists (linkedAssemblyDirectory, "Release trimmable build should run ILLink."); @@ -363,8 +358,6 @@ public void ReleaseCoreClrTrimmableTypeMap_SingleRuntimeIdentifier_PackagesLinke expectedHash.SequenceEqual (packagedHash), $"{apkPath} should package post-link typemap assembly {pair.Key} from {pair.Value}, not the generated pre-link copy."); } - - AssertPostTrimR8InputsExcludeDeadFrameworkImplementor (dexFile, javaSourceDirectory, acwMapPath, proguardPrimaryPath); } [Test] @@ -652,35 +645,6 @@ ISet ReadPackagedManagedAssemblyNames (string apkPath, AndroidTargetArch .ToHashSet (StringComparer.Ordinal); } - void AssertPostTrimR8InputsExcludeDeadFrameworkImplementor (string dexFile, string javaSourceDirectory, string acwMapPath, string proguardPrimaryPath) - { - const string deadManagedType = "Android.Animation.Animator+IAnimatorListenerImplementor"; - const string deadJavaName = "Lmono/android/animation/Animator_AnimatorListenerImplementor;"; - const string deadJavaDotName = "mono.android.animation.Animator_AnimatorListenerImplementor"; - - Assert.IsTrue ( - Directory.EnumerateFiles (javaSourceDirectory, "MainActivity.java", SearchOption.AllDirectories).Any (), - "Post-trim Java source generation should keep the app activity JCW."); - FileAssert.DoesNotExist ( - Path.Combine (javaSourceDirectory, "mono", "android", "animation", "Animator_AnimatorListenerImplementor.java"), - "Post-trim Java source generation should not copy framework listener implementors removed by ILLink."); - - FileAssert.Exists (acwMapPath, "Post-trim scan should rewrite acw-map.txt for R8."); - var acwMap = File.ReadAllText (acwMapPath); - Assert.IsFalse (acwMap.Contains (deadManagedType, StringComparison.Ordinal), $"{acwMapPath} should be based on linked assemblies."); - Assert.IsFalse (acwMap.Contains (deadJavaDotName, StringComparison.Ordinal), $"{acwMapPath} should not keep removed framework listener implementors."); - - FileAssert.Exists (proguardPrimaryPath, "R8 should generate a primary proguard configuration from the post-trim acw-map."); - Assert.IsFalse ( - File.ReadAllText (proguardPrimaryPath).Contains (deadJavaDotName, StringComparison.Ordinal), - $"{proguardPrimaryPath} should not keep removed framework listener implementors."); - - FileAssert.Exists (dexFile, "R8 should produce classes.dex."); - Assert.IsFalse ( - DexUtils.ContainsClass (deadJavaName, dexFile, AndroidSdkPath), - $"{dexFile} should not contain the removed framework listener implementor."); - } - string FindOutputFile (ProjectBuilder builder, XamarinAndroidApplicationProject proj, string fileName) { var outputDirectory = Path.Combine (Root, builder.ProjectDirectory, proj.OutputPath);