mirror of https://github.com/dotnet/runtime
Merge 407b4db0ee
into 02596ba8d9
This commit is contained in:
commit
fd886269ae
|
@ -993,6 +993,48 @@ extends:
|
|||
eq(variables['coreclrContainsChange'], true),
|
||||
eq(variables['isRollingBuild'], true))
|
||||
|
||||
#
|
||||
# Android arm64 devices and x64 emulators
|
||||
# Build the whole product using CoreCLR and run functional tests
|
||||
#
|
||||
- template: /eng/pipelines/common/platform-matrix.yml
|
||||
parameters:
|
||||
jobTemplate: /eng/pipelines/common/global-build-job.yml
|
||||
helixQueuesTemplate: /eng/pipelines/libraries/helix-queues-setup.yml
|
||||
buildConfig: Release
|
||||
runtimeFlavor: nativeaot
|
||||
platforms:
|
||||
- android_x64
|
||||
- android_arm64
|
||||
variables:
|
||||
# map dependencies variables to local variables
|
||||
- name: librariesContainsChange
|
||||
value: $[ stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'] ]
|
||||
- name: coreclrContainsChange
|
||||
value: $[ stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'] ]
|
||||
jobParameters:
|
||||
testGroup: innerloop
|
||||
nameSuffix: NativeAOT
|
||||
buildArgs: -s clr.aot+libs+libs.tests -c $(_BuildConfig) /p:ArchiveTests=true /p:RunSmokeTestsOnly=true /p:UseNativeAOTRuntime=true /p:RuntimeFlavor=nativeaot /p:TestNativeAOT=true
|
||||
timeoutInMinutes: 120
|
||||
condition: >-
|
||||
or(
|
||||
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_libraries.containsChange'], true),
|
||||
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_coreclr.containsChange'], true),
|
||||
eq(stageDependencies.EvaluatePaths.evaluate_paths.outputs['SetPathVars_installer.containsChange'], true),
|
||||
eq(variables['isRollingBuild'], true))
|
||||
# extra steps, run tests
|
||||
postBuildSteps:
|
||||
- template: /eng/pipelines/libraries/helix.yml
|
||||
parameters:
|
||||
creator: dotnet-bot
|
||||
testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig)
|
||||
condition: >-
|
||||
or(
|
||||
eq(variables['librariesContainsChange'], true),
|
||||
eq(variables['coreclrContainsChange'], true),
|
||||
eq(variables['isRollingBuild'], true))
|
||||
|
||||
#
|
||||
# iOS/tvOS devices - Full AOT + AggressiveTrimming to reduce size
|
||||
# Build the whole product using Mono and run libraries tests
|
||||
|
|
|
@ -66,14 +66,14 @@
|
|||
RuntimeFrameworkName="$(LocalFrameworkOverrideName)"
|
||||
LatestRuntimeFrameworkVersion="$(ProductVersion)"
|
||||
RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.NativeAOT.**RID**"
|
||||
RuntimePackRuntimeIdentifiers="ios-arm64;iossimulator-arm64;iossimulator-x64;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;maccatalyst-arm64;maccatalyst-x64;linux-bionic-arm64;linux-bionic-x64;osx-arm64;osx-x64"
|
||||
RuntimePackRuntimeIdentifiers="ios-arm64;iossimulator-arm64;iossimulator-x64;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;maccatalyst-arm64;maccatalyst-x64;linux-bionic-arm64;linux-bionic-x64;android-x64;android-arm64;osx-arm64;osx-x64"
|
||||
RuntimePackLabels="NativeAOT"
|
||||
Condition="'$(UseLocalTargetingRuntimePack)' == 'true' and ('@(KnownRuntimePack)' == '' or @(KnownRuntimePack->WithMetadataValue('Identity', 'Microsoft.NETCore.App')->WithMetadataValue('RuntimePackLabels', 'NativeAOT')->WithMetadataValue('TargetFramework', '$(NetCoreAppCurrent)')) == '')" />
|
||||
<KnownILCompilerPack Include="Microsoft.DotNet.ILCompiler"
|
||||
ILCompilerPackNamePattern="runtime.**RID**.Microsoft.DotNet.ILCompiler"
|
||||
TargetFramework="$(NetCoreAppCurrent)"
|
||||
ILCompilerPackVersion="$(ProductVersion)"
|
||||
ILCompilerRuntimeIdentifiers="linux-musl-x64;linux-x64;win-x64;linux-arm;linux-arm64;linux-musl-arm;linux-musl-arm64;osx-arm64;osx-x64;win-arm64;win-x86;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64"
|
||||
ILCompilerRuntimeIdentifiers="linux-musl-x64;linux-x64;win-x64;linux-arm;linux-arm64;linux-musl-arm;linux-musl-arm64;osx-arm64;osx-x64;win-arm64;win-x86;linux-riscv64;linux-musl-riscv64;linux-loongarch64;linux-musl-loongarch64;android-x64;linux-bionic-x64;android-arm64;linux-bionic-arm64"
|
||||
Condition="'$(UseLocalILCompilerPack)' == 'true' and '@(KnownILCompilerPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))' != 'true'" />
|
||||
<KnownCrossgen2Pack Include="$(LocalFrameworkOverrideName).Crossgen2"
|
||||
TargetFramework="$(NetCoreAppCurrent)"
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
<MainLibraryFileName Condition="'$(MainLibraryFileName)' == ''">AndroidTestRunner.dll</MainLibraryFileName>
|
||||
|
||||
<AndroidBuildDir>$(PublishDir)</AndroidBuildDir>
|
||||
<AndroidBundleDir>$(BundleDir)</AndroidBundleDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<Project>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputType Condition="'$(TargetOS)' != 'android'">Exe</OutputType>
|
||||
|
||||
<BundleDir>$([MSBuild]::NormalizeDirectory('$(OutDir)', 'publish'))</BundleDir>
|
||||
<RunScriptOutputPath>$([MSBuild]::NormalizePath('$(BundleDir)', '$(RunScriptOutputName)'))</RunScriptOutputPath>
|
||||
|
@ -49,7 +49,8 @@
|
|||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(CommonTestPath)SingleFileTestRunner\SingleFileTestRunner.cs"
|
||||
Link="Common\SingleFileTestRunner\SingleFileTestRunner.cs" />
|
||||
Link="Common\SingleFileTestRunner\SingleFileTestRunner.cs"
|
||||
Condition="'$(IsFunctionalTest)' != 'true'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
<_targetOS>$(_originalTargetOS)</_targetOS>
|
||||
<_linuxToken>linux-</_linuxToken>
|
||||
<_linuxLibcFlavor Condition="$(_targetOS.StartsWith($(_linuxToken)))">$(_targetOS.SubString($(_linuxToken.Length)))</_linuxLibcFlavor>
|
||||
<_linuxLibcFlavor Condition="'$(_targetOS)' == 'android'">bionic</_linuxLibcFlavor>
|
||||
<_targetOS Condition="$(_targetOS.StartsWith($(_linuxToken)))">linux</_targetOS>
|
||||
|
||||
<!-- linux-bionic on ARM uses armel (softfp) ABI -->
|
||||
|
|
|
@ -47,7 +47,7 @@ The .NET Foundation licenses this file to you under the MIT license.
|
|||
<CrossCompileArch Condition="$(CrossCompileRid.EndsWith('-arm'))">armv7</CrossCompileArch>
|
||||
|
||||
<CrossCompileAbi>gnu</CrossCompileAbi>
|
||||
<CrossCompileAbi Condition="$(CrossCompileRid.StartsWith('linux-bionic-'))">android21</CrossCompileAbi>
|
||||
<CrossCompileAbi Condition="$(CrossCompileRid.StartsWith('linux-bionic-')) or $(CrossCompileRid.StartsWith('android'))">android21</CrossCompileAbi>
|
||||
<CrossCompileAbi Condition="$(CrossCompileRid.StartsWith('linux-musl-')) or $(CrossCompileRid.StartsWith('alpine-'))">musl</CrossCompileAbi>
|
||||
<CrossCompileAbi Condition="'$(CrossCompileRid)' == 'linux-arm'">gnueabihf</CrossCompileAbi>
|
||||
<CrossCompileAbi Condition="'$(CrossCompileRid)' == 'linux-bionic-arm'">androideabi21</CrossCompileAbi>
|
||||
|
|
|
@ -574,7 +574,7 @@
|
|||
<ProjectReference Include="$(MSBuildThisFileDirectory)System.Runtime\tests\System.Globalization.Tests\System.Globalization.Tests.csproj" Condition="'$(OS)' != 'Windows_NT'" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TestNativeAot)' == 'true'">
|
||||
<ItemGroup Condition="'$(TestNativeAot)' == 'true' and '$(TargetOS)' != 'android'">
|
||||
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Collections\tests\System.Collections.Tests.csproj" />
|
||||
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.IO.Compression\tests\System.IO.Compression.Tests.csproj" />
|
||||
<SmokeTestProject Include="$(MSBuildThisFileDirectory)System.Linq.Expressions\tests\System.Linq.Expressions.Tests.csproj" />
|
||||
|
@ -607,6 +607,10 @@
|
|||
<SmokeTestProject Include="$(RepoRoot)\src\tests\FunctionalTests\Android\Device_Emulator\JIT\*.Test.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetOS)' == 'android' and '$(RuntimeFlavor)' == 'NativeAOT'">
|
||||
<SmokeTestProject Include="$(RepoRoot)src\tests\FunctionalTests\Android\Device_Emulator\NativeAOT\*.Test.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="('$(TargetOS)' == 'iossimulator' or '$(TargetOS)' == 'tvossimulator') and '$(RuntimeFlavor)' == 'CoreCLR'">
|
||||
<SmokeTestProject Remove="@(SmokeTestProject)" />
|
||||
<SmokeTestProject Include="$(RepoRoot)\src\tests\FunctionalTests\iOS\Simulator\CoreCLR.Interpreter\*.Test.csproj"/>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<RuntimeIdentifier>$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())</RuntimeIdentifier>
|
||||
<!-- TODO: Revisit this.
|
||||
We need to check for RuntimeFlavor setting as for runtime tests we always import CoreCLR props which force UseMonoRuntime=false (see: https://github.com/dotnet/runtime/issues/111919) -->
|
||||
<UseMonoRuntime Condition="'$(RuntimeFlavor)' == 'coreclr'">false</UseMonoRuntime>
|
||||
<UseMonoRuntime Condition="'$(RuntimeFlavor)' == 'coreclr' or '$(RuntimeFlavor)' == 'nativeaot'">false</UseMonoRuntime>
|
||||
<UseMonoRuntime Condition="'$(UseMonoRuntime)' == '' or '$(RuntimeFlavor)' == 'mono'">true</UseMonoRuntime>
|
||||
<UseMonoJustInterp Condition="'$(UseMonoRuntime)' == 'true' and '$(RunAOTCompilation)' == 'true' and '$(MonoForceInterpreter)' == 'true'">true</UseMonoJustInterp>
|
||||
|
||||
|
@ -14,8 +14,15 @@
|
|||
<_IsLibraryMode Condition="'$(UseMonoRuntime)' == 'true' and '$(UseNativeAOTRuntime)' != 'true' and '$(NativeLib)' != ''">true</_IsLibraryMode>
|
||||
<_ReadRuntimeComponentsManifestTargetName Condition="'$(UseMonoRuntime)' == 'true' and '$(UseNativeAOTRuntime)' != 'true'">_MonoReadAvailableComponentsManifest</_ReadRuntimeComponentsManifestTargetName>
|
||||
|
||||
<StaticLinkedRuntime Condition="'$(RuntimeFlavor)' == 'nativeaot'">false</StaticLinkedRuntime>
|
||||
<StaticLinkedRuntime Condition="'$(RuntimeFlavor)' == 'coreclr' and '$(StaticLinkedRuntime)' == ''">false</StaticLinkedRuntime>
|
||||
|
||||
<!-- Android NDK uses x86_64 as the architecture for naming, even on MacOS arm64 -->
|
||||
<NdkToolchainPrebuiltOS Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux-x86_64</NdkToolchainPrebuiltOS>
|
||||
<NdkToolchainPrebuiltOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">darwin-x86_64</NdkToolchainPrebuiltOS>
|
||||
<NdkToolchainPrebuiltOS Condition="'$(HostOS)' == 'windows'">windows-x86_64</NdkToolchainPrebuiltOS>
|
||||
<CppCompilerAndLinker>$(ANDROID_NDK_ROOT)\toolchains\llvm\prebuilt\$(NdkToolchainPrebuiltOS)\bin\clang</CppCompilerAndLinker>
|
||||
|
||||
<AndroidBuildAfterThisTarget Condition="'$(AndroidBuildAfterThisTarget)' == ''">Publish</AndroidBuildAfterThisTarget>
|
||||
<AndroidBuildDependsOn Condition="'$(UseMonoRuntime)' == 'true'">
|
||||
$(_ReadRuntimeComponentsManifestTargetName);
|
||||
|
@ -35,6 +42,11 @@
|
|||
_AndroidGenerateAppBundle;
|
||||
_AfterAndroidBuild
|
||||
</AndroidBuildDependsOn>
|
||||
<AndroidBuildDependsOn Condition="'$(UseNativeAOTRuntime)' == 'true'">
|
||||
$(AndroidBuildDependsOn);
|
||||
CopyNativeBinary;
|
||||
_CopyAotSymbols
|
||||
</AndroidBuildDependsOn>
|
||||
|
||||
<!-- When building on Helix $(_CommonTargetsDir) will be properly set, otherwise we have to set it to a in-tree location -->
|
||||
<_CommonTargetsDir Condition="'$(_CommonTargetsDir)' == ''">$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), '..', '..', 'common'))</_CommonTargetsDir>
|
||||
|
|
|
@ -239,6 +239,7 @@
|
|||
We are using a private property to determine the target runtime, we should instead unify the resolution with Apple targets instead, (see: https://github.com/dotnet/runtime/issues/111923) -->
|
||||
<_RuntimeFlavor>Mono</_RuntimeFlavor>
|
||||
<_RuntimeFlavor Condition="'$(UseMonoRuntime)' == 'false' and '$(UseNativeAOTRuntime)' != 'true'">CoreCLR</_RuntimeFlavor>
|
||||
<_RuntimeFlavor Condition="'$(UseNativeAOTRuntime)' == 'true'">nativeaot</_RuntimeFlavor>
|
||||
</PropertyGroup>
|
||||
|
||||
<AndroidAppBuilderTask
|
||||
|
@ -290,4 +291,5 @@
|
|||
RuntimeConfigReservedProperties="@(_RuntimeConfigReservedProperties)">
|
||||
</RuntimeConfigParserTask>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -16,7 +16,8 @@ using Microsoft.Build.Utilities;
|
|||
public enum RuntimeFlavorEnum
|
||||
{
|
||||
Mono,
|
||||
CoreCLR
|
||||
CoreCLR,
|
||||
NativeAOT
|
||||
}
|
||||
|
||||
public partial class ApkBuilder
|
||||
|
@ -53,6 +54,7 @@ public partial class ApkBuilder
|
|||
private RuntimeFlavorEnum parsedRuntimeFlavor;
|
||||
private bool IsMono => parsedRuntimeFlavor == RuntimeFlavorEnum.Mono;
|
||||
private bool IsCoreCLR => parsedRuntimeFlavor == RuntimeFlavorEnum.CoreCLR;
|
||||
private bool IsNativeAOT => parsedRuntimeFlavor == RuntimeFlavorEnum.NativeAOT;
|
||||
|
||||
private TaskLoggingHelper logger;
|
||||
|
||||
|
@ -91,7 +93,8 @@ public partial class ApkBuilder
|
|||
throw new ArgumentException($"ProjectName='{ProjectName}' should not not contain spaces.");
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(AndroidSdk)){
|
||||
if (string.IsNullOrEmpty(AndroidSdk))
|
||||
{
|
||||
AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT");
|
||||
}
|
||||
|
||||
|
@ -154,7 +157,7 @@ public partial class ApkBuilder
|
|||
var assemblerFilesToLink = new StringBuilder();
|
||||
var aotLibraryFiles = new List<string>();
|
||||
|
||||
if (!IsLibraryMode)
|
||||
if (!(IsLibraryMode || IsNativeAOT))
|
||||
{
|
||||
foreach (ITaskItem file in Assemblies)
|
||||
{
|
||||
|
@ -244,7 +247,7 @@ public partial class ApkBuilder
|
|||
{
|
||||
nativeLibraries = string.Join("\n ", NativeDependencies.Select(dep => dep));
|
||||
}
|
||||
else
|
||||
else if (!IsNativeAOT)
|
||||
{
|
||||
string runtimeLib = "";
|
||||
if (StaticLinkedRuntime && IsMono)
|
||||
|
@ -325,79 +328,85 @@ public partial class ApkBuilder
|
|||
nativeLibraries += $" libc++_static.a{Environment.NewLine}";
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder extraLinkerArgs = new StringBuilder();
|
||||
foreach (ITaskItem item in ExtraLinkerArguments)
|
||||
string abi;
|
||||
if (IsNativeAOT)
|
||||
{
|
||||
extraLinkerArgs.AppendLine($" \"{item.ItemSpec}\"");
|
||||
abi = AndroidProject.DetermineAbi(runtimeIdentifier);
|
||||
}
|
||||
|
||||
if (StaticLinkedRuntime && IsCoreCLR)
|
||||
else
|
||||
{
|
||||
// Ensure global symbol references in the shared library are resolved to definitions in
|
||||
// the same shared library. For the static linked runtime specifically, we need this for
|
||||
// global functions in assembly for the linker to treat relative offsets to them as constant
|
||||
extraLinkerArgs.AppendLine($" \"-Wl,-Bsymbolic\"");
|
||||
}
|
||||
|
||||
nativeLibraries += assemblerFilesToLink.ToString();
|
||||
|
||||
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%", runtimeInclude)
|
||||
.Replace("%NativeLibrariesToLink%", NormalizePathToUnix(nativeLibraries))
|
||||
.Replace("%MONODROID_SOURCE%", monodroidSource)
|
||||
.Replace("%AotSources%", NormalizePathToUnix(aotSources))
|
||||
.Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c")
|
||||
.Replace("%APP_LINKER_ARGS%", extraLinkerArgs.ToString());
|
||||
|
||||
var defines = new StringBuilder();
|
||||
if (ForceInterpreter)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFORCE_INTERPRETER=1)");
|
||||
}
|
||||
else if (ForceAOT)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFORCE_AOT=1)");
|
||||
if (aotLibraryFiles.Count == 0)
|
||||
StringBuilder extraLinkerArgs = new StringBuilder();
|
||||
foreach (ITaskItem item in ExtraLinkerArguments)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DSTATIC_AOT=1)");
|
||||
extraLinkerArgs.AppendLine($" \"{item.ItemSpec}\"");
|
||||
}
|
||||
|
||||
if (StaticLinkedRuntime && IsCoreCLR)
|
||||
{
|
||||
// Ensure global symbol references in the shared library are resolved to definitions in
|
||||
// the same shared library. For the static linked runtime specifically, we need this for
|
||||
// global functions in assembly for the linker to treat relative offsets to them as constant
|
||||
extraLinkerArgs.AppendLine($" \"-Wl,-Bsymbolic\"");
|
||||
}
|
||||
|
||||
nativeLibraries += assemblerFilesToLink.ToString();
|
||||
|
||||
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%", runtimeInclude)
|
||||
.Replace("%NativeLibrariesToLink%", NormalizePathToUnix(nativeLibraries))
|
||||
.Replace("%MONODROID_SOURCE%", monodroidSource)
|
||||
.Replace("%AotSources%", NormalizePathToUnix(aotSources))
|
||||
.Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c")
|
||||
.Replace("%APP_LINKER_ARGS%", extraLinkerArgs.ToString());
|
||||
|
||||
var defines = new StringBuilder();
|
||||
if (ForceInterpreter)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFORCE_INTERPRETER=1)");
|
||||
}
|
||||
else if (ForceAOT)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFORCE_AOT=1)");
|
||||
if (aotLibraryFiles.Count == 0)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DSTATIC_AOT=1)");
|
||||
}
|
||||
}
|
||||
|
||||
if (ForceFullAOT)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFULL_AOT=1)");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DiagnosticPorts))
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DDIAGNOSTIC_PORTS=\"" + DiagnosticPorts + "\")");
|
||||
}
|
||||
|
||||
cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString());
|
||||
|
||||
File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);
|
||||
|
||||
string monodroidContent = Utils.GetEmbeddedResource(monodroidSource);
|
||||
if (IsCoreCLR)
|
||||
{
|
||||
monodroidContent = RenderMonodroidCoreClrTemplate(monodroidContent);
|
||||
}
|
||||
File.WriteAllText(Path.Combine(OutputDir, monodroidSource), monodroidContent);
|
||||
|
||||
AndroidProject project = new AndroidProject("monodroid", runtimeIdentifier, AndroidNdk, logger);
|
||||
project.GenerateCMake(OutputDir, MinApiLevel, StripDebugSymbols);
|
||||
project.BuildCMake(OutputDir, StripDebugSymbols);
|
||||
abi = project.Abi;
|
||||
|
||||
// TODO: https://github.com/dotnet/runtime/issues/115717
|
||||
}
|
||||
|
||||
if (ForceFullAOT)
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DFULL_AOT=1)");
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(DiagnosticPorts))
|
||||
{
|
||||
defines.AppendLine("add_definitions(-DDIAGNOSTIC_PORTS=\"" + DiagnosticPorts + "\")");
|
||||
}
|
||||
|
||||
cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString());
|
||||
|
||||
File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);
|
||||
|
||||
string monodroidContent = Utils.GetEmbeddedResource(monodroidSource);
|
||||
if (IsCoreCLR)
|
||||
{
|
||||
monodroidContent = RenderMonodroidCoreClrTemplate(monodroidContent);
|
||||
}
|
||||
File.WriteAllText(Path.Combine(OutputDir, monodroidSource), monodroidContent);
|
||||
|
||||
AndroidProject project = new AndroidProject("monodroid", runtimeIdentifier, AndroidNdk, logger);
|
||||
project.GenerateCMake(OutputDir, MinApiLevel, StripDebugSymbols);
|
||||
project.BuildCMake(OutputDir, StripDebugSymbols);
|
||||
|
||||
// TODO: https://github.com/dotnet/runtime/issues/115717
|
||||
|
||||
string abi = project.Abi;
|
||||
|
||||
// 2. Compile Java files
|
||||
|
||||
string javaSrcFolder = Path.Combine(OutputDir, "src", "net", "dot");
|
||||
|
@ -430,11 +439,22 @@ public partial class ApkBuilder
|
|||
envVariables += $"\t\tsetEnv(\"{name}\", \"{value}\");\n";
|
||||
}
|
||||
|
||||
string jniLibraryName = (IsLibraryMode) ? ProjectName! :
|
||||
(StaticLinkedRuntime && IsCoreCLR) ? "monodroid" : "System.Security.Cryptography.Native.Android";
|
||||
string jniLibraryName;
|
||||
if (IsLibraryMode || IsNativeAOT)
|
||||
jniLibraryName = ProjectName!;
|
||||
else if (StaticLinkedRuntime && IsCoreCLR)
|
||||
jniLibraryName = "monodroid";
|
||||
else
|
||||
jniLibraryName = "System.Security.Cryptography.Native.Android";
|
||||
|
||||
List<string> librariesToLoad = [jniLibraryName];
|
||||
if (!IsNativeAOT)
|
||||
librariesToLoad.Add("monodroid");
|
||||
|
||||
string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java")
|
||||
.Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName))
|
||||
.Replace("%JNI_LIBRARY_NAME%", jniLibraryName)
|
||||
.Replace("%LoadLibraryStatements%",
|
||||
string.Join('\n', librariesToLoad.Select(l => $"System.loadLibrary(\"{l}\");")))
|
||||
.Replace("%EnvVariables%", envVariables);
|
||||
|
||||
File.WriteAllText(monoRunnerPath, monoRunner);
|
||||
|
@ -455,8 +475,13 @@ public partial class ApkBuilder
|
|||
|
||||
if (classFiles.Length == 0)
|
||||
throw new InvalidOperationException("Didn't find any .class files");
|
||||
List<string> inputFiles = [.. classFiles];
|
||||
if (IsNativeAOT)
|
||||
{
|
||||
inputFiles.Add(Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(AppDir)!)!, "libSystem.Security.Cryptography.Native.Android.jar"));
|
||||
}
|
||||
|
||||
Utils.RunProcess(logger, androidSdkHelper.D8Path, $"--no-desugaring {string.Join(" ", classFiles)}", workingDir: OutputDir);
|
||||
Utils.RunProcess(logger, androidSdkHelper.D8Path, $"--no-desugaring {string.Join(" ", inputFiles)}", workingDir: OutputDir);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -470,7 +495,8 @@ public partial class ApkBuilder
|
|||
Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar} {debugModeArg}", workingDir: OutputDir);
|
||||
|
||||
var dynamicLibs = new List<string>();
|
||||
dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so"));
|
||||
if (!IsNativeAOT)
|
||||
dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so"));
|
||||
|
||||
if (IsLibraryMode)
|
||||
{
|
||||
|
@ -533,7 +559,6 @@ public partial class ApkBuilder
|
|||
}
|
||||
|
||||
// NOTE: we can run android-strip tool from NDK to shrink native binaries here even more.
|
||||
|
||||
File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true);
|
||||
Utils.RunProcess(logger, androidSdkHelper.AaptPath, $"add {apkFile} {NormalizePathToUnix(destRelative)}", workingDir: OutputDir);
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ public class MonoRunner extends Instrumentation
|
|||
{
|
||||
static {
|
||||
// loadLibrary triggers JNI_OnLoad in these libs
|
||||
System.loadLibrary("%JNI_LIBRARY_NAME%");
|
||||
System.loadLibrary("monodroid");
|
||||
%LoadLibraryStatements%
|
||||
}
|
||||
|
||||
static String testResultsDir;
|
||||
|
|
|
@ -0,0 +1,422 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime;
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using JObject = nint;
|
||||
using JString = nint;
|
||||
using JObjectArray = nint;
|
||||
|
||||
namespace MonoDroid.NativeAOT;
|
||||
|
||||
#pragma warning disable IDE0060 // Remove unused parameter
|
||||
internal static unsafe partial class MonoDroidExports
|
||||
{
|
||||
// void Java_net_dot_MonoRunner_setEnv (JNIEnv* env, jobject thiz, jstring j_key, jstring j_value);
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) }, EntryPoint = "Java_net_dot_MonoRunner_setEnv")]
|
||||
public static void SetEnv(JNIEnv* env, JObject thiz, JString j_key, JString j_value)
|
||||
{
|
||||
string key = env->GetStringUTFChars(j_key);
|
||||
string value = env->GetStringUTFChars(j_value);
|
||||
Environment.SetEnvironmentVariable(key, value);
|
||||
}
|
||||
|
||||
// int Java_net_dot_MonoRunner_initRuntime (JNIEnv* env, jobject thiz, jstring j_files_dir, jstring j_entryPointLibName, long current_local_time);
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) }, EntryPoint = "Java_net_dot_MonoRunner_initRuntime")]
|
||||
public static int InitRuntime(JNIEnv* env, JObject thiz, JString j_files_dir, JString j_entryPointLibName, long current_local_time)
|
||||
{
|
||||
// The NativeAOT runtime does not need to be initialized, but the crypto library does.
|
||||
JavaVM* javaVM = env->GetJavaVM();
|
||||
AndroidCryptoNative_InitLibraryOnLoad(javaVM, null);
|
||||
return 0;
|
||||
}
|
||||
|
||||
[LibraryImport("System.Security.Cryptography.Native.Android")]
|
||||
internal static partial int AndroidCryptoNative_InitLibraryOnLoad(JavaVM* vm, void* reserved);
|
||||
|
||||
// int Java_net_dot_MonoRunner_execEntryPoint (JNIEnv* env, jobject thiz, jstring j_entryPointLibName, jobjectArray j_args);
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) }, EntryPoint = "Java_net_dot_MonoRunner_execEntryPoint")]
|
||||
public static int ExecEntryPoint(JNIEnv* env, JObject thiz, JString j_entryPointLibName, JObjectArray j_args)
|
||||
{
|
||||
return Program.Main();
|
||||
}
|
||||
|
||||
// void Java_net_dot_MonoRunner_freeNativeResources (JNIEnv* env, jobject thiz);
|
||||
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) }, EntryPoint = "Java_net_dot_MonoRunner_freeNativeResources")]
|
||||
public static void FreeNativeResources(JNIEnv* env, JObject thiz)
|
||||
{
|
||||
// Placeholder for actual implementation
|
||||
Console.WriteLine("FreeNativeResources start");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct JNIEnv
|
||||
{
|
||||
JNINativeInterface* NativeInterface;
|
||||
public string GetStringUTFChars(JString str)
|
||||
{
|
||||
fixed (JNIEnv* thisptr = &this)
|
||||
{
|
||||
byte* chars = NativeInterface->GetStringUTFChars(thisptr, str, out byte isCopy);
|
||||
string result = Marshal.PtrToStringUTF8((nint)chars);
|
||||
if (isCopy != 0)
|
||||
NativeInterface->ReleaseStringUTFChars(thisptr, str, chars);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public JavaVM* GetJavaVM()
|
||||
{
|
||||
fixed (JNIEnv* thisptr = &this)
|
||||
{
|
||||
JavaVM* vm;
|
||||
NativeInterface->GetJavaVM(thisptr, &vm);
|
||||
return vm;
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
unsafe struct JNINativeInterface
|
||||
{
|
||||
void* reserved0;
|
||||
void* reserved1;
|
||||
void* reserved2;
|
||||
|
||||
void* reserved3;
|
||||
void* GetVersion;
|
||||
|
||||
void* DefineClass;
|
||||
void* FindClass;
|
||||
|
||||
void* FromReflectedMethod;
|
||||
void* FromReflectedField;
|
||||
|
||||
void* ToReflectedMethod;
|
||||
|
||||
void* GetSuperclass;
|
||||
void* IsAssignableFrom;
|
||||
|
||||
void* ToReflectedField;
|
||||
|
||||
void* Throw;
|
||||
void* ThrowNew;
|
||||
void* ExceptionOccurred;
|
||||
void* ExceptionDescribe;
|
||||
void* ExceptionClear;
|
||||
void* FatalError;
|
||||
|
||||
void* PushLocalFrame;
|
||||
void* PopLocalFrame;
|
||||
|
||||
void* NewGlobalRef;
|
||||
void* DeleteGlobalRef;
|
||||
void* DeleteLocalRef;
|
||||
void* IsSameObject;
|
||||
void* NewLocalRef;
|
||||
void* EnsureLocalCapacity;
|
||||
|
||||
void* AllocObject;
|
||||
void* NewObject;
|
||||
void* NewObjectV;
|
||||
void* NewObjectA;
|
||||
|
||||
void* GetObjectClass;
|
||||
void* IsInstanceOf;
|
||||
|
||||
void* GetMethodID;
|
||||
|
||||
void* CallObjectMethod;
|
||||
void* CallObjectMethodV;
|
||||
void* CallObjectMethodA;
|
||||
|
||||
void* CallBooleanMethod;
|
||||
void* CallBooleanMethodV;
|
||||
void* CallBooleanMethodA;
|
||||
|
||||
void* CallByteMethod;
|
||||
void* CallByteMethodV;
|
||||
void* CallByteMethodA;
|
||||
|
||||
void* CallCharMethod;
|
||||
void* CallCharMethodV;
|
||||
void* CallCharMethodA;
|
||||
|
||||
void* CallShortMethod;
|
||||
void* CallShortMethodV;
|
||||
void* CallShortMethodA;
|
||||
|
||||
void* CallIntMethod;
|
||||
void* CallIntMethodV;
|
||||
void* CallIntMethodA;
|
||||
|
||||
void* CallLongMethod;
|
||||
void* CallLongMethodV;
|
||||
void* CallLongMethodA;
|
||||
|
||||
void* CallFloatMethod;
|
||||
void* CallFloatMethodV;
|
||||
void* CallFloatMethodA;
|
||||
|
||||
void* CallDoubleMethod;
|
||||
void* CallDoubleMethodV;
|
||||
void* CallDoubleMethodA;
|
||||
|
||||
void* CallVoidMethod;
|
||||
void* CallVoidMethodV;
|
||||
void* CallVoidMethodA;
|
||||
|
||||
void* CallNonvirtualObjectMethod;
|
||||
void* CallNonvirtualObjectMethodV;
|
||||
void* CallNonvirtualObjectMethodA;
|
||||
|
||||
void* CallNonvirtualBooleanMethod;
|
||||
void* CallNonvirtualBooleanMethodV;
|
||||
void* CallNonvirtualBooleanMethodA;
|
||||
|
||||
void* CallNonvirtualByteMethod;
|
||||
void* CallNonvirtualByteMethodV;
|
||||
void* CallNonvirtualByteMethodA;
|
||||
|
||||
void* CallNonvirtualCharMethod;
|
||||
void* CallNonvirtualCharMethodV;
|
||||
void* CallNonvirtualCharMethodA;
|
||||
|
||||
void* CallNonvirtualShortMethod;
|
||||
void* CallNonvirtualShortMethodV;
|
||||
void* CallNonvirtualShortMethodA;
|
||||
|
||||
void* CallNonvirtualIntMethod;
|
||||
void* CallNonvirtualIntMethodV;
|
||||
void* CallNonvirtualIntMethodA;
|
||||
|
||||
void* CallNonvirtualLongMethod;
|
||||
void* CallNonvirtualLongMethodV;
|
||||
void* CallNonvirtualLongMethodA;
|
||||
|
||||
void* CallNonvirtualFloatMethod;
|
||||
void* CallNonvirtualFloatMethodV;
|
||||
void* CallNonvirtualFloatMethodA;
|
||||
|
||||
void* CallNonvirtualDoubleMethod;
|
||||
void* CallNonvirtualDoubleMethodV;
|
||||
void* CallNonvirtualDoubleMethodA;
|
||||
|
||||
void* CallNonvirtualVoidMethod;
|
||||
void* CallNonvirtualVoidMethodV;
|
||||
void* CallNonvirtualVoidMethodA;
|
||||
|
||||
void* GetFieldID;
|
||||
|
||||
void* GetObjectField;
|
||||
void* GetBooleanField;
|
||||
void* GetByteField;
|
||||
void* GetCharField;
|
||||
void* GetShortField;
|
||||
void* GetIntField;
|
||||
void* GetLongField;
|
||||
void* GetFloatField;
|
||||
void* GetDoubleField;
|
||||
|
||||
void* SetObjectField;
|
||||
void* SetBooleanField;
|
||||
void* SetByteField;
|
||||
void* SetCharField;
|
||||
void* SetShortField;
|
||||
void* SetIntField;
|
||||
void* SetLongField;
|
||||
void* SetFloatField;
|
||||
void* SetDoubleField;
|
||||
|
||||
void* GetStaticMethodID;
|
||||
|
||||
void* CallStaticObjectMethod;
|
||||
void* CallStaticObjectMethodV;
|
||||
void* CallStaticObjectMethodA;
|
||||
|
||||
void* CallStaticBooleanMethod;
|
||||
void* CallStaticBooleanMethodV;
|
||||
void* CallStaticBooleanMethodA;
|
||||
|
||||
void* CallStaticByteMethod;
|
||||
void* CallStaticByteMethodV;
|
||||
void* CallStaticByteMethodA;
|
||||
|
||||
void* CallStaticCharMethod;
|
||||
void* CallStaticCharMethodV;
|
||||
void* CallStaticCharMethodA;
|
||||
|
||||
void* CallStaticShortMethod;
|
||||
void* CallStaticShortMethodV;
|
||||
void* CallStaticShortMethodA;
|
||||
|
||||
void* CallStaticIntMethod;
|
||||
void* CallStaticIntMethodV;
|
||||
void* CallStaticIntMethodA;
|
||||
|
||||
void* CallStaticLongMethod;
|
||||
void* CallStaticLongMethodV;
|
||||
void* CallStaticLongMethodA;
|
||||
|
||||
void* CallStaticFloatMethod;
|
||||
void* CallStaticFloatMethodV;
|
||||
void* CallStaticFloatMethodA;
|
||||
|
||||
void* CallStaticDoubleMethod;
|
||||
void* CallStaticDoubleMethodV;
|
||||
void* CallStaticDoubleMethodA;
|
||||
|
||||
void* CallStaticVoidMethod;
|
||||
void* CallStaticVoidMethodV;
|
||||
void* CallStaticVoidMethodA;
|
||||
|
||||
void* GetStaticFieldID;
|
||||
void* GetStaticObjectField;
|
||||
void* GetStaticBooleanField;
|
||||
void* GetStaticByteField;
|
||||
void* GetStaticCharField;
|
||||
void* GetStaticShortField;
|
||||
void* GetStaticIntField;
|
||||
void* GetStaticLongField;
|
||||
void* GetStaticFloatField;
|
||||
void* GetStaticDoubleField;
|
||||
|
||||
void* SetStaticObjectField;
|
||||
void* SetStaticBooleanField;
|
||||
void* SetStaticByteField;
|
||||
void* SetStaticCharField;
|
||||
void* SetStaticShortField;
|
||||
void* SetStaticIntField;
|
||||
void* SetStaticLongField;
|
||||
void* SetStaticFloatField;
|
||||
void* SetStaticDoubleField;
|
||||
|
||||
void* NewString;
|
||||
void* GetStringLength;
|
||||
void* GetStringChars;
|
||||
void* ReleaseStringChars;
|
||||
|
||||
void* NewStringUTF;
|
||||
delegate* unmanaged[Cdecl]<JNIEnv*, JString, int> GetStringUTFLength;
|
||||
public delegate* unmanaged[Cdecl]<JNIEnv*, JString, out byte, byte*> GetStringUTFChars;
|
||||
public delegate* unmanaged[Cdecl]<JNIEnv*, JString, byte*, void> ReleaseStringUTFChars;
|
||||
|
||||
void* GetArrayLength;
|
||||
|
||||
void* NewObjectArray;
|
||||
void* GetObjectArrayElement;
|
||||
void* SetObjectArrayElement;
|
||||
|
||||
void* NewBooleanArray;
|
||||
void* NewByteArray;
|
||||
void* NewCharArray;
|
||||
void* NewShortArray;
|
||||
void* NewIntArray;
|
||||
void* NewLongArray;
|
||||
void* NewFloatArray;
|
||||
void* NewDoubleArray;
|
||||
|
||||
void* GetBooleanArrayElements;
|
||||
void* GetByteArrayElements;
|
||||
void* GetCharArrayElements;
|
||||
void* GetShortArrayElements;
|
||||
void* GetIntArrayElements;
|
||||
void* GetLongArrayElements;
|
||||
void* GetFloatArrayElements;
|
||||
void* GetDoubleArrayElements;
|
||||
|
||||
void* ReleaseBooleanArrayElements;
|
||||
void* ReleaseByteArrayElements;
|
||||
void* ReleaseCharArrayElements;
|
||||
void* ReleaseShortArrayElements;
|
||||
void* ReleaseIntArrayElements;
|
||||
void* ReleaseLongArrayElements;
|
||||
void* ReleaseFloatArrayElements;
|
||||
void* ReleaseDoubleArrayElements;
|
||||
|
||||
void* GetBooleanArrayRegion;
|
||||
void* GetByteArrayRegion;
|
||||
void* GetCharArrayRegion;
|
||||
void* GetShortArrayRegion;
|
||||
void* GetIntArrayRegion;
|
||||
void* GetLongArrayRegion;
|
||||
void* GetFloatArrayRegion;
|
||||
void* GetDoubleArrayRegion;
|
||||
|
||||
void* SetBooleanArrayRegion;
|
||||
void* SetByteArrayRegion;
|
||||
void* SetCharArrayRegion;
|
||||
void* SetShortArrayRegion;
|
||||
void* SetIntArrayRegion;
|
||||
void* SetLongArrayRegion;
|
||||
void* SetFloatArrayRegion;
|
||||
void* SetDoubleArrayRegion;
|
||||
|
||||
void* RegisterNatives;
|
||||
void* UnregisterNatives;
|
||||
|
||||
void* MonitorEnter;
|
||||
void* MonitorExit;
|
||||
|
||||
public delegate* unmanaged[Cdecl]<JNIEnv*, JavaVM**, int> GetJavaVM;
|
||||
|
||||
void* GetStringRegion;
|
||||
void* GetStringUTFRegion;
|
||||
|
||||
void* GetPrimitiveArrayCritical;
|
||||
void* ReleasePrimitiveArrayCritical;
|
||||
|
||||
void* GetStringCritical;
|
||||
void* ReleaseStringCritical;
|
||||
|
||||
void* NewWeakGlobalRef;
|
||||
void* DeleteWeakGlobalRef;
|
||||
|
||||
void* ExceptionCheck;
|
||||
|
||||
void* NewDirectByteBuffer;
|
||||
void* GetDirectBufferAddress;
|
||||
void* GetDirectBufferCapacity;
|
||||
|
||||
/* New JNI 1.6 Features */
|
||||
|
||||
void* GetObjectRefType;
|
||||
|
||||
/* Module Features */
|
||||
|
||||
void* GetModule;
|
||||
|
||||
/* Virtual threads */
|
||||
|
||||
void* IsVirtualThread;
|
||||
|
||||
/* Large UTF8 Support */
|
||||
|
||||
void* GetStringUTFLengthAsLong;
|
||||
};
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal unsafe struct JavaVM
|
||||
{
|
||||
JNIInvokeInterface* InvokeInterface;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
struct JNIInvokeInterface
|
||||
{
|
||||
void* reserved0;
|
||||
void* reserved1;
|
||||
void* reserved2;
|
||||
void* DestroyJavaVM;
|
||||
void* AttachCurrentThread;
|
||||
void* DetachCurrentThread;
|
||||
void* GetEnv;
|
||||
void* AttachCurrentThreadAsDaemon;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore IDE0060 // Remove unused parameter
|
|
@ -151,7 +151,7 @@ namespace Microsoft.Android.Build
|
|||
return "linux";
|
||||
}
|
||||
|
||||
private static string DetermineAbi(string runtimeIdentifier) =>
|
||||
public static string DetermineAbi(string runtimeIdentifier) =>
|
||||
runtimeIdentifier switch
|
||||
{
|
||||
"android-x86" => "x86",
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- ./dotnet.sh build -c <Debug|Release> src/tests/FunctionalTests/Android/Device_Emulator/NativeAOT/Android.Device_Emulator.NativeAOT.Test.csproj /t:Test -bl /p:targetos=android /p:targetarchitecture=x64 -->
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TestRuntime>true</TestRuntime>
|
||||
<TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
|
||||
<TargetName>lib$(MSBuildProjectName)</TargetName>
|
||||
<MainLibraryFileName>$(TargetName).so</MainLibraryFileName>
|
||||
<ExpectedExitCode>42</ExpectedExitCode>
|
||||
<UseNativeAOTRuntime>true</UseNativeAOTRuntime>
|
||||
<PublishAOT>true</PublishAOT>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\..\..\..\tasks\AndroidAppBuilder\Templates\monodroid-nativeaot.cs" />
|
||||
<DirectPInvoke Include="System.Security.Cryptography.Native.Android" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Program.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,16 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using System;
|
||||
|
||||
public class Program
|
||||
{
|
||||
public static int Main()
|
||||
{
|
||||
string message = "Hello, Android!";
|
||||
Console.WriteLine(message); // logcat
|
||||
// Test the linux-bionic cryptography library
|
||||
Console.WriteLine(System.Security.Cryptography.SHA256.HashData(new byte[] {0x1, 0x2, 0x3}));
|
||||
return 42;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue