diff --git a/src/mono/sample/Android/AndroidSampleApp.csproj b/src/mono/sample/Android/AndroidSampleApp.csproj index 14fba9d69a0225..dd52a30abf241c 100644 --- a/src/mono/sample/Android/AndroidSampleApp.csproj +++ b/src/mono/sample/Android/AndroidSampleApp.csproj @@ -79,6 +79,8 @@ Assemblies="@(BundleAssemblies)" MainLibraryFileName="$(AssemblyName).dll" StripDebugSymbols="$(StripDebugSymbols)" + RuntimeComponents="$(RuntimeComponents)" + DiagnosticPorts="$(DiagnosticPorts)" OutputDir="$(ApkDir)" AppDir="$(PublishDir)"> diff --git a/src/mono/sample/Android/Makefile b/src/mono/sample/Android/Makefile index aae622cb2862ed..889e31248dc18c 100644 --- a/src/mono/sample/Android/Makefile +++ b/src/mono/sample/Android/Makefile @@ -4,6 +4,16 @@ DOTNET := ../../../../dotnet.sh USE_LLVM=true AOT=false DEPLOY_AND_RUN?=true +RUNTIME_COMPONENTS=diagnostics_tracing + +#If DIAGNOSTIC_PORTS is enabled, RUNTIME_COMPONENTS must also be enabled. +#If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is optional. +#If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is disabled, use DOTNET_DiagnosticPorts when launching application to enable diagnostics. +#RUNTIME_COMPONENTS=diagnostics_tracing +#DIAGNOSTIC_PORTS=10.0.2.2:9000,nosuspend +#DIAGNOSTIC_PORTS=10.0.2.2:9000,suspend +#DIAGNOSTIC_PORTS=$(DOTNET_DiagnosticPorts) + all: runtimepack run @@ -18,7 +28,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 diff --git a/src/mono/sample/iOS/Makefile b/src/mono/sample/iOS/Makefile index be7c2bcefe0aa6..5cbd1277aa89a5 100644 --- a/src/mono/sample/iOS/Makefile +++ b/src/mono/sample/iOS/Makefile @@ -4,6 +4,14 @@ DOTNET := ../../../../dotnet.sh USE_LLVM=true AOT=false +#If DIAGNOSTIC_PORTS is enabled, RUNTIME_COMPONENTS must also be enabled. +#If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is optional. +#If RUNTIME_COMPONENTS is enabled, DIAGNOSTIC_PORTS is disabled, use DOTNET_DiagnosticPorts when launching application to enable diagnostics. +#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 TOOLS_DIR=../../../tasks @@ -15,24 +23,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)"' \ + '/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 diff --git a/src/mono/sample/iOS/Program.csproj b/src/mono/sample/iOS/Program.csproj index 242896e764b15e..6c238dc62484df 100644 --- a/src/mono/sample/iOS/Program.csproj +++ b/src/mono/sample/iOS/Program.csproj @@ -84,6 +84,8 @@ Optimized="$(Optimized)" ForceAOT="$(ForceAOT)" ForceInterpreter="$(MonoForceInterpreter)" + RuntimeComponents="$(RuntimeComponents)" + DiagnosticPorts="$(DiagnosticPorts)" AppDir="$(MSBuildThisFileDirectory)$(PublishDir)"> diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs index 20438d0bc65588..345ad7219998dc 100644 --- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs +++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs @@ -43,6 +43,11 @@ public class AndroidAppBuilderTask : Task /// public string? RuntimeComponents { get; set; } = ""!; + /// + /// Diagnostic ports configuration string + /// + public string? DiagnosticPorts { get; set; } = ""!; + [Required] public string RuntimeIdentifier { get; set; } = ""!; @@ -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); diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs index 42e5d282d2afc9..ca7c4922ddbbcb 100644 --- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs +++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs @@ -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(); public (string apk, string packageId) BuildApk( @@ -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); @@ -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); diff --git a/src/tasks/AndroidAppBuilder/Templates/monodroid.c b/src/tasks/AndroidAppBuilder/Templates/monodroid.c index 17f6c2b3ad4ec0..7bd0464075ebf9 100644 --- a/src/tasks/AndroidAppBuilder/Templates/monodroid.c +++ b/src/tasks/AndroidAppBuilder/Templates/monodroid.c @@ -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); @@ -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; } diff --git a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs index 3f72ca56cf243e..68ce0e18500137 100644 --- a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs +++ b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs @@ -131,6 +131,11 @@ public string TargetOS /// public string? RuntimeComponents { get; set; } = ""!; + /// + /// Diagnostic ports configuration string + /// + public string? DiagnosticPorts { get; set; } = ""!; + /// /// Forces the runtime to use the invariant mode /// @@ -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); diff --git a/src/tasks/AppleAppBuilder/Templates/runtime.m b/src/tasks/AppleAppBuilder/Templates/runtime.m index 9b90f44972db37..e45455507a138b 100644 --- a/src/tasks/AppleAppBuilder/Templates/runtime.m +++ b/src/tasks/AppleAppBuilder/Templates/runtime.m @@ -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]; @@ -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 @@ -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); } diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs index 6a59b718c5bc42..4409043f00a425 100644 --- a/src/tasks/AppleAppBuilder/Xcode.cs +++ b/src/tasks/AppleAppBuilder/Xcode.cs @@ -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, @@ -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")