Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add diagnostic support into sample app and AppBuilders on Mono. #53361

Merged
merged 3 commits into from
May 31, 2021
Merged
Show file tree
Hide file tree
Changes from 2 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
2 changes: 2 additions & 0 deletions src/mono/sample/Android/AndroidSampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@
Assemblies="@(BundleAssemblies)"
MainLibraryFileName="$(AssemblyName).dll"
StripDebugSymbols="$(StripDebugSymbols)"
RuntimeComponents="$(RuntimeComponents)"
DiagnosticPorts="$(DiagnosticPorts)"
OutputDir="$(ApkDir)"
AppDir="$(PublishDir)">
<Output TaskParameter="ApkBundlePath" PropertyName="ApkBundlePath" />
Expand Down
9 changes: 8 additions & 1 deletion src/mono/sample/Android/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ DOTNET := ../../../../dotnet.sh
USE_LLVM=true
AOT=false
DEPLOY_AND_RUN?=true
#RUNTIME_COMPONENTS=diagnostics_tracing
#DIAGNOSTIC_PORTS=10.0.2.2:9000,nosuspend
#DIAGNOSTIC_PORTS=10.0.2.2:9000,suspend
#DIAGNOSTIC_PORTS=$(DOTNET_DiagnosticPorts)
Comment on lines +12 to +15
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just setting DiagnosticPorts and not set RuntimeComponents to at least include diagnostics_tracing will generate a build error.

Since they're all commented out, can it be noted in the makefiles that RUNTIME_COMPONENTS and DIAGNOSTIC_PORTS should be uncommented together if at all?

Also, out of curiosity, how were 10.0.2.2:9000 and 127.0.0.1:9000 selected (having no prior context of diagnostic ports)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can add more comments into the script.

There are no dedicated port numbers, so could be anything.

10.0.2.2 is how you reach host loopback from Android emulator (without need to use adb). On iOS, 127.0.0.1 can still be used from simulator. But as above these are just examples and might need to be adjusted if you run different scenario.



all: runtimepack run

Expand All @@ -18,7 +23,9 @@ run:
/p:DeployAndRun=$(DEPLOY_AND_RUN) \
/p:ForceAOT=$(AOT) \
/p:UseLLVM=$(USE_LLVM) \
/p:RunActivity=false
/p:RunActivity=false \
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

clean:
rm -rf ../../../../artifacts/bin/AndroidSampleApp
51 changes: 41 additions & 10 deletions src/mono/sample/iOS/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ MONO_ARCH=x64
DOTNET := ../../../../dotnet.sh
USE_LLVM=true
AOT=false
#RUNTIME_COMPONENTS=diagnostics_tracing
#DIAGNOSTIC_PORTS=127.0.0.1:9000,nosuspend
#DIAGNOSTIC_PORTS=127.0.0.1:9000,suspend
#DIAGNOSTIC_PORTS=$(DOTNET_DiagnosticPorts)

all: runtimepack run

Expand All @@ -15,24 +19,51 @@ runtimepack:
../../../../build.sh Mono+Libs -os iOSSimulator -arch $(MONO_ARCH) -c $(MONO_CONFIG)

run: clean appbuilder
$(DOTNET) publish -c $(MONO_CONFIG) /p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) /p:ForceAOT=$(AOT)
$(DOTNET) publish \
-c $(MONO_CONFIG) \
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) \
/p:ForceAOT=$(AOT) \
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this format
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
instead of like the previous formats
/p:RuntimeComponents=$(RUNTIME_COMPONENTS) \

Copy link
Member Author

@lateralusX lateralusX May 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it includes , in the value it needs to be quoted or you will get msbuild argument parsing errors, just putting "" around value is not enough so complete property needs to be quoted as well in order to correctly go through shell parsing rules, problem is described here:

dotnet/msbuild#2999

and there are various workarounds to the problem, one of them is in this PR, but also suggested in different places, like here dotnet/msbuild#471 (comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, good to know, thanks for the explanation :)

'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

run-sim: clean appbuilder
$(DOTNET) publish -c $(MONO_CONFIG) /p:TargetOS=iOSSimulator /p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) /p:ForceAOT=$(AOT)
$(DOTNET) publish \
-c $(MONO_CONFIG) \
/p:TargetOS=iOSSimulator \
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) \
/p:ForceAOT=$(AOT) \
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

run-catalyst:
$(DOTNET) publish -c $(MONO_CONFIG) /p:TargetOS=MacCatalyst /p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=False /p:ForceAOT=False
$(DOTNET) publish \
-c $(MONO_CONFIG) \
/p:TargetOS=MacCatalyst \
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=False \
/p:ForceAOT=False

run-sim-interp: clean appbuilder
$(DOTNET) publish -c $(MONO_CONFIG) /p:TargetOS=iOSSimulator /p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) /p:ForceAOT=$(AOT) /p:MonoForceInterpreter=true
$(DOTNET) publish \
-c $(MONO_CONFIG) \
/p:TargetOS=iOSSimulator \
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=$(USE_LLVM) \
/p:ForceAOT=$(AOT) \
/p:MonoForceInterpreter=true \
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

run-catalyst-interp:
$(DOTNET) publish -c $(MONO_CONFIG) /p:TargetOS=MacCatalyst /p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=False /p:ForceAOT=False /p:MonoForceInterpreter=true
$(DOTNET) publish \
-c $(MONO_CONFIG) \
/p:TargetOS=MacCatalyst \
/p:TargetArchitecture=$(MONO_ARCH) \
/p:UseLLVM=False \
/p:ForceAOT=False \
/p:MonoForceInterpreter=true

clean:
rm -rf bin
2 changes: 2 additions & 0 deletions src/mono/sample/iOS/Program.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
Optimized="$(Optimized)"
ForceAOT="$(ForceAOT)"
ForceInterpreter="$(MonoForceInterpreter)"
RuntimeComponents="$(RuntimeComponents)"
DiagnosticPorts="$(DiagnosticPorts)"
AppDir="$(MSBuildThisFileDirectory)$(PublishDir)">
<Output TaskParameter="AppBundlePath" PropertyName="AppBundlePath" />
<Output TaskParameter="XcodeProjectPath" PropertyName="XcodeProjectPath" />
Expand Down
6 changes: 6 additions & 0 deletions src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public class AndroidAppBuilderTask : Task
/// </summary>
public string? RuntimeComponents { get; set; } = ""!;

/// <summary>
/// Diagnostic ports configuration string
/// </summary>
public string? DiagnosticPorts { get; set; } = ""!;

[Required]
public string RuntimeIdentifier { get; set; } = ""!;

Expand Down Expand Up @@ -102,6 +107,7 @@ public override bool Execute()
apkBuilder.ForceAOT = ForceAOT;
apkBuilder.StaticLinkedRuntime = StaticLinkedRuntime;
apkBuilder.RuntimeComponents = RuntimeComponents;
apkBuilder.DiagnosticPorts = DiagnosticPorts;
apkBuilder.Assemblies = Assemblies;
(ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(abi, MainLibraryFileName, MonoRuntimeHeaders);

Expand Down
21 changes: 21 additions & 0 deletions src/tasks/AndroidAppBuilder/ApkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public class ApkBuilder
public bool EnableRuntimeLogging { get; set; }
public bool StaticLinkedRuntime { get; set; }
public string? RuntimeComponents { get; set; }
public string? DiagnosticPorts { get; set; }
public ITaskItem[] Assemblies { get; set; } = Array.Empty<ITaskItem>();

public (string apk, string packageId) BuildApk(
Expand Down Expand Up @@ -79,6 +80,21 @@ public class ApkBuilder
throw new InvalidOperationException("Interpreter and AOT cannot be enabled at the same time");
}

if (!string.IsNullOrEmpty(DiagnosticPorts))
{
bool validDiagnosticsConfig = false;

if (string.IsNullOrEmpty(RuntimeComponents))
validDiagnosticsConfig = false;
else if (RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
validDiagnosticsConfig = true;
else if (RuntimeComponents.Contains("diagnostics_tracing", StringComparison.OrdinalIgnoreCase))
validDiagnosticsConfig = true;

if (!validDiagnosticsConfig)
throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component.");
}

// Try to get the latest build-tools version if not specified
if (string.IsNullOrEmpty(BuildToolsVersion))
BuildToolsVersion = GetLatestBuildTools(AndroidSdk);
Expand Down Expand Up @@ -268,6 +284,11 @@ public class ApkBuilder
defines = "add_definitions(-DFORCE_AOT=1)";
}

if (!string.IsNullOrEmpty(DiagnosticPorts))
{
defines += "\nadd_definitions(-DDIAGNOSTIC_PORTS=\"" + DiagnosticPorts + "\")";
}

cmakeLists = cmakeLists.Replace("%Defines%", defines);

File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);
Expand Down
20 changes: 16 additions & 4 deletions src/tasks/AndroidAppBuilder/Templates/monodroid.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,12 +205,20 @@ cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data)
int
mono_droid_runtime_init (const char* executable, int managed_argc, char* managed_argv[])
{
// NOTE: these options can be set via command line args for adb or xharness, see AndroidSampleApp.csproj

// uncomment for debug output:
//
//setenv ("XUNIT_VERBOSE", "true", true);
//setenv ("MONO_LOG_LEVEL", "debug", true);
//setenv ("MONO_LOG_MASK", "all", true);
// NOTE: these options can be set via command line args for adb or xharness, see AndroidSampleApp.csproj

// build using DiagnosticPorts property in AndroidAppBuilder
// or set DOTNET_DiagnosticPorts env via adb, xharness when undefined.
// NOTE, using DOTNET_DiagnosticPorts requires app build using AndroidAppBuilder and RuntimeComponents=diagnostics_tracing
#ifdef DIAGNOSTIC_PORTS
setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true);
#endif

bool wait_for_debugger = false;
chdir (bundle_path);
Expand Down Expand Up @@ -266,14 +274,18 @@ mono_droid_runtime_init (const char* executable, int managed_argc, char* managed
mono_jit_set_aot_mode(MONO_AOT_MODE_FULL);
#endif

mono_jit_init_version ("dotnet.android", "mobile");
MonoDomain *domain = mono_jit_init_version ("dotnet.android", "mobile");
assert (domain);

MonoAssembly *assembly = mono_droid_load_assembly (executable, NULL);
assert (assembly);
LOG_INFO ("Executable: %s", executable);

int res = mono_jit_exec (mono_domain_get (), assembly, managed_argc, managed_argv);
LOG_INFO ("Executable: %s", executable);
int res = mono_jit_exec (domain, assembly, managed_argc, managed_argv);
LOG_INFO ("Exit code: %d.", res);

mono_jit_cleanup (domain);

return res;
}

Expand Down
21 changes: 21 additions & 0 deletions src/tasks/AppleAppBuilder/AppleAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ public string TargetOS
/// </summary>
public string? RuntimeComponents { get; set; } = ""!;

/// <summary>
/// Diagnostic ports configuration string
/// </summary>
public string? DiagnosticPorts { get; set; } = ""!;

/// <summary>
/// Forces the runtime to use the invariant mode
/// </summary>
Expand Down Expand Up @@ -198,10 +203,26 @@ public override bool Execute()
throw new InvalidOperationException("Interpreter and AOT cannot be enabled at the same time");
}

if (!string.IsNullOrEmpty(DiagnosticPorts))
{
bool validDiagnosticsConfig = false;

if (string.IsNullOrEmpty(RuntimeComponents))
validDiagnosticsConfig = false;
else if (RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
validDiagnosticsConfig = true;
else if (RuntimeComponents.Contains("diagnostics_tracing", StringComparison.OrdinalIgnoreCase))
validDiagnosticsConfig = true;

if (!validDiagnosticsConfig)
throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component.");
}

if (GenerateXcodeProject)
{
Xcode generator = new Xcode(TargetOS, Arch);
generator.EnableRuntimeLogging = EnableRuntimeLogging;
generator.DiagnosticPorts = DiagnosticPorts;

XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles,
AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, RuntimeComponents, NativeMainSource);
Expand Down
13 changes: 12 additions & 1 deletion src/tasks/AppleAppBuilder/Templates/runtime.m
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@
setenv ("MONO_LOG_MASK", "all", TRUE);
#endif

// build using DiagnosticPorts property in AppleAppBuilder
// or set DOTNET_DiagnosticPorts env via mlaunch, xharness when undefined.
// NOTE, using DOTNET_DiagnosticPorts requires app build using AppleAppBuilder and RuntimeComponents=diagnostics_tracing
#ifdef DIAGNOSTIC_PORTS
setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true);
#endif

id args_array = [[NSProcessInfo processInfo] arguments];
assert ([args_array count] <= 128);
const char *managed_argv [128];
Expand Down Expand Up @@ -308,7 +315,9 @@
char* options[] = { "--debugger-agent=transport=dt_socket,server=y,address=0.0.0.0:55555" };
mono_jit_parse_options (1, options);
}
mono_jit_init_version ("dotnet.ios", "mobile");

MonoDomain *domain = mono_jit_init_version ("dotnet.ios", "mobile");
assert (domain);

#if !FORCE_INTERPRETER && (!TARGET_OS_SIMULATOR || FORCE_AOT)
// device runtimes are configured to use lazy gc thread creation
Expand All @@ -326,5 +335,7 @@
// Print this so apps parsing logs can detect when we exited
os_log_info (OS_LOG_DEFAULT, "Exit code: %d.", res);

mono_jit_cleanup (domain);

exit (res);
}
6 changes: 6 additions & 0 deletions src/tasks/AppleAppBuilder/Xcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public Xcode(string target, string arch)
}

public bool EnableRuntimeLogging { get; set; }
public string? DiagnosticPorts { get; set; } = ""!;

public string GenerateXCode(
string projectName,
Expand Down Expand Up @@ -212,6 +213,11 @@ public string GenerateXCode(
defines.AppendLine("add_definitions(-DENABLE_RUNTIME_LOGGING=1)");
}

if (!string.IsNullOrEmpty(DiagnosticPorts))
{
defines.AppendLine("\nadd_definitions(-DDIAGNOSTIC_PORTS=\"" + DiagnosticPorts + "\")");
}

cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString());

string plist = Utils.GetEmbeddedResource("Info.plist.template")
Expand Down