Skip to content

Commit

Permalink
[Android] Add NdkToolFinder task & Fix up AOT app build (#88210)
Browse files Browse the repository at this point in the history
Since we bumped to NDK 23, having the aot compiler itself generate shared libraries stopped working. This is due to NDK 23 moving most of the toolchain into a common bin directory. AS was left over in each of these directories as an alias to bin/<triple>-as.

This change adds a task to collect all of the important NDK toolchain paths. It also fixes up the aot build when AOTWithLibraryFiles is set to true and we want the aot compiler to produce shared libraries.
  • Loading branch information
steveisok authored Jul 6, 2023
1 parent cd9d541 commit b3d2503
Show file tree
Hide file tree
Showing 15 changed files with 550 additions and 34 deletions.
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@

<AppleAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AppleAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)'))</AppleAppBuilderDir>
<AndroidAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'AndroidAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)', 'publish'))</AndroidAppBuilderDir>
<MobileBuildTasksDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'MobileBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)'))</MobileBuildTasksDir>
<WasmAppBuilderDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppBuilder', 'Debug', '$(NetCoreAppToolCurrent)'))</WasmAppBuilderDir>
<WasmBuildTasksDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)', 'publish'))</WasmBuildTasksDir>
<WorkloadBuildTasksDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WorkloadBuildTasks', 'Debug', '$(NetCoreAppToolCurrent)'))</WorkloadBuildTasksDir>
Expand All @@ -162,6 +163,7 @@
<Crossgen2SdkOverrideTargetsPath Condition="'$(MSBuildRuntimeType)' == 'Core'">$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Crossgen2Tasks', 'Debug', '$(NetCoreAppToolCurrent)', 'Microsoft.NET.CrossGen.targets'))</Crossgen2SdkOverrideTargetsPath>
<AppleAppBuilderTasksAssemblyPath>$([MSBuild]::NormalizePath('$(AppleAppBuilderDir)', 'AppleAppBuilder.dll'))</AppleAppBuilderTasksAssemblyPath>
<AndroidAppBuilderTasksAssemblyPath>$([MSBuild]::NormalizePath('$(AndroidAppBuilderDir)', 'AndroidAppBuilder.dll'))</AndroidAppBuilderTasksAssemblyPath>
<MobileBuildTasksAssemblyPath>$([MSBuild]::NormalizePath('$(MobileBuildTasksDir)', 'MobileBuildTasks.dll'))</MobileBuildTasksAssemblyPath>
<WasmAppBuilderTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmAppBuilderDir)', 'WasmAppBuilder.dll'))</WasmAppBuilderTasksAssemblyPath>
<WasmBuildTasksAssemblyPath>$([MSBuild]::NormalizePath('$(WasmBuildTasksDir)', 'WasmBuildTasks.dll'))</WasmBuildTasksAssemblyPath>
<WasmAppHostDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppHost', 'wasm', '$(Configuration)'))</WasmAppHostDir>
Expand Down
9 changes: 7 additions & 2 deletions src/mono/mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ typedef struct MonoAotOptions {
gboolean deterministic;
gboolean allow_errors;
char *tool_prefix;
char *as_prefix;
char *ld_flags;
char *ld_name;
char *mtriple;
Expand Down Expand Up @@ -8825,6 +8826,8 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
opts->nunbox_arbitrary_trampolines = atoi (arg + strlen ("nunbox-arbitrary-trampolines="));
} else if (str_begins_with (arg, "tool-prefix=")) {
opts->tool_prefix = g_strdup (arg + strlen ("tool-prefix="));
} else if (str_begins_with (arg, "as-prefix=")) {
opts->as_prefix = g_strdup (arg + strlen ("as-prefix="));
} else if (str_begins_with (arg, "ld-flags=")) {
opts->ld_flags = g_strdup (arg + strlen ("ld-flags="));
} else if (str_begins_with (arg, "ld-name=")) {
Expand Down Expand Up @@ -13123,6 +13126,7 @@ compile_asm (MonoAotCompile *acfg)
char *command, *objfile;
char *outfile_name, *tmp_outfile_name, *llvm_ofile;
const char *tool_prefix = acfg->aot_opts.tool_prefix ? acfg->aot_opts.tool_prefix : "";
const char *as_prefix = acfg->aot_opts.as_prefix ? acfg->aot_opts.as_prefix : tool_prefix;
char *ld_flags = acfg->aot_opts.ld_flags ? acfg->aot_opts.ld_flags : g_strdup("");

#ifdef TARGET_WIN32_MSVC
Expand Down Expand Up @@ -13214,7 +13218,7 @@ compile_asm (MonoAotCompile *acfg)
g_string_append (acfg->as_args, "-c -x assembler ");
#endif

command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS,
command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", as_prefix, AS_NAME, AS_OPTIONS,
acfg->as_args ? acfg->as_args->str : "",
wrap_path (objfile), wrap_path (acfg->tmpfname));
aot_printf (acfg, "Executing the native assembler: %s\n", command);
Expand All @@ -13225,7 +13229,7 @@ compile_asm (MonoAotCompile *acfg)
}

if (acfg->llvm && !acfg->llvm_owriter) {
command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", tool_prefix, AS_NAME, AS_OPTIONS,
command = g_strdup_printf ("\"%s%s\" %s %s -o %s %s", as_prefix, AS_NAME, AS_OPTIONS,
acfg->as_args ? acfg->as_args->str : "",
wrap_path (acfg->llvm_ofile), wrap_path (acfg->llvm_sfile));
aot_printf (acfg, "Executing the native assembler: %s\n", command);
Expand Down Expand Up @@ -14222,6 +14226,7 @@ aot_opts_free (MonoAotOptions *aot_opts)
g_list_free (aot_opts->direct_pinvoke_lists);
g_free (aot_opts->dedup_include);
g_free (aot_opts->tool_prefix);
g_free (aot_opts->as_prefix);
g_free (aot_opts->ld_flags);
g_free (aot_opts->ld_name);
g_free (aot_opts->mtriple);
Expand Down
4 changes: 4 additions & 0 deletions src/mono/msbuild/android/build/AndroidBuild.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
<UseMonoRuntime>true</UseMonoRuntime>
<UseMonoJustInterp Condition="'$(RunAOTCompilation)' == 'true' and '$(MonoForceInterpreter)' == 'true'">true</UseMonoJustInterp>

<_HostOS Condition="$([MSBuild]::IsOSPlatform('Windows'))">windows</_HostOS>
<_HostOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">osx</_HostOS>
<_HostOS Condition="'$(_HostOS)' == ''">linux</_HostOS>

<_IsLibraryMode Condition="'$(NativeLib)' != ''">true</_IsLibraryMode>

<AndroidBuildAfterThisTarget Condition="'$(AndroidBuildAfterThisTarget)' == ''">Publish</AndroidBuildAfterThisTarget>
Expand Down
40 changes: 38 additions & 2 deletions src/mono/msbuild/android/build/AndroidBuild.targets
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
<EnableDefaultAssembliesToBundle Condition="'$(EnableDefaultAssembliesToBundle)' == ''">false</EnableDefaultAssembliesToBundle>
</PropertyGroup>

<UsingTask Condition="'$(RunAOTCompilation)' == 'true'"
TaskName="NdkToolFinderTask"
AssemblyFile="$(MobileBuildTasksAssemblyPath)" />
<UsingTask Condition="'$(AndroidGenerateAppBundle)' == 'true'"
TaskName="AndroidAppBuilderTask"
AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)" />
Expand Down Expand Up @@ -37,7 +40,6 @@

<BundleDir>$(AndroidBundleDir)</BundleDir>
<_MonoHeaderPath>$([MSBuild]::NormalizeDirectory($(MicrosoftNetCoreAppRuntimePackRidNativeDir), 'include', 'mono-2.0'))</_MonoHeaderPath>
<_AotModuleTablePath>$(AndroidBundleDir)\modules.c</_AotModuleTablePath>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -94,6 +96,15 @@
<_AOTMode Condition="'$(UseMonoJustInterp)' != 'true'">Normal</_AOTMode>
<_AOTMode Condition="'$(UseMonoJustInterp)' == 'true'">JustInterp</_AOTMode>
<_AOTMode Condition="'$(ForceFullAOT)' == 'true'">Full</_AOTMode>
<_AotOutputType>AsmOnly</_AotOutputType>
</PropertyGroup>
<!-- Should consider renaming property to something more appropriate-->
<PropertyGroup Condition="'$(AOTWithLibraryFiles)' == 'true'">
<_AotOutputType>Library</_AotOutputType>
<_AotLibraryFormat>So</_AotLibraryFormat>
</PropertyGroup>
<PropertyGroup Condition="'$(AOTWithLibraryFiles)' != 'true'">
<_AotModuleTablePath>$(AndroidBundleDir)\modules.c</_AotModuleTablePath>
</PropertyGroup>

<PropertyGroup Condition="'$(_IsLibraryMode)' == 'true'">
Expand Down Expand Up @@ -126,6 +137,28 @@
<ProcessArguments>@(MonoAOTCompilerDefaultProcessArguments, ';')</ProcessArguments>
</PropertyGroup>

<PropertyGroup>
<AndroidLibraryMinApiLevel Condition="'$(AndroidLibraryMinApiLevel)' == ''">21</AndroidLibraryMinApiLevel>
</PropertyGroup>

<NdkToolFinderTask
Condition="'$(AOTWithLibraryFiles)' == 'true'"
Architecture="$(TargetArchitecture)"
HostOS="$(_HostOS)"
MinApiLevel="$(AndroidLibraryMinApiLevel)">
<Output TaskParameter="AsPrefixPath" PropertyName="_AsPrefixPath" />
<Output TaskParameter="ToolPrefixPath" PropertyName="_ToolPrefixPath" />
<Output TaskParameter="Triple" PropertyName="_Triple" />
<Output TaskParameter="LdName" PropertyName="_LdName" />
<Output TaskParameter="LdPath" PropertyName="_LdPath" />
<Output TaskParameter="ClangPath" PropertyName="_ClangPath" />
</NdkToolFinderTask>

<PropertyGroup Condition="'$(AOTWithLibraryFiles)' == 'true'">
<_AsPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_AsPrefixPath)'))</_AsPrefixPath>
<_ToolPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_ToolPrefixPath)'))</_ToolPrefixPath>
</PropertyGroup>

<ItemGroup>
<_AotInputAssemblies Include="@(_AssembliesToBundleInternal)"
Condition="'%(_AssembliesToBundleInternal._InternalForceInterpret)' != 'true'">
Expand Down Expand Up @@ -182,17 +215,20 @@

<MonoAOTCompiler
AotModulesTablePath="$(_AotModuleTablePath)"
AsPrefix="$(_AsPrefixPath)"
Assemblies="@(_AotInputAssemblies)"
CompilerBinaryPath="@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','$(TargetOS.ToLowerInvariant())-$(TargetArchitecture.ToLowerInvariant())'))"
DirectPInvokes="@(DirectPInvokes)"
DirectPInvokeLists="@(DirectPInvokeLists)"
EnableUnmanagedCallersOnlyMethodsExport="$(_EnableUnmanagedCallersOnlyMethodsExport)"
IntermediateOutputPath="$(_MobileIntermediateOutputPath)"
LibraryFormat="$(_AotLibraryFormat)"
LLVMPath="$(MonoAotCrossDir)"
MibcProfilePath="@(ProfiledAOTProfilePaths)"
Mode="$(_AOTMode)"
OutputDir="$(_MobileIntermediateOutputPath)"
OutputType="AsmOnly"
OutputType="$(_AotOutputType)"
ToolPrefix="$(_ToolPrefixPath)"
UseAotDataFile="$(_UseAotDataFile)"
UseLLVM="$(MonoEnableLLVM)">
<Output TaskParameter="CompiledAssemblies" ItemName="_AssembliesToBundleInternal" />
Expand Down
72 changes: 44 additions & 28 deletions src/mono/sample/Android/AndroidSampleApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,13 @@
</PropertyGroup>

<Import Project="$(RepoTasksDir)AotCompilerTask\MonoAOTCompiler.props" />
<UsingTask TaskName="AndroidAppBuilderTask" AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)"/>
<UsingTask TaskName="MonoAOTCompiler" AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
<UsingTask TaskName="AndroidAppBuilderTask"
AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)"/>
<UsingTask TaskName="MonoAOTCompiler"
AssemblyFile="$(MonoAOTCompilerTasksAssemblyPath)" />
<UsingTask Condition="'$(RunAOTCompilation)' == 'true'"
TaskName="NdkToolFinderTask"
AssemblyFile="$(MobileBuildTasksAssemblyPath)" />

<PropertyGroup Condition="'$(RunAOTCompilation)' == 'true'">
<_MobileIntermediateOutputPath>$(IntermediateOutputPath)mobile</_MobileIntermediateOutputPath>
Expand All @@ -36,46 +41,57 @@
Condition="'$(ForceAOT)' == 'true'"/>
<RemoveDir Directories="$(ApkDir)" />

<PropertyGroup>
<AndroidAbi Condition="'$(TargetArchitecture)' == 'arm64'">arm64-v8a</AndroidAbi>
<AndroidAbi Condition="'$(TargetArchitecture)' == 'arm'">armeabi-v7a</AndroidAbi>
<AndroidAbi Condition="'$(TargetArchitecture)' == 'x64'">x86_64</AndroidAbi>
<AndroidAbi Condition="'$(TargetArchitecture)' == 'x86'">x86</AndroidAbi>
</PropertyGroup>

<Message Importance="High" Text="Path: $(PublishDir)" />
<Message Importance="High" Text="SourceDir: $(OutputPath)" />

<PropertyGroup Condition="'$(ForceAOT)' == 'true' and '$(AOTWithLibraryFiles)' == 'true'">
<_AotOutputType>Library</_AotOutputType>
<_AotLibraryFormat>So</_AotLibraryFormat>
<_AotMode Condition="'$(AotMode)' == ''">Normal</_AotMode>
</PropertyGroup>

<PropertyGroup Condition="'$(ForceAOT)' == 'true' and '$(AOTWithLibraryFiles)' != 'true'">
<_AotOutputType>AsmOnly</_AotOutputType>
<_AotModulesTablePath>$(ApkDir)\modules.c</_AotModulesTablePath>
<_AotMode Condition="'$(AotMode)' == ''">Full</_AotMode>
</PropertyGroup>

<PropertyGroup Condition="'$(ForceAOT)' == 'true' and '$(AOTWithLibraryFiles)' == 'true'">
<_AotOutputType>Library</_AotOutputType>
<_AotLibraryFormat>So</_AotLibraryFormat>
<_PrebuiltOS Condition="$([MSBuild]::IsOSPlatform('Linux'))">linux-x86_64</_PrebuiltOS>
<_PrebuiltOS Condition="$([MSBuild]::IsOSPlatform('OSX'))">darwin-x86_64</_PrebuiltOS>
<_PrebuiltOS Condition="$([MSBuild]::IsOSPlatform('Windows'))">windows-x86_64</_PrebuiltOS>
<_PrebuiltAbi Condition="'$(TargetArchitecture)' == 'arm'">arm-linux-androideabi$</_PrebuiltAbi>
<_PrebuiltAbi Condition="'$(TargetArchitecture)' == 'arm64'">aarch64-linux-android</_PrebuiltAbi>
<_PrebuiltAbi Condition="'$(TargetArchitecture)' == 'x64'">x86_64-linux-android</_PrebuiltAbi>
<_PrebuiltAbi Condition="'$(TargetArchitecture)' == 'x86'">i686-linux-android</_PrebuiltAbi>
<_AotToolPrefix>$(ANDROID_NDK_ROOT)\toolchains\llvm\prebuilt\$(_PrebuiltOS)\bin\$(_PrebuiltAbi)-</_AotToolPrefix>
<PropertyGroup>
<AndroidLibraryMinApiLevel Condition="'$(AndroidLibraryMinApiLevel)' == ''">21</AndroidLibraryMinApiLevel>
</PropertyGroup>

<NdkToolFinderTask
Condition="'$(AOTWithLibraryFiles)' == 'true'"
Architecture="$(TargetArchitecture)"
HostOS="$(_HostOS)"
MinApiLevel="$(AndroidLibraryMinApiLevel)">
<Output TaskParameter="AsPrefixPath" PropertyName="_AsPrefixPath" />
<Output TaskParameter="ToolPrefixPath" PropertyName="_ToolPrefixPath" />
<Output TaskParameter="Triple" PropertyName="_Triple" />
<Output TaskParameter="LdName" PropertyName="_LdName" />
<Output TaskParameter="LdPath" PropertyName="_LdPath" />
<Output TaskParameter="ClangPath" PropertyName="_ClangPath" />
</NdkToolFinderTask>

<PropertyGroup Condition="'$(AOTWithLibraryFiles)' == 'true'">
<_AsPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_AsPrefixPath)'))</_AsPrefixPath>
<_ToolPrefixPath>$([MSBuild]::EnsureTrailingSlash('$(_ToolPrefixPath)'))</_ToolPrefixPath>
</PropertyGroup>

<MonoAOTCompiler Condition="'$(ForceAOT)' == 'true'"
AotModulesTablePath="$(_AotModulesTablePath)"
AsPrefix="$(_AsPrefixPath)"
Assemblies="@(AotInputAssemblies)"
CompilerBinaryPath="@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier','$(TargetOS)-$(TargetArchitecture.ToLowerInvariant())'))"
IntermediateOutputPath="$(IntermediateOutputPath)"
LibraryFormat="$(_AotLibraryFormat)"
LLVMPath="$(MonoAotCrossDir)"
Mode="$(_AotMode)"
OutputDir="$(_MobileIntermediateOutputPath)"
Mode="Full"
OutputType="$(_AotOutputType)"
Assemblies="@(AotInputAssemblies)"
AotModulesTablePath="$(_AotModulesTablePath)"
ToolPrefix="$(_AotToolPrefix)"
LibraryFormat="$(_AotLibraryFormat)"
IntermediateOutputPath="$(IntermediateOutputPath)"
UseLLVM="$(UseLLVM)"
LLVMPath="$(MonoAotCrossDir)">
ToolPrefix="$(_ToolPrefixPath)"
UseAotDataFile="false"
UseLLVM="$(UseLLVM)">
<Output TaskParameter="CompiledAssemblies" ItemName="BundleAssemblies" />
</MonoAOTCompiler>

Expand Down
1 change: 0 additions & 1 deletion src/mono/sample/Android/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,5 @@ run:
/p:RunActivity=false \
'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

clean:
rm -rf ../../../../artifacts/bin/AndroidSampleApp
16 changes: 15 additions & 1 deletion src/tasks/AotCompilerTask/MonoAOTCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,11 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task
/// </summary>
public string? ToolPrefix { get; set; }

/// <summary>
/// Prepends a prefix to the name of the assembler (as) tool ran by the AOT compiler.
/// </summary>
public string? AsPrefix { get; set; }

/// <summary>
/// Path to the directory where msym artifacts are stored.
/// </summary>
Expand Down Expand Up @@ -723,6 +728,11 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st
aotArgs.Add($"tool-prefix={ToolPrefix}");
}

if (!string.IsNullOrEmpty(AsPrefix))
{
aotArgs.Add($"as-prefix={AsPrefix}");
}

string assemblyFilename = Path.GetFileName(assembly);

if (isDedup)
Expand Down Expand Up @@ -845,7 +855,11 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st
ProxyFile proxyFile = _cache.NewFile(llvmObjectFile);
proxyFiles.Add(proxyFile);
aotArgs.Add($"llvm-outfile={proxyFile.TempFile}");
aotAssembly.SetMetadata("LlvmObjectFile", proxyFile.TargetFile);

if (UseStaticLinking)
{
aotAssembly.SetMetadata("LlvmObjectFile", proxyFile.TargetFile);
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions src/tasks/Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ public static void DirectoryCopy(string sourceDir, string destDir, Func<string,
}
#endif

public static bool IsWindows()
{
#if NETCOREAPP
return OperatingSystem.IsWindows();
#else
return true;
#endif
}

public static bool IsManagedAssembly(string filePath)
{
if (!File.Exists(filePath))
Expand Down
16 changes: 16 additions & 0 deletions src/tasks/MobileBuildTasks/Android/Ndk/AndroidArch.cs
Original file line number Diff line number Diff line change
@@ -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;

namespace Microsoft.Android.Build.Ndk
{
public sealed class AndroidArch(string archName, string abi, string triple)
{
public string ArchName { get; set; } = archName;

public string Abi { get; set; } = abi;

public string Triple { get; set; } = triple;
}
}
Loading

0 comments on commit b3d2503

Please sign in to comment.