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

Fix EventPipe on Android CoreClr. #112270

Merged
Merged
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
4 changes: 4 additions & 0 deletions src/mono/mono/component/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ set(MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME "diagnostics_tracing")
set(MONO_DEBUGGER_COMPONENT_NAME "debugger")
set(MONO_MARSHAL_ILGEN_COMPONENT_NAME "marshal-ilgen")

set(EP_GENERATED_HEADER_PATH "${CMAKE_CURRENT_BINARY_DIR}")
include (${SHARED_EVENTPIPE_SOURCE_PATH}configure.cmake)
include_directories(${SHARED_EVENTPIPE_CONFIG_HEADER_PATH})

add_subdirectory(${SHARED_CONTAINERS_SOURCE_PATH} containers)
add_subdirectory(${SHARED_EVENTPIPE_SOURCE_PATH} eventpipe)

Expand Down
28 changes: 7 additions & 21 deletions src/native/eventpipe/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
include(CheckSymbolExists)
include(CheckIncludeFile)

check_include_file(
sys/socket.h
HAVE_SYS_SOCKET_H
)

check_symbol_exists(
accept4
sys/socket.h
HAVE_ACCEPT4)

# Use TCP for EventPipe on mobile platforms
if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_ANDROID)
set(FEATURE_PERFTRACING_PAL_TCP 1)
set(FEATURE_PERFTRACING_DISABLE_DEFAULT_LISTEN_PORT 1)
endif()

configure_file(${CLR_SRC_NATIVE_DIR}/eventpipe/ep-shared-config.h.in ${CMAKE_CURRENT_BINARY_DIR}/ep-shared-config.h)

# Define the DiagnosticsServer and EventPipe as interface libraries.
# We must define them as interface libraries as each runtime builds the same set of files slightly differently.
# Defining it as an interface library allows us to specify common sources, include directories, dependencies, etc.
# in one place, but also allow each runtime to add any settings that are specific to that runtime.
# This includes, but is not limited to each runtime's implementation of the ds-rt.h and ep-rt.h contracts.

if (NOT DEFINED SHARED_EVENTPIPE_CONFIG_HEADER_PATH)
message(FATAL_ERROR "Required configuration SHARED_EVENTPIPE_CONFIG_HEADER_PATH not set.")
endif (NOT DEFINED SHARED_EVENTPIPE_CONFIG_HEADER_PATH)

add_library(dn-diagnosticserver INTERFACE)

target_sources(dn-diagnosticserver INTERFACE
Expand All @@ -38,10 +21,12 @@ target_sources(dn-diagnosticserver INTERFACE
ds-server.c)

target_include_directories(dn-diagnosticserver INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(dn-diagnosticserver INTERFACE ${SHARED_EVENTPIPE_CONFIG_HEADER_PATH})
target_link_libraries(dn-diagnosticserver INTERFACE dn-containers)

add_library(dn-diagnosticserver-pal INTERFACE)
target_include_directories(dn-diagnosticserver-pal INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(dn-diagnosticserver-pal INTERFACE ${SHARED_EVENTPIPE_CONFIG_HEADER_PATH})
target_link_libraries(dn-diagnosticserver-pal INTERFACE dn-containers)

if (FEATURE_PERFTRACING_PAL_TCP)
Expand Down Expand Up @@ -83,4 +68,5 @@ target_sources(dn-eventpipe INTERFACE
ep-thread.c)

target_include_directories(dn-eventpipe INTERFACE ${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(dn-eventpipe INTERFACE ${SHARED_EVENTPIPE_CONFIG_HEADER_PATH})
target_link_libraries(dn-eventpipe INTERFACE dn-containers)
14 changes: 13 additions & 1 deletion src/native/eventpipe/configure.cmake
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
include(CheckSymbolExists)
include(CheckIncludeFile)

check_include_file(
sys/socket.h
HAVE_SYS_SOCKET_H
)

check_symbol_exists(
accept4
sys/socket.h
HAVE_ACCEPT4)

# Use TCP for EventPipe on mobile platforms
if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_ANDROID)
set(FEATURE_PERFTRACING_PAL_TCP 1)
set(FEATURE_PERFTRACING_DISABLE_DEFAULT_LISTEN_PORT 1)
endif()

if (NOT DEFINED EP_GENERATED_HEADER_PATH)
message(FATAL_ERROR "Required configuration EP_GENERATED_HEADER_PATH not set.")
endif (NOT DEFINED EP_GENERATED_HEADER_PATH)

configure_file(${CLR_SRC_NATIVE_DIR}/eventpipe/ep-shared-config.h.in ${EP_GENERATED_HEADER_PATH}/ep-shared-config.h)

set (SHARED_EVENTPIPE_CONFIG_HEADERS "${EP_GENERATED_HEADER_PATH}/ep-shared-config.h")
set (SHARED_EVENTPIPE_CONFIG_HEADER_PATH "${EP_GENERATED_HEADER_PATH}")
45 changes: 24 additions & 21 deletions src/tasks/AndroidAppBuilder/ApkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ public partial class ApkBuilder
public ITaskItem[] ExtraLinkerArguments { get; set; } = Array.Empty<ITaskItem>();
public string[] NativeDependencies { get; set; } = Array.Empty<string>();
public string RuntimeFlavor { get; set; } = nameof(RuntimeFlavorEnum.Mono);

private RuntimeFlavorEnum parsedRuntimeFlavor;
private bool IsMono => parsedRuntimeFlavor == RuntimeFlavorEnum.Mono;
private bool IsCoreCLR => parsedRuntimeFlavor == RuntimeFlavorEnum.CoreCLR;

private TaskLoggingHelper logger;

Expand All @@ -62,6 +65,11 @@ public ApkBuilder(TaskLoggingHelper logger)
string mainLibraryFileName,
string runtimeHeaders)
{
if (!Enum.TryParse(RuntimeFlavor, true, out parsedRuntimeFlavor))
{
throw new ArgumentException($"Unknown RuntimeFlavor value: {RuntimeFlavor}. '{nameof(RuntimeFlavor)}' must be one of: {string.Join(",", Enum.GetNames(typeof(RuntimeFlavorEnum)))}");
}

if (string.IsNullOrEmpty(AppDir) || !Directory.Exists(AppDir))
{
throw new ArgumentException($"AppDir='{AppDir}' is empty or doesn't exist");
Expand Down Expand Up @@ -106,9 +114,14 @@ public ApkBuilder(TaskLoggingHelper logger)
throw new InvalidOperationException("Interpreter and AOT cannot be enabled at the same time");
}

if (!string.IsNullOrEmpty(DiagnosticPorts) && !Array.Exists(RuntimeComponents, runtimeComponent => string.Equals(runtimeComponent, "diagnostics_tracing", StringComparison.OrdinalIgnoreCase)))
if (IsMono && !string.IsNullOrEmpty(DiagnosticPorts) && !Array.Exists(RuntimeComponents, runtimeComponent => string.Equals(runtimeComponent, "diagnostics_tracing", StringComparison.OrdinalIgnoreCase)))
{
throw new ArgumentException($"Using DiagnosticPorts requires diagnostics_tracing runtime component, which was not included in 'RuntimeComponents' item group. @RuntimeComponents: '{string.Join(", ", RuntimeComponents)}'");
throw new ArgumentException($"Using DiagnosticPorts targeting Mono requires diagnostics_tracing runtime component, which was not included in 'RuntimeComponents' item group. @RuntimeComponents: '{string.Join(", ", RuntimeComponents)}'");
}

if (IsCoreCLR && StaticLinkedRuntime)
{
throw new ArgumentException("Static linking is not supported for CoreCLR runtime");
}

// Try to get the latest build-tools version if not specified
Expand Down Expand Up @@ -148,11 +161,6 @@ public ApkBuilder(TaskLoggingHelper logger)
throw new ArgumentException($"{buildToolsFolder} was not found.");
}

if (!Enum.TryParse(RuntimeFlavor, true, out parsedRuntimeFlavor))
{
throw new ArgumentException($"Unknown RuntimeFlavor value: {RuntimeFlavor}. '{nameof(RuntimeFlavor)}' must be one of: {string.Join(",", Enum.GetNames(typeof(RuntimeFlavorEnum)))}");
}

var assemblerFiles = new StringBuilder();
var assemblerFilesToLink = new StringBuilder();
var aotLibraryFiles = new List<string>();
Expand Down Expand Up @@ -260,22 +268,17 @@ public ApkBuilder(TaskLoggingHelper logger)
else
{
string runtimeLib = "";
if (parsedRuntimeFlavor == RuntimeFlavorEnum.CoreCLR)
if (StaticLinkedRuntime && IsMono)
{
if (StaticLinkedRuntime)
throw new ArgumentException("Static linking is not supported for CoreCLR runtime");
runtimeLib = Path.Combine(AppDir, "libcoreclr.so");
runtimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a");
}
else
else if (IsMono)
{
if (StaticLinkedRuntime)
{
runtimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a");
}
else
{
runtimeLib = Path.Combine(AppDir, "libmonosgen-2.0.so");
}
runtimeLib = Path.Combine(AppDir, "libmonosgen-2.0.so");
}
else if (IsCoreCLR)
{
runtimeLib = Path.Combine(AppDir, "libcoreclr.so");
}

if (!File.Exists(runtimeLib))
Expand Down Expand Up @@ -332,7 +335,7 @@ public ApkBuilder(TaskLoggingHelper logger)
nativeLibraries += assemblerFilesToLink.ToString();

string aotSources = assemblerFiles.ToString();
string monodroidSource = (parsedRuntimeFlavor == RuntimeFlavorEnum.CoreCLR) ?
string monodroidSource = IsCoreCLR ?
"monodroid-coreclr.c" : (IsLibraryMode) ? "monodroid-librarymode.c" : "monodroid.c";

string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
Expand Down
7 changes: 7 additions & 0 deletions src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,13 @@ mono_droid_runtime_init (const char* executable)
{
LOG_INFO ("mono_droid_runtime_init (CoreCLR) called with executable: %s", executable);

// 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 to include 'diagnostics_tracing' component
#ifdef DIAGNOSTIC_PORTS
setenv ("DOTNET_DiagnosticPorts", DIAGNOSTIC_PORTS, true);
#endif
Copy link
Member

Choose a reason for hiding this comment

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

Do we need the same for AppleAppBuilder?

Copy link
Member Author

@lateralusX lateralusX Feb 7, 2025

Choose a reason for hiding this comment

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

You mean for NAOT on iOS? Not sure if that has been enabled yet. But once we do, then we could add this for iOS inline with what we do on Mono.

Copy link
Member

Choose a reason for hiding this comment

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

(NativeAOT for iOS shipped since .NET 8; CoreCLR for iOS Simulator landed on main last month)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes I know, but what I don't know if NATO + iOS also includes EventPipe support, do you know?

Copy link
Member Author

@lateralusX lateralusX Feb 7, 2025

Choose a reason for hiding this comment

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

For the CoreCLR for iOS Simulator I believe we should do similar work to make sure EventPipe is build using right flags + include similar support in AppleAppBuilder, but we could do that as a separate PR.

Copy link
Member

Choose a reason for hiding this comment

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

Yes I know, but what I don't know if NATO + iOS also includes EventPipe support, do you know?

Yes, it does, in theory...although I am not sure if it ever worked or if it was tested. The GC heap events were not wired so I never bothered to use it.


if (bundle_executable_path(executable, g_bundle_path, &g_executable_path) < 0)
{
LOG_ERROR("Failed to resolve full path for: %s", executable);
Expand Down
Loading