Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions build-tools/banned-apis/banned-apis.targets
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<Project>
<PropertyGroup>
<WarningsAsErrors>RS0030</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" />
</ItemGroup>
</Project>
<Project>
<PropertyGroup>
<WarningsAsErrors>RS0030</WarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" PrivateAssets="All" />
<AdditionalFiles Include="$(MSBuildThisFileDirectory)BannedSymbols.txt" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
<ItemGroup>
<RuntimeHostConfigurationOption Include="Microsoft.Android.Runtime.RuntimeFeature.TrimmableTypeMap"
Value="true" Trim="true" />
<RuntimeHostConfigurationOption Include="Java.Interop.RuntimeFeature.ManagedPeerNativeRegistration"
Value="false" Trim="true" />
<RuntimeHostConfigurationOption Include="System.Runtime.InteropServices.TypeMappingEntryAssembly"
Value="$(_TypeMapAssemblyName)" />
<!-- [Export] metadata is still needed at compile time, but the legacy runtime helper
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using Mono.Cecil;
Expand All @@ -11,6 +12,7 @@
using Xamarin.Android.Tasks;
using Xamarin.Android.Tools;
using Xamarin.ProjectTools;
using Xamarin.Tools.Zip;

namespace Xamarin.Android.Build.Tests {
[TestFixture]
Expand Down Expand Up @@ -398,6 +400,16 @@ public void TrimmableTypeMap_RuntimeArtifacts_ArePackagedInSdk ()
}) {
FileAssert.Exists (Path.Combine (toolsDir, file), $"{file} should exist in the SDK pack.");
}

var trimmableJar = Path.Combine (toolsDir, "java_runtime_trimmable.jar");
using (var zip = ZipArchive.Open (trimmableJar, FileMode.Open)) {
zip.AssertDoesNotContainEntry (trimmableJar, "net/dot/jni/ManagedPeer.class");
}

var trimmableDex = Path.Combine (toolsDir, "java_runtime_trimmable.dex");
Assert.IsFalse (
FileContainsAscii (trimmableDex, "Lnet/dot/jni/ManagedPeer;"),
"java_runtime_trimmable.dex should not contain the Java ManagedPeer type descriptor.");
}

// T1: end-to-end build coverage for [Export] and [ExportField] under trimmable.
Expand Down Expand Up @@ -451,14 +463,20 @@ class ExportShapes : Java.Lang.Object {
// to avoid coupling to the hash.
string? exportShapesJava = null;
string? exportShapesText = null;
var managedPeerReferences = new List<string> ();
foreach (var f in allJavaFiles) {
var text = File.ReadAllText (f);
if (text.Contains ("EchoString") && text.Contains ("InitialFoo")) {
if (text.Contains ("net.dot.jni.ManagedPeer", StringComparison.Ordinal)) {
managedPeerReferences.Add (f);
}
if (exportShapesJava == null && text.Contains ("EchoString") && text.Contains ("InitialFoo")) {
exportShapesJava = f;
exportShapesText = text;
break;
}
}
Assert.IsEmpty (managedPeerReferences,
"Trimmable generated Java source should not reference net.dot.jni.ManagedPeer. Offending files:\n " +
string.Join ("\n ", managedPeerReferences));
Assert.IsNotNull (exportShapesJava,
$"Could not find a generated JCW Java file referencing both EchoString and InitialFoo under {javaDir}.");
Assert.IsNotNull (exportShapesText,
Expand Down Expand Up @@ -487,6 +505,9 @@ class ExportShapes : Java.Lang.Object {
var typemapDir = builder.Output.GetIntermediaryPath ("typemap");
var typemapDlls = Directory.GetFiles (typemapDir, "*.TypeMap.dll");
Assert.IsNotEmpty (typemapDlls, "Trimmable typemap should produce at least one *.TypeMap.dll.");

var apk = Path.Combine (Root, builder.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk");
AssertApkDexDoesNotContain (apk, "Lnet/dot/jni/ManagedPeer;");
}

// T6: trim-warning baseline for [Export] under trimmable.
Expand Down Expand Up @@ -595,6 +616,41 @@ public ConcreteProvider (Android.Content.Context context) : base (context) { }
Assert.IsTrue (builder.Build (proj), "Build should have succeeded — abstract types with protected ctors should not cause XAGTT7009.");
}

static void AssertApkDexDoesNotContain (string apk, string value)
{
FileAssert.Exists (apk);
using var zip = ZipArchive.Open (apk, FileMode.Open);
var dexEntries = zip
.Where (entry => entry.FullName.StartsWith ("classes", StringComparison.Ordinal) &&
entry.FullName.EndsWith (".dex", StringComparison.Ordinal))
.ToArray ();
Assert.IsNotEmpty (dexEntries, $"{apk} should contain at least one dex file.");

foreach (var entry in dexEntries) {
Assert.IsFalse (
EntryContainsAscii (entry, value),
$"{entry.FullName} should not contain {value}.");
}
}

static bool EntryContainsAscii (ZipEntry entry, string value)
{
using var stream = new MemoryStream ();
entry.Extract (stream);
return ContainsAscii (stream.ToArray (), value);
}

static bool FileContainsAscii (string file, string value)
{
return ContainsAscii (File.ReadAllBytes (file), value);
}

static bool ContainsAscii (byte [] data, string value)
{
var pattern = Encoding.ASCII.GetBytes (value);
return data.AsSpan ().IndexOf (pattern) >= 0;
}

static void AssertTrimmableTypeMapOutputs (string typemapDir)
{
DirectoryAssert.Exists (typemapDir);
Expand All @@ -603,7 +659,6 @@ static void AssertTrimmableTypeMapOutputs (string typemapDir)

var javaDir = Path.Combine (typemapDir, "java");
DirectoryAssert.Exists (javaDir, "Trimmable JCW Java output directory should exist.");

var javaFiles = Directory.GetFiles (javaDir, "*.java", SearchOption.AllDirectories);
Assert.IsNotEmpty (javaFiles, "At least one trimmable JCW Java source file should be generated.");
}
Expand Down
2 changes: 1 addition & 1 deletion src/java-runtime/java-runtime.targets
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<OutputDex>$(OutputPath)java_runtime_trimmable.dex</OutputDex>
<IntermediateRuntimeOutputPath>$(IntermediateOutputPath)release-trimmable</IntermediateRuntimeOutputPath>
<IntermediateRuntimeClassesTxt>$(IntermediateOutputPath)release-trimmable.txt</IntermediateRuntimeClassesTxt>
<RemoveItems>..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java;$(JavaInteropSourceDirectory)\src\Java.Interop\java\net\dot\jni\internal\JavaProxyObject.java;$(JavaInteropSourceDirectory)\src\Java.Interop\java\net\dot\jni\internal\JavaProxyThrowable.java</RemoveItems>
<RemoveItems>..\..\src-ThirdParty\bazel\java\mono\android\debug\MultiDexLoader.java;java\mono\android\debug-net6\BuildConfig.java;java\mono\android\debug\BuildConfig.java;java\mono\android\release\BuildConfig.java;java\mono\android\MonoPackageManager.java;$(JavaInteropSourceDirectory)\src\Java.Interop\java\net\dot\jni\ManagedPeer.java;$(JavaInteropSourceDirectory)\src\Java.Interop\java\net\dot\jni\internal\JavaProxyObject.java;$(JavaInteropSourceDirectory)\src\Java.Interop\java\net\dot\jni\internal\JavaProxyThrowable.java</RemoveItems>
<AddItems>java-trimmable\net\dot\jni\internal\JavaProxyObject.java;java-trimmable\net\dot\jni\internal\JavaProxyThrowable.java</AddItems>
</_RuntimeOutput>
<_RuntimeOutput Include="$(OutputPath)java_runtime_fastdev.jar">
Expand Down