Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,13 @@ _ResolveAssemblies MSBuild target.
<ItemGroup>
<_ResolvedNativeLibraries Include="@(ResolvedFileToPublish)" Condition=" '%(ResolvedFileToPublish.Extension)' == '.so' " />
</ItemGroup>
<ItemGroup>
<ItemGroup Condition="'$(_AndroidRuntime)' == 'Mono'">
<_MonoComponent Condition=" '$(AndroidEnableProfiler)' == 'true' " Include="diagnostics_tracing" />
<_MonoComponent Condition=" '$(AndroidUseInterpreter)' == 'true' " Include="hot_reload" />
<_MonoComponent Condition=" '$(AndroidIncludeDebugSymbols)' == 'true' " Include="debugger" />
<_MonoComponent Condition=" '$(_AndroidExcludeMarshalIlgenComponent)' != 'true' " Include="marshal-ilgen" />
</ItemGroup>
<ItemGroup>
<!-- Filename without extension -->
<_ExcludedNativeLibraries Condition=" '$(_AndroidIncludeSystemGlobalizationNative)' != 'true' " Include="libSystem.Globalization.Native" />
<_ExcludedNativeLibraries Condition=" '$(_AndroidEnableNativeStackTracing)' != 'true' " Include="libxamarin-native-tracing" />
Expand Down Expand Up @@ -274,6 +276,17 @@ _ResolveAssemblies MSBuild target.
KnownRuntimeNativeLibraries="@(_KnownRuntimeNativeLibrary)">
<Output TaskParameter="OutputLibraries" ItemName="FrameworkNativeLibrary" />
</ProcessNativeLibraries>

<ItemGroup Condition=" '$(AndroidEnableDebugger)' == 'true' and '$(_AndroidRuntime)' == 'CoreCLR' ">
<AndroidNativeLibrary Include="$(AndroidDebuggerNativeLibraryPath)\arm64-v8a\libremotemscordbitarget.so"
Condition="Exists('$(AndroidDebuggerNativeLibraryPath)\arm64-v8a\libremotemscordbitarget.so')">
<Abi>arm64-v8a</Abi>
</AndroidNativeLibrary>
<AndroidNativeLibrary Include="$(AndroidDebuggerNativeLibraryPath)\x86_64\libremotemscordbitarget.so"
Condition="Exists('$(AndroidDebuggerNativeLibraryPath)\x86_64\libremotemscordbitarget.so')">
<Abi>x86_64</Abi>
</AndroidNativeLibrary>
</ItemGroup>
</Target>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,6 @@
<_AndroidFastDeploymentSupported Condition=" Exists ('$(MSBuildThisFileDirectory)../tools/Xamarin.Android.Common.Debugging.targets') ">true</_AndroidFastDeploymentSupported>
<_AndroidFastDeploymentSupported Condition=" '$(_AndroidFastDeploymentSupported)' == '' ">False</_AndroidFastDeploymentSupported>

<!-- TODO: remove when we have debugger support for CoreCLR -->
<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' and '$(Configuration)' == 'Debug' ">true</UseMonoRuntime>

<!--
Disable @(Content) from referenced projects
See: https://github.com/dotnet/sdk/blob/955c0fc7b06e2fa34bacd076ed39f61e4fb61716/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L16
Expand Down Expand Up @@ -57,6 +54,11 @@
<AndroidEnableProfiler Condition=" '$(AndroidEnableProfiler)' == '' and ('$(DiagnosticConfiguration)' != '' or '$(DiagnosticAddress)' != '' or '$(DiagnosticPort)' != '' or '$(DiagnosticSuspend)' != '' or '$(DiagnosticListenMode)' != '') ">true</AndroidEnableProfiler>
<AndroidEnableProfiler Condition=" '$(AndroidEnableProfiler)' == '' ">false</AndroidEnableProfiler>

<AndroidEnableDebugger Condition=" '$(AndroidEnableDebugger)' == '' and '$(_AndroidRuntime)' == 'CoreCLR' and '$(Configuration)' != 'Release' ">true</AndroidEnableDebugger>
<AndroidEnableDebugger Condition=" '$(AndroidEnableDebugger)' == '' ">false</AndroidEnableDebugger>
<AndroidDebuggerPort Condition=" '$(AndroidDebuggerPort)' == '' ">4711</AndroidDebuggerPort>
<AndroidDebuggerNativeLibraryPath Condition=" '$(AndroidDebuggerNativeLibraryPath)' == '' ">$(MSBuildThisFileDirectory)..\tools\libremotemscordbitarget</AndroidDebuggerNativeLibraryPath>

<!--
Android package (apt/aab) alignment, expressed as the page size in kilobytes. Two values are supported: 4 and 16.
Sometime next year 16 is going to be a Google Play store requirement for application submissions.
Expand Down Expand Up @@ -153,6 +155,8 @@

<!-- profiler won't work without internet permission, we must thus force it -->
<AndroidNeedsInternetPermission Condition=" '$(AndroidEnableProfiler)' == 'true' ">True</AndroidNeedsInternetPermission>
<!-- CoreCLR debugger uses gRPC which requires network access -->
<AndroidNeedsInternetPermission Condition=" '$(AndroidEnableDebugger)' == 'true' ">True</AndroidNeedsInternetPermission>
</PropertyGroup>
<!-- Trimmer switches that default to OFF in Release mode -->
<PropertyGroup Condition=" '$(AndroidApplication)' == 'true' and '$(Optimize)' == 'true' ">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public class GenerateNativeApplicationConfigSources : AndroidTask
public string? AndroidSequencePointsMode { get; set; }
public bool EnableSGenConcurrent { get; set; }
public string? CustomBundleConfigFile { get; set; }
public bool EnableDebugger { get; set; }

bool _Debug {
get {
Expand Down Expand Up @@ -118,13 +119,20 @@ public override bool RunTask ()
envBuilder.AddDefaultDebugBuildLogLevel ();
}

if (androidRuntime != Xamarin.Android.Tasks.AndroidRuntime.NativeAOT) {
AddDefaultEnvironmentVariables (envBuilder, HttpClientHandlerType, EnableSGenConcurrent);
} else {
if (androidRuntime == Xamarin.Android.Tasks.AndroidRuntime.NativeAOT) {
// NativeAOT sets all the environment variables from Java, we don't want to repeat that
// process in the native code. This is just a precaution, because NativeAOT builds should
// not even use this task.
envBuilder.EnvironmentVariables.Clear ();
} else if (androidRuntime == Xamarin.Android.Tasks.AndroidRuntime.CoreCLR) {
// CoreCLR needs the HTTP client handler type
envBuilder.AddHttpClientHandlerType (HttpClientHandlerType);
} else {
AddDefaultEnvironmentVariables (envBuilder, HttpClientHandlerType, EnableSGenConcurrent);
}

if (EnableDebugger && TargetsCLR) {
envBuilder.AddDebuggerEnvironment ();
}

global::Android.Runtime.BoundExceptionType boundExceptionType;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,5 +237,116 @@ public void CheckHttpClientHandlerType ([Values] AndroidRuntime runtime)
Assert.AreEqual (expectedUpdatedValue, envvars[httpClientHandlerVarName]);
}
}

[Test]
public void CheckDebuggerEnvironmentVariables ()
{
const string supportedAbis = "arm64-v8a;x86_64";

var proj = new XamarinAndroidApplicationProject () {
IsRelease = false,
};

proj.SetRuntime (AndroidRuntime.CoreCLR);
proj.SetProperty ("AndroidEnableDebugger", "true");
proj.SetAndroidSupportedAbis (supportedAbis);

using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");

string intermediateOutputDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
List<EnvironmentHelper.EnvironmentFile> envFiles = EnvironmentHelper.GatherEnvironmentFiles (intermediateOutputDir, supportedAbis, true, AndroidRuntime.CoreCLR);
Dictionary<string, string> envvars = EnvironmentHelper.ReadEnvironmentVariables (envFiles, AndroidRuntime.CoreCLR);
Assert.IsTrue (envvars.Count > 0, $"No environment variables defined");

Assert.IsTrue (envvars.ContainsKey ("CORECLR_ENABLE_PROFILING"), "Environment should contain CORECLR_ENABLE_PROFILING");
Assert.AreEqual ("1", envvars ["CORECLR_ENABLE_PROFILING"], "CORECLR_ENABLE_PROFILING should be '1'");

Assert.IsTrue (envvars.ContainsKey ("CORECLR_PROFILER"), "Environment should contain CORECLR_PROFILER");
Assert.AreEqual ("{9DC623E8-C88F-4FD5-AD99-77E67E1D9631}", envvars ["CORECLR_PROFILER"], "CORECLR_PROFILER GUID mismatch");

Assert.IsTrue (envvars.ContainsKey ("CORECLR_PROFILER_PATH"), "Environment should contain CORECLR_PROFILER_PATH");
Assert.AreEqual ("libremotemscordbitarget.so", envvars ["CORECLR_PROFILER_PATH"], "CORECLR_PROFILER_PATH should point to libremotemscordbitarget.so");

Assert.IsFalse (envvars.ContainsKey ("MONO_GC_PARAMS"), "CoreCLR builds should not set MONO_GC_PARAMS");
Assert.IsFalse (envvars.ContainsKey ("MONO_DEBUG"), "CoreCLR builds should not set MONO_DEBUG");
}
}

[Test]
public void CheckDebuggerNativeLibraryInApk ()
{
const string supportedAbis = "arm64-v8a;x86_64";

var proj = new XamarinAndroidApplicationProject () {
IsRelease = false,
};

proj.SetRuntime (AndroidRuntime.CoreCLR);
proj.SetProperty ("AndroidEnableDebugger", "true");
proj.SetAndroidSupportedAbis (supportedAbis);

using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");

string apk = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk");
Assert.IsTrue (File.Exists (apk), $"APK not found at {apk}");

foreach (var abi in supportedAbis.Split (';')) {
string entryPath = $"lib/{abi}/libremotemscordbitarget.so";
var data = ZipHelper.ReadFileFromZip (apk, entryPath);
Assert.IsNotNull (data, $"{entryPath} should be present in the APK");
Assert.IsTrue (data.Length > 0, $"{entryPath} should not be empty");
}
}
}

[Test]
public void CheckDebuggerNativeLibraryNotInReleaseApk ()
{
const string supportedAbis = "arm64-v8a";

var proj = new XamarinAndroidApplicationProject () {
IsRelease = true,
};

proj.SetRuntime (AndroidRuntime.CoreCLR);
proj.SetAndroidSupportedAbis (supportedAbis);

using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");

string apk = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk");
Assert.IsTrue (File.Exists (apk), $"APK not found at {apk}");

string entryPath = $"lib/{supportedAbis}/libremotemscordbitarget.so";
var data = ZipHelper.ReadFileFromZip (apk, entryPath);
Assert.IsNull (data, $"{entryPath} should NOT be present in Release APK");
}
}

[Test]
public void CheckDebuggerNotEnabledInRelease ()
{
const string supportedAbis = "arm64-v8a";

var proj = new XamarinAndroidApplicationProject () {
IsRelease = true,
};

proj.SetRuntime (AndroidRuntime.CoreCLR);
proj.SetAndroidSupportedAbis (supportedAbis);

using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");

string intermediateOutputDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
List<EnvironmentHelper.EnvironmentFile> envFiles = EnvironmentHelper.GatherEnvironmentFiles (intermediateOutputDir, supportedAbis, true, AndroidRuntime.CoreCLR);
Dictionary<string, string> envvars = EnvironmentHelper.ReadEnvironmentVariables (envFiles, AndroidRuntime.CoreCLR);

Assert.IsFalse (envvars.ContainsKey ("CORECLR_ENABLE_PROFILING"), "Release builds should not enable CoreCLR profiling");
Assert.IsFalse (envvars.ContainsKey ("CORECLR_PROFILER"), "Release builds should not set CORECLR_PROFILER");
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,5 +108,12 @@ public void AddMonoGcParams (bool enableSgenConcurrent)
AddEnvironmentVariable ("MONO_GC_PARAMS", enableSgenConcurrent ? "major=marksweep-conc" : "major=marksweep");
}

public void AddDebuggerEnvironment ()
{
AddEnvironmentVariable ("CORECLR_ENABLE_PROFILING", "1");
AddEnvironmentVariable ("CORECLR_PROFILER", "{9DC623E8-C88F-4FD5-AD99-77E67E1D9631}");
AddEnvironmentVariable ("CORECLR_PROFILER_PATH", "libremotemscordbitarget.so");
}

static string ValidAssemblerString (string s) => s.Replace ("\\", "\\\\").Replace ("\"", "\\\"");
}
Original file line number Diff line number Diff line change
Expand Up @@ -1715,6 +1715,11 @@ because xbuild doesn't support framework reference assemblies.
<_AllNativeLibraries Include="@(AndroidNativeLibrary);@(EmbeddedNativeLibrary);@(FrameworkNativeLibrary)" />
</ItemGroup>

<ItemGroup Condition=" '$(AndroidEnableDebugger)' == 'true' ">
<!-- CoreCLR remote debugger target library should not be preloaded via JNI; it is loaded as a CLR profiler -->
<_AndroidNativeLibraryNeverJniPreload Include="libremotemscordbitarget.so" />
</ItemGroup>

<ItemGroup Condition=" '$(AndroidIgnoreAllJniPreload)' == 'true' ">
<!-- We include everything, tasks below will take care of exclusion of certain libs from this
item group -->
Expand Down Expand Up @@ -1751,6 +1756,7 @@ because xbuild doesn't support framework reference assemblies.
TargetsCLR="$(_AndroidUseCLR)"
AndroidRuntime="$(_AndroidRuntime)"
ProjectRuntimeConfigFilePath="$(ProjectRuntimeConfigFilePath)"
EnableDebugger="$(AndroidEnableDebugger)"
>
</GenerateNativeApplicationConfigSources>

Expand Down