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

[android] Make Android app on coreclr use host-runtime contract and provide external assembly probe #112938

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
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
13 changes: 10 additions & 3 deletions src/mono/msbuild/android/build/AndroidBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,17 @@
<AndroidBundleDir Condition="'$(AndroidBundleDir)' == ''">$([MSBuild]::NormalizeDirectory('$(OutDir)', 'Bundle'))</AndroidBundleDir>

<BundleDir>$(AndroidBundleDir)</BundleDir>
<RuntimeHeaders>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))</RuntimeHeaders>
<RuntimeHeaders Condition="'$(UseMonoRuntime)' == 'false' and '$(UseNativeAOTRuntime)' != 'true'">$(CoreClrProjectRoot)hosts\inc</RuntimeHeaders>
</PropertyGroup>

<ItemGroup>
<RuntimeHeaders Include="$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))"
Condition="'$(UseMonoRuntime)' == 'true' and '$(UseNativeAOTRuntime)' != 'true'"/>
<RuntimeHeaders Include="$(CoreClrProjectRoot)hosts\inc"
Condition="'$(UseMonoRuntime)' == 'false' and '$(UseNativeAOTRuntime)' != 'true'" />
<RuntimeHeaders Include="$(SharedNativeRoot)"
Condition="'$(UseMonoRuntime)' == 'false' and '$(UseNativeAOTRuntime)' != 'true'" />
</ItemGroup>

<ItemGroup Condition="'$(UseMonoRuntime)' == 'true' and '$(UseNativeAOTRuntime)' != 'true'">
<RuntimeComponents Condition="'$(UseAllRuntimeComponents)' == 'true'" Include="@(_MonoRuntimeAvailableComponents)" />
<!-- Make sure marshal-ilgen is included in the components list. -->
Expand Down Expand Up @@ -246,7 +253,7 @@
ForceInterpreter="$(MonoForceInterpreter)"
IsLibraryMode="$(_IsLibraryMode)"
MainLibraryFileName="$(MainLibraryFileName)"
MonoRuntimeHeaders="$(RuntimeHeaders)"
RuntimeHeaders="@(RuntimeHeaders)"
NativeDependencies="@(_NativeDependencies)"
OutputDir="$(AndroidBundleDir)"
ProjectName="$(AppName)"
Expand Down
10 changes: 7 additions & 3 deletions src/mono/msbuild/apple/build/AppleBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,15 @@
<AppleBundleDir Condition="'$(AppleBundleDir)' == ''">$([MSBuild]::NormalizeDirectory('$(OutDir)', 'Bundle'))</AppleBundleDir>

<BundleDir>$(AppleBundleDir)</BundleDir>
<RuntimeHeaders Condition="'$(UseMonoRuntime)' != 'false' and '$(UseNativeAOTRuntime)' != 'true'">$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))</RuntimeHeaders>
<_AotModuleTablePath>$(AppleBundleDir)\modules.m</_AotModuleTablePath>
<AppName Condition="'$(AppName)' == ''">$(AssemblyName)</AppName>
</PropertyGroup>

<ItemGroup>
<RuntimeHeaders Include="$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))"
Condition="'$(UseMonoRuntime)' != 'false' and '$(UseNativeAOTRuntime)' != 'true'" />
</ItemGroup>

<ItemGroup Condition="'$(AppleAppBuilderRuntime)' == 'MonoVM'">
<RuntimeComponents Condition="'$(UseAllRuntimeComponents)' == 'true'" Include="@(_MonoRuntimeAvailableComponents)"/>
<!-- Make sure marshal-ilgen is included in the components list. -->
Expand Down Expand Up @@ -298,7 +302,7 @@
<LinkerArg Remove="@(_LinkerFlagsToDrop)" />
<ExtraAppLinkerArgs Include="@(LinkerArg)" />
</ItemGroup>

<PropertyGroup>
<AppleAppBuilderRuntime Condition="'$(AppleAppBuilderRuntime)' == '' and '$(UseNativeAOTRuntime)' == 'true'">NativeAOT</AppleAppBuilderRuntime>
<AppleAppBuilderRuntime Condition="'$(AppleAppBuilderRuntime)' == '' and '$(UseMonoRuntime)' == 'false'">CoreCLR</AppleAppBuilderRuntime>
Expand All @@ -324,7 +328,7 @@
InvariantGlobalization="$(InvariantGlobalization)"
IsLibraryMode="$(_IsLibraryMode)"
MainLibraryFileName="$(MainLibraryFileName)"
MonoRuntimeHeaders="$(RuntimeHeaders)"
MonoRuntimeHeaders="@(RuntimeHeaders)"
NativeMainSource="$(NativeMainSource)"
NativeDependencies="@(NativeDependencies)"
Optimized="$(Optimized)"
Expand Down
4 changes: 2 additions & 2 deletions src/mono/msbuild/common/LibraryBuilder.targets
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project>
<UsingTask TaskName="EmitBundleSourceFiles"
AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
<UsingTask TaskName="LibraryBuilderTask"
<UsingTask TaskName="LibraryBuilderTask"
AssemblyFile="$(LibraryBuilderTasksAssemblyPath)" />

<Target Name="_BuildNativeLibrary"
Expand Down Expand Up @@ -33,7 +33,7 @@
ExtraLinkerArguments="@(_ExtraLinkerArgs)"
ExtraSources="@(_ExtraLibrarySources)"
IsSharedLibrary="$(_IsSharedLibrary)"
MonoRuntimeHeaders="$(RuntimeHeaders)"
MonoRuntimeHeaders="@(RuntimeHeaders)"
Name="$(AssemblyName)"
OutputDirectory="$(BundleDir)"
RuntimeIdentifier="$(RuntimeIdentifier)"
Expand Down
1 change: 1 addition & 0 deletions src/mono/sample/Android/AndroidSampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

<ItemGroup>
<RuntimeComponents Condition="'$(RuntimeFlavor)' == 'Mono' and '$(DiagnosticPorts)' != ''" Include="diagnostics_tracing" />
<RuntimeHeaders Include="$(SharedNativeRoot)" Condition="'$(RuntimeFlavor)' != 'Mono'"/>
</ItemGroup>

<Import Project="$(MonoProjectRoot)\msbuild\android\build\AndroidBuild.props" />
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
public class AndroidAppBuilderTask : Task
{
[Required]
public string MonoRuntimeHeaders { get; set; } = ""!;
public string[] RuntimeHeaders { get; set; } = Array.Empty<string>()!;

/// <summary>
/// Target directory with *dll and other content to be AOT'd and/or bundled
Expand Down Expand Up @@ -141,7 +141,7 @@ public override bool Execute()
apkBuilder.NativeDependencies = NativeDependencies;
apkBuilder.ExtraLinkerArguments = ExtraLinkerArguments;
apkBuilder.RuntimeFlavor = RuntimeFlavor;
(ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(RuntimeIdentifier, MainLibraryFileName, MonoRuntimeHeaders);
(ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(RuntimeIdentifier, MainLibraryFileName, RuntimeHeaders);

return true;
}
Expand Down
5 changes: 3 additions & 2 deletions src/tasks/AndroidAppBuilder/ApkBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public ApkBuilder(TaskLoggingHelper logger)
public (string apk, string packageId) BuildApk(
string runtimeIdentifier,
string mainLibraryFileName,
string runtimeHeaders)
string[] runtimeHeaders)
{
if (!Enum.TryParse(RuntimeFlavor, true, out parsedRuntimeFlavor))
{
Expand Down Expand Up @@ -324,9 +324,10 @@ public ApkBuilder(TaskLoggingHelper logger)
string aotSources = assemblerFiles.ToString();
string monodroidSource = IsCoreCLR ?
"monodroid-coreclr.c" : (IsLibraryMode) ? "monodroid-librarymode.c" : "monodroid.c";
string runtimeInclude = string.Join(" ", runtimeHeaders.Select(h => $"\"{NormalizePathToUnix(h)}\""));

string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
.Replace("%RuntimeInclude%", NormalizePathToUnix(runtimeHeaders))
.Replace("%RuntimeInclude%", runtimeInclude)
.Replace("%NativeLibrariesToLink%", NormalizePathToUnix(nativeLibraries))
.Replace("%MONODROID_SOURCE%", monodroidSource)
.Replace("%AotSources%", NormalizePathToUnix(aotSources))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ add_library(

%Defines%

include_directories("%RuntimeInclude%")
include_directories(%RuntimeInclude%)

target_link_libraries(
monodroid
Expand Down
100 changes: 83 additions & 17 deletions src/tasks/AndroidAppBuilder/Templates/monodroid-coreclr.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
#include <coreclrhost.h>
#include <dirent.h>

#include <corehost/host_runtime_contract.h>

/********* exported symbols *********/

/* JNI exports */
Expand All @@ -34,11 +36,15 @@ Java_net_dot_MonoRunner_freeNativeResources (JNIEnv* env, jobject thiz);

/********* implementation *********/

static const char* g_bundle_path = NULL;
static char* g_bundle_path = NULL;
static const char* g_executable_path = NULL;
static unsigned int g_coreclr_domainId = 0;
static void* g_coreclr_handle = NULL;

#define MAX_MAPPED_COUNT 50 // Arbitrarily 'large enough' number
static void* g_mapped_files[MAX_MAPPED_COUNT];
static size_t g_mapped_file_sizes[MAX_MAPPED_COUNT];
static unsigned int g_mapped_files_count = 0;

#define LOG_INFO(fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, "DOTNET", fmt, ##__VA_ARGS__)
#define LOG_ERROR(fmt, ...) __android_log_print(ANDROID_LOG_ERROR, "DOTNET", fmt, ##__VA_ARGS__)
Expand Down Expand Up @@ -70,7 +76,7 @@ strncpy_str (JNIEnv *env, char *buff, jstring str, int nbuff)

/*
* Get the list of trusted assemblies from a specified @dir_path.
* The path is searched for .dll files which when found are concatenated
* The path is searched for .dll files which when found are concatenated
* to the output string @tpas separated by ':'.
* The output string should be freed by the caller.
* The return value is the length of the output string.
Expand Down Expand Up @@ -147,6 +153,56 @@ bundle_executable_path (const char* executable, const char* bundle_path, const c
return executable_path_len;
}

static bool
external_assembly_probe(const char* name, void** data, int64_t* size)
{
if (g_mapped_files_count >= MAX_MAPPED_COUNT)
{
LOG_ERROR("Too many mapped files, cannot map %s", name);
return false;
}

// Get just the file name
const char* pos = strrchr(name, '/');
if (pos != NULL)
name = pos + 1;

// Look in the bundle path where the files were extracted
char full_path[1024];
size_t path_len = strlen(g_bundle_path) + strlen(name) + 1; // +1 for '/'
size_t res = snprintf(full_path, path_len + 1, "%s/%s", g_bundle_path, name);
if (res < 0 || res != path_len)
return false;

int fd = open(full_path, O_RDONLY);
if (fd == -1)
return false;

struct stat buf;
if (fstat(fd, &buf) == -1)
{
close(fd);
return false;
}

int64_t size_local = buf.st_size;
void* mapped = mmap(NULL, size_local, PROT_READ, MAP_PRIVATE, fd, 0);
if (mapped == MAP_FAILED)
{
close(fd);
return false;
}

LOG_INFO("Mapped %s -> %s", name, full_path);
g_mapped_files[g_mapped_files_count] = mapped;
g_mapped_file_sizes[g_mapped_files_count] = size_local;
g_mapped_files_count++;
close(fd);
*data = mapped;
*size = size_local;
return true;
}

static void
free_resources ()
{
Expand All @@ -166,9 +222,13 @@ free_resources ()
coreclr_shutdown (g_coreclr_handle, g_coreclr_domainId);
g_coreclr_handle = NULL;
}
for (int i = 0; i < g_mapped_files_count; ++i)
{
munmap (g_mapped_files[i], g_mapped_file_sizes[i]);
}
}

static int
static int
mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle, unsigned int coreclr_domainId, int managed_argc, const char** managed_argv)
{
unsigned int rv;
Expand All @@ -178,6 +238,8 @@ mono_droid_execute_assembly (const char* executable_path, void* coreclr_handle,
return rv;
}

#define PROPERTY_COUNT 3

static int
mono_droid_runtime_init (const char* executable)
{
Expand All @@ -198,34 +260,38 @@ mono_droid_runtime_init (const char* executable)

chdir (g_bundle_path);

// TODO: set TRUSTED_PLATFORM_ASSEMBLIES, APP_PATHS and NATIVE_DLL_SEARCH_DIRECTORIES
struct host_runtime_contract host_contract = {
sizeof(struct host_runtime_contract),
NULL, // context
NULL, // get_runtime_property
NULL, // bundle_proble
NULL, // pinvoke_override
&external_assembly_probe };

const char* appctx_keys[3];
const char* appctx_keys[PROPERTY_COUNT];
appctx_keys[0] = "RUNTIME_IDENTIFIER";
appctx_keys[1] = "APP_CONTEXT_BASE_DIRECTORY";
appctx_keys[2] = "TRUSTED_PLATFORM_ASSEMBLIES";
appctx_keys[2] = "HOST_RUNTIME_CONTRACT";

const char* appctx_values[3];
const char* appctx_values[PROPERTY_COUNT];
appctx_values[0] = ANDROID_RUNTIME_IDENTIFIER;
appctx_values[1] = g_bundle_path;
size_t tpas_len = get_tpas_from_path(g_bundle_path, &appctx_values[2]);
if (tpas_len < 1)
{
LOG_ERROR("Failed to get trusted assemblies from path: %s", g_bundle_path);
return -1;
}

char contract_str[19]; // 0x + 16 hex digits + '\0'
snprintf(contract_str, 19, "0x%zx", (size_t)(&host_contract));
appctx_values[2] = contract_str;

LOG_INFO ("Calling coreclr_initialize");
int rv = coreclr_initialize (
g_executable_path,
executable,
3,
PROPERTY_COUNT,
appctx_keys,
appctx_values,
&g_coreclr_handle,
&g_coreclr_domainId
);
LOG_INFO ("coreclr_initialize returned %d", rv);
LOG_INFO ("coreclr_initialize returned 0x%x", rv);
return rv;
}

Expand All @@ -237,7 +303,7 @@ Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstrin

const char *key = (*env)->GetStringUTFChars(env, j_key, 0);
const char *val = (*env)->GetStringUTFChars(env, j_value, 0);

LOG_INFO ("Setting env: %s=%s", key, val);
setenv (key, val, true);
(*env)->ReleaseStringUTFChars(env, j_key, key);
Expand Down Expand Up @@ -270,7 +336,7 @@ int
Java_net_dot_MonoRunner_execEntryPoint (JNIEnv* env, jobject thiz, jstring j_entryPointLibName, jobjectArray j_args)
{
LOG_INFO("Java_net_dot_MonoRunner_execEntryPoint (CoreCLR):");

if ((g_bundle_path == NULL) || (g_executable_path == NULL))
{
LOG_ERROR("Bundle path or executable path not set");
Expand Down
6 changes: 3 additions & 3 deletions src/tasks/AppleAppBuilder/AppleAppBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public string TargetOS
/// <summary>
/// Path to Mono public headers (*.h)
/// </summary>
public string MonoRuntimeHeaders { get; set; } = ""!;
public string[] MonoRuntimeHeaders { get; set; } = Array.Empty<string>();

/// <summary>
/// This library will be used as an entry point (e.g. TestRunner.dll). Can
Expand Down Expand Up @@ -201,7 +201,7 @@ public void ValidateRuntimeSelection()

if (targetRuntime == TargetRuntime.NativeAOT || targetRuntime == TargetRuntime.CoreCLR)
{
if (!string.IsNullOrEmpty(MonoRuntimeHeaders))
if (MonoRuntimeHeaders.Length != 0)
throw new ArgumentException($"Property \"{nameof(MonoRuntimeHeaders)}\" is not supported with {Runtime} runtime and will be ignored.");

if (!string.IsNullOrEmpty(MainLibraryFileName) && targetRuntime == TargetRuntime.NativeAOT)
Expand All @@ -224,7 +224,7 @@ public void ValidateRuntimeSelection()
}
else
{
if (string.IsNullOrEmpty(MonoRuntimeHeaders))
if (MonoRuntimeHeaders.Length == 0)
throw new ArgumentException($"The \"{nameof(AppleAppBuilderTask)}\" task was not given a value for the required parameter \"{nameof(MonoRuntimeHeaders)}\" when using Mono runtime.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ add_executable(
%Defines%

if(NOT %UseNativeAOTRuntime%)
include_directories("%MonoInclude%")
include_directories(%MonoInclude%)
endif()

set_target_properties(%ProjectName% PROPERTIES
Expand Down
4 changes: 2 additions & 2 deletions src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ endif()

%Defines%

if(NOT "%MonoInclude%" STREQUAL "")
include_directories("%MonoInclude%")
if(%HasMonoIncludes%)
include_directories(%MonoInclude%)
endif()

set_target_properties(%ProjectName% %AotTargetsList% PROPERTIES
Expand Down
7 changes: 4 additions & 3 deletions src/tasks/AppleAppBuilder/Xcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public string GenerateXCode(
IEnumerable<string> excludes,
string workspace,
string binDir,
string monoInclude,
string[] monoInclude,
bool preferDylibs,
bool useConsoleUiTemplate,
bool forceAOT,
Expand Down Expand Up @@ -250,7 +250,7 @@ public string GenerateCMake(
IEnumerable<string> excludes,
string workspace,
string binDir,
string monoInclude,
string[] monoInclude,
bool preferDylibs,
bool useConsoleUiTemplate,
bool forceAOT,
Expand Down Expand Up @@ -347,7 +347,8 @@ public string GenerateCMake(
.Replace("%ProjectName%", projectName)
.Replace("%AppResources%", appResources)
.Replace("%MainSource%", nativeMainSource)
.Replace("%MonoInclude%", monoInclude)
.Replace("%HasMonoIncludes%", monoInclude.Length > 0 ? "TRUE" : "FALSE")
.Replace("%MonoInclude%", string.Join(" ", monoInclude.Select(h => $"\"{h}\"")))
.Replace("%HardenedRuntime%", hardenedRuntime ? "TRUE" : "FALSE");

string toLink = "";
Expand Down
Loading
Loading