Skip to content

Commit

Permalink
[NativeAOT] MSBuild-related logic to get projects to build
Browse files Browse the repository at this point in the history
This is an initial step to get the NativeAOT build working the same as
iOS does. At a high level, the changes are:

* Run `ILLink` with our existing trimmer/linker pipeline.

* Temporarily change our RID to `linux-bionic-arm64`.

* Pass the output to `ILC`, the NativeAOT compiler.

* Turn the RID back to `android-arm64`.

A list of MSBuild/workload changes required so far:

* `$(UseMonoRuntime)` is false when `$(PublishAot)` is true

* Set `$(_IsPublishing)` as NativeAOT expects `dotnet publish` to be
  the only way NativeAOT is used. Setting this in our targets allows
  the proper `*.NativeAOT.*` packs to restore inside of a `dotnet
  build`.

* `$(SelfContained)=true`, seems to be required for the
  `linux-bionic-arm64` runtime packs to restore. All Android apps are
  self-contained, so this might be fine.

* Create a new `Microsoft.Android.Sdk.NativeAOT.targets` file that
  uses `$(_AndroidNdkDirectory)` to set various properties for
  NativeAOT's build (ILC).

* `HACK:` set `$(_targetOS)` to `linux` to make the NativeAOT build
  attempt to run. `--targetos:android` results in a build error that
  says Android is not supported.

* Disable `$(RunAOTCompilation)`, Mono's AOT compiler and the
  `<RemoveRegisterAttribute/>` MSBuild task.

* Disable `$(AndroidEnableMarshalMethods)` to be re-enabled in a
  future PR.

A list of blockers or things that don't work yet:

* NativeAOT apps won't launch yet (future changes for that)

* The NativeAOT cross compiler doesn't run on Windows:

    Microsoft.NETCore.Native.Publish.targets(61,5): Cross-OS native compilation is not supported.
    Microsoft.NETCore.Native.Unix.targets(296,5): error : Platform linker ('C:\Android\android-sdk\ndk\26.3.11579264\toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang++' or 'gcc') not found in PATH. Ensure you have all the required prerequisites documented at https://aka.ms/nativeaot-prerequisites.

* You can only target `-r android-arm64` as there are no other
  `linux-bionic-*` runtime packs yet.

* `-p:PublishAotUsingRuntimePack=true` is currently required, but I
  will investigate if we should just set this by default.
  • Loading branch information
jonathanpeppers committed Dec 10, 2024
1 parent fc88da7 commit 546c241
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<AndroidUseIntermediateDesignerFile Condition=" '$(AndroidUseDesignerAssembly)' == 'True' ">false</AndroidUseIntermediateDesignerFile>
<AndroidUseIntermediateDesignerFile Condition=" '$(AndroidUseIntermediateDesignerFile)' == '' ">$(AndroidGenerateResourceDesigner)</AndroidUseIntermediateDesignerFile>
<AllowSelfContainedWithoutRuntimeIdentifier Condition =" '$(AllowSelfContainedWithoutRuntimeIdentifier)' == '' ">true</AllowSelfContainedWithoutRuntimeIdentifier>
<SelfContained Condition=" '$(SelfContained)' == '' ">true</SelfContained>
<GenerateDependencyFile Condition=" '$(GenerateDependencyFile)' == '' ">false</GenerateDependencyFile>
<CopyLocalLockFileAssemblies Condition=" '$(CopyLocalLockFileAssemblies)' == '' ">false</CopyLocalLockFileAssemblies>
<ComputeNETCoreBuildOutputFiles Condition=" '$(ComputeNETCoreBuildOutputFiles)' == '' ">false</ComputeNETCoreBuildOutputFiles>
Expand All @@ -23,7 +24,10 @@
See: https://github.com/dotnet/sdk/blob/955c0fc7b06e2fa34bacd076ed39f61e4fb61716/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.Publish.targets#L16
-->
<_GetChildProjectCopyToPublishDirectoryItems>false</_GetChildProjectCopyToPublishDirectoryItems>
<UseMonoRuntime Condition=" '$(PublishAot)' == 'true' and '$(UseMonoRuntime)' == '' ">false</UseMonoRuntime>
<UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' ">true</UseMonoRuntime>
<!-- HACK: make dotnet restore include Microsoft.NETCore.App.Runtime.NativeAOT.linux-bionic-arm64 -->
<_IsPublishing Condition=" '$(_IsPublishing)' == '' and '$(PublishAot)' == 'true' ">true</_IsPublishing>

<!-- Use $(AndroidMinimumSupportedApiLevel) for $(SupportedOSPlatformVersion) if unset -->
<SupportedOSPlatformVersion Condition=" '$(SupportedOSPlatformVersion)' == '' ">$(AndroidMinimumSupportedApiLevel)</SupportedOSPlatformVersion>
Expand Down Expand Up @@ -89,8 +93,8 @@
<RuntimeIdentifiers Condition=" '$(RuntimeIdentifier)' == '' And '$(RuntimeIdentifiers)' == '' ">android-arm64;android-x64</RuntimeIdentifiers>
<RuntimeIdentifier Condition=" '$(RuntimeIdentifiers)' != '' And '$(RuntimeIdentifier)' != '' " />
<GenerateApplicationManifest Condition=" '$(GenerateApplicationManifest)' == '' ">true</GenerateApplicationManifest>
<!-- Default to AOT in Release mode -->
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' and '$(AotAssemblies)' == '' and '$(Configuration)' == 'Release' ">true</RunAOTCompilation>
<!-- Default to Mono's AOT in Release mode -->
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' and '$(AotAssemblies)' == '' and '$(Configuration)' == 'Release' and '$(PublishAot)' != 'true' ">true</RunAOTCompilation>
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' and '$(AotAssemblies)' == 'true' ">true</RunAOTCompilation>
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' ">false</RunAOTCompilation>
<_AndroidXA1029 Condition=" '$(AotAssemblies)' != '' ">true</_AndroidXA1029>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<!--
***********************************************************************************************
Microsoft.Android.Sdk.NativeAOT.targets
This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
***********************************************************************************************
-->
<Project>

<!-- Make IlcCompile depend on the trimmer -->
<PropertyGroup>
<IlcCompileDependsOn>
_AndroidBeforeIlcCompile;
SetupOSSpecificProps;
PrepareForILLink;
ILLink;
ComputeIlcCompileInputs;
_AndroidComputeIlcCompileInputs;
$(IlcCompileDependsOn)
</IlcCompileDependsOn>
</PropertyGroup>

<Target Name="_AndroidBeforeIlcCompile" BeforeTargets="SetupProperties">
<!-- Example settings from: https://github.com/jonathanpeppers/Android-NativeAOT/blob/ea69d122cdc7de67aa6a5db14b7e560763c63cdd/DotNet/libdotnet.targets -->
<PropertyGroup>
<_NdkSysrootAbi>aarch64-linux-android</_NdkSysrootAbi>
<_NdkClangPrefix>aarch64-linux-android21-</_NdkClangPrefix>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('windows')) ">windows-x86_64</_NdkPrebuiltAbi>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('osx')) ">darwin-x86_64</_NdkPrebuiltAbi>
<_NdkPrebuiltAbi Condition=" $([MSBuild]::IsOSPlatform('linux')) ">linux-x86_64</_NdkPrebuiltAbi>
<_NdkSysrootDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/sysroot/usr/lib/$(_NdkSysrootAbi)</_NdkSysrootDir>
<_NdkBinDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/bin/</_NdkBinDir>
<CppCompilerAndLinker>$(_NdkBinDir)$(_NdkClangPrefix)clang++</CppCompilerAndLinker>
<CppLinker>$(CppCompilerAndLinker)</CppLinker>
<ObjCopyName>$(_NdkBinDir)llvm-objcopy</ObjCopyName>

<!-- Example settings from: https://github.com/xamarin/xamarin-macios/blob/c43d4ea40bc777969e3b158cf46446df292d8449/dotnet/targets/Xamarin.Shared.Sdk.targets#L541-L550 -->
<RunILLink>true</RunILLink>
<!--
We want to suppress warnings from trimmer and only show warnings from ILC.
Otherwise, you would get 2x for every warning.
-->
<_OriginalSuppressTrimAnalysisWarnings>$(SuppressTrimAnalysisWarnings)</_OriginalSuppressTrimAnalysisWarnings>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>

<!-- The list of hacks below should go away when we have NativeAOT.android-* packs -->
<!-- HACK: we are android-arm64, so this is required for the right path(s) to be found -->
<_OriginalRuntimeIdentifier>$(RuntimeIdentifier)</_OriginalRuntimeIdentifier>
<RuntimeIdentifier Condition=" '$(RuntimeIdentifier)' == 'android-arm64' ">linux-bionic-arm64</RuntimeIdentifier>
<!-- HACK: -targetos:android results in error, so use linux -->
<_targetOS>linux</_targetOS>
<!-- HACK: prevents libSystem.Net.Security.Native.a from being added -->
<_linuxLibcFlavor>bionic</_linuxLibcFlavor>
</PropertyGroup>
</Target>

<Target Name="_AndroidComputeIlcCompileInputs">
<PropertyGroup>
<!-- Turn trimmer warnings back to original value -->
<SuppressTrimAnalysisWarnings>$(_OriginalSuppressTrimAnalysisWarnings)</SuppressTrimAnalysisWarnings>
</PropertyGroup>
<ItemGroup>
<!-- Give ILLink's output to ILC -->
<IlcCompileInput Remove="@(IlcCompileInput)" />
<IlcCompileInput Include="$(IntermediateLinkDir)$(TargetName)$(TargetExt)" />
<IlcReference Remove="@(IlcReference)" />
<IlcReference Include="@(PrivateSdkAssemblies)" />
<IlcReference Include="@(ManagedAssemblyToLink->'$(IntermediateLinkDir)%(Filename)%(Extension)')" Condition="Exists('$(IntermediateLinkDir)%(Filename)%(Extension)')" Exclude="@(IlcCompileInput)" />
</ItemGroup>
</Target>

<Target Name="_AndroidAfterLinkNative" AfterTargets="LinkNative">
<PropertyGroup>
<!-- Turn $(RuntimeIdentifier) back to original value -->
<RuntimeIdentifier>$(_OriginalRuntimeIdentifier)</RuntimeIdentifier>
</PropertyGroup>
</Target>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@
<Import Project="Microsoft.Android.Sdk.DefaultProperties.targets" />
<Import Project="$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props"
Condition="Exists('$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props')"/>
<Import Project="Microsoft.Android.Sdk.NativeAOT.targets" Condition=" '$(PublishAot)' == 'true' " />

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,30 @@ public void BuildBasicApplication ([Values (true, false)] bool isRelease, [Value
}
}

[Test]
public void NativeAOT ()
{
if (IsWindows) {
// Microsoft.NETCore.Native.Publish.targets(61,5): Cross-OS native compilation is not supported.
// Set $(DisableUnsupportedError)=true, Microsoft.NETCore.Native.Unix.targets(296,5): error : Platform linker ('C:\Android\android-sdk\ndk\26.3.11579264\toolchains/llvm/prebuilt/windows-x86_64/bin/aarch64-linux-android21-clang++' or 'gcc') not found in PATH. Ensure you have all the required prerequisites documented at https://aka.ms/nativeaot-prerequisites.
Assert.Ignore ("This test is not valid on Windows.");
}

var proj = new XamarinAndroidApplicationProject {
IsRelease = true,
// Add locally downloaded NativeAOT packs
ExtraNuGetConfigSources = {
Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"),
}
};
proj.SetRuntimeIdentifier ("arm64-v8a");
proj.SetProperty ("PublishAot", "true");
proj.SetProperty ("PublishAotUsingRuntimePack", "true");

using var b = CreateApkBuilder ();
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
}

[Test]
public void BuildBasicApplicationThenMoveIt ([Values (true, false)] bool isRelease)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,9 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
<AndroidUseAssemblyStore Condition=" '$(AndroidUseAssemblyStore)' == '' ">true</AndroidUseAssemblyStore>
<AndroidAotEnableLazyLoad Condition=" '$(AndroidAotEnableLazyLoad)' == '' And '$(AotAssemblies)' == 'true' And '$(AndroidIncludeDebugSymbols)' != 'true' ">True</AndroidAotEnableLazyLoad>
<AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' and ('$(UsingMicrosoftNETSdkRazor)' == 'true') ">False</AndroidEnableMarshalMethods>
<AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' ">True</AndroidEnableMarshalMethods>
<AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' and '$(PublishAot)' != 'true' ">True</AndroidEnableMarshalMethods>
<!-- NOTE: temporarily disable for NativeAOT for now, to get build passing -->
<AndroidEnableMarshalMethods Condition=" '$(AndroidEnableMarshalMethods)' == '' and '$(PublishAot)' == 'true' ">False</AndroidEnableMarshalMethods>
<_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' ">False</_AndroidUseMarshalMethods>
<_AndroidUseMarshalMethods Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">$(AndroidEnableMarshalMethods)</_AndroidUseMarshalMethods>
</PropertyGroup>
Expand Down Expand Up @@ -1937,7 +1939,7 @@ because xbuild doesn't support framework reference assemblies.

<!-- Shrink Mono.Android.dll by removing attribute only needed for GenerateJavaStubs -->
<RemoveRegisterAttribute
Condition="'$(AndroidLinkMode)' != 'None' AND '$(AndroidIncludeDebugSymbols)' != 'true' AND '$(AndroidStripILAfterAOT)' != 'true'"
Condition="'$(AndroidLinkMode)' != 'None' and '$(AndroidIncludeDebugSymbols)' != 'true' and '$(AndroidStripILAfterAOT)' != 'true' and '$(PublishAot)' != 'true' "
ShrunkFrameworkAssemblies="@(_ShrunkAssemblies)" />

<MakeDir Directories="$(MonoAndroidIntermediateAssemblyDir)shrunk" />
Expand Down

0 comments on commit 546c241

Please sign in to comment.