Remove MetadataLoadContext dependency from AndroidAppBuilder (#43339)
authorSteve Pfister <steveisok@users.noreply.github.com>
Tue, 13 Oct 2020 20:21:41 +0000 (16:21 -0400)
committerGitHub <noreply@github.com>
Tue, 13 Oct 2020 20:21:41 +0000 (16:21 -0400)
This will allow AndroidAppBuilder to be packaged without having unnecessary dependencies.

eng/testing/tests.mobile.targets
src/mono/mono.proj
src/mono/netcore/sample/Android/AndroidSampleApp.csproj
src/mono/netcore/sample/Android/Makefile
tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.cs
tools-local/tasks/mobile.tasks/AndroidAppBuilder/AndroidAppBuilder.csproj
tools-local/tasks/mobile.tasks/AndroidAppBuilder/ApkBuilder.cs
tools-local/tasks/mobile.tasks/AndroidAppBuilder/AssemblyResolver.cs [deleted file]

index 07ec891..2f0d799 100644 (file)
@@ -28,6 +28,9 @@
              AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)" />
 
   <Target Condition="'$(TargetOS)' == 'Android'" Name="BundleTestAndroidApp">
+    <Error Condition="!Exists('$(MicrosoftNetCoreAppRuntimePackRidDir)')" Text="MicrosoftNetCoreAppRuntimePackRidDir=$(MicrosoftNetCoreAppRuntimePackRidDir) doesn't exist" />
+
+    <!-- TEMP: consume OpenSSL binaries from external sources via env. variables.-->
     <PropertyGroup>
       <AndroidAbi Condition="'$(TargetArchitecture)' == 'arm64'">arm64-v8a</AndroidAbi>
       <AndroidAbi Condition="'$(TargetArchitecture)' == 'arm'">armeabi-v7a</AndroidAbi>
@@ -35,9 +38,6 @@
       <AndroidAbi Condition="'$(TargetArchitecture)' == 'x86'">x86</AndroidAbi>
     </PropertyGroup>
 
-    <Error Condition="!Exists('$(MicrosoftNetCoreAppRuntimePackRidDir)')" Text="MicrosoftNetCoreAppRuntimePackRidDir=$(MicrosoftNetCoreAppRuntimePackRidDir) doesn't exist" />
-
-    <!-- TEMP: consume OpenSSL binaries from external sources via env. variables -->
     <Copy Condition="'$(ANDROID_OPENSSL_AAR)' != ''"
           SourceFiles="$(ANDROID_OPENSSL_AAR)\prefab\modules\crypto\libs\android.$(AndroidAbi)\libcrypto.so"
           DestinationFolder="$(PublishDir)" SkipUnchangedFiles="true"/>
@@ -49,7 +49,7 @@
 
     <RemoveDir Directories="$(BundleDir)" />
     <AndroidAppBuilderTask
-        Abi="$(AndroidAbi)"
+        RuntimeIdentifier="$(RuntimeIdentifier)"
         ProjectName="$(AssemblyName)"
         MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackNativeDir)include\mono-2.0"
         MainLibraryFileName="AndroidTestRunner.dll"
index a7100ae..165861a 100644 (file)
@@ -6,7 +6,7 @@
   -->
 
   <PropertyGroup>
-    <MonoEnableCMake Condition="'$(TargetsBrowser)' == 'true' or '$(TargetsOSX)' == 'true' or '$(TargetsAndroid)' == 'true'">true</MonoEnableCMake>
+    <MonoEnableCMake Condition="'$(TargetsBrowser)' == 'true' or '$(TargetsOSX)' == 'true'">true</MonoEnableCMake>
     <MonoCrossDir Condition="'$(MonoCrossDir)' == '' and '$(ROOTFS_DIR)' != ''">$(ROOTFS_DIR)</MonoCrossDir>
     <MonoEnableInterpreter Condition="'$(MonoEnableInterpreter)' == ''">false</MonoEnableInterpreter>
     <ScriptExt Condition="'$(OS)' == 'Windows_NT'">.cmd</ScriptExt>
index c5949f7..3eddf9f 100644 (file)
@@ -4,53 +4,44 @@
     <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
     <TargetFramework>$(NetCoreAppCurrent)</TargetFramework>
     <TargetArchitecture Condition="'$(TargetArchitecture)'==''">x64</TargetArchitecture>
-    <TargetOS>Android</TargetOS>
-    <MicrosoftNetCoreAppRuntimePackDir>$(ArtifactsBinDir)microsoft.netcore.app.runtime.android-$(TargetArchitecture)\$(Configuration)\runtimes\android-$(TargetArchitecture)\</MicrosoftNetCoreAppRuntimePackDir>
+    <EnableTargetingPackDownload>false</EnableTargetingPackDownload>
+    <RuntimeIdentifier>android-$(TargetArchitecture)</RuntimeIdentifier>
+    <PublishTrimmed Condition="'$(Configuration)' == 'Release'">true</PublishTrimmed>
+    <_TrimmerDefaultAction Condition="'$(Configuration)' == 'Release'">link</_TrimmerDefaultAction>
+    <Optimized Condition="'$(Configuration)' == 'Release'">True</Optimized>
+    <MicrosoftNetCoreAppRuntimePackDir>$(ArtifactsBinDir)microsoft.netcore.app.runtime.$(RuntimeIdentifier)\$(Configuration)\runtimes\android-$(TargetArchitecture)\</MicrosoftNetCoreAppRuntimePackDir>
     <NoWarn>$(NoWarn),CA1050</NoWarn>
   </PropertyGroup>
 
-  <Target Name="RebuildAndroidAppBuilder">
+  <!-- Redirect 'dotnet publish' to in-tree runtime pack -->
+  <Target Name="TrickRuntimePackLocation" AfterTargets="ProcessFrameworkReferences">
     <ItemGroup>
-      <AndroidAppBuilderProject Include="$(RepoTasksDir)mobile.tasks\AndroidAppBuilder\AndroidAppBuilder.csproj" />
+      <RuntimePack>
+        <PackageDirectory>$(ArtifactsBinDir)microsoft.netcore.app.runtime.$(RuntimeIdentifier)\$(Configuration)</PackageDirectory>
+      </RuntimePack>
     </ItemGroup>
-    <MSBuild Projects="@(AndroidAppBuilderProject)"
-             Properties="Configuration=$(Configuration);MSBuildRestoreSessionId=$([System.Guid]::NewGuid())"
-             Targets="Restore"/>
-    <MSBuild Projects="@(AndroidAppBuilderProject)"
-             Properties="Configuration=$(Configuration)"
-             Targets="Build;Publish"/>
+    <Message Text="Packaged ID: %(RuntimePack.PackageDirectory)" Importance="high" />
   </Target>
 
   <UsingTask TaskName="AndroidAppBuilderTask" AssemblyFile="$(AndroidAppBuilderTasksAssemblyPath)"/>
 
-  <Target Name="BuildApp" DependsOnTargets="RebuildAndroidAppBuilder;Build">
+  <Target Name="BuildApp" AfterTargets="CopyFilesToPublishDirectory">
     <PropertyGroup>
-      <AndroidAbi Condition="'$(Platform)'=='arm64'">arm64-v8a</AndroidAbi>
-      <AndroidAbi Condition="'$(Platform)'=='arm'">armeabi-v7a</AndroidAbi>
-      <AndroidAbi Condition="'$(Platform)'=='x64'">x86_64</AndroidAbi>
-      <AndroidAbi Condition="'$(AndroidAbi)'==''">$(Platform)</AndroidAbi>
       <StripDebugSymbols>False</StripDebugSymbols>
       <StripDebugSymbols Condition="'$(Configuration)' == 'Release'">True</StripDebugSymbols>
       <AdbTool>$(ANDROID_SDK_ROOT)\platform-tools\adb</AdbTool>
       <ApkDir>$(OutputPath)apk\</ApkDir>
     </PropertyGroup>
 
-    <ItemGroup>
-      <AssemblySearchPaths Include="$(OutputPath)" />
-      <AssemblySearchPaths Include="$(MicrosoftNetCoreAppRuntimePackDir)native"/>
-      <AssemblySearchPaths Include="$(MicrosoftNetCoreAppRuntimePackDir)lib\$(NetCoreAppCurrent)"/>
-    </ItemGroup>
-
     <RemoveDir Directories="$(ApkDir)" />
 
     <AndroidAppBuilderTask
+        RuntimeIdentifier="$(RuntimeIdentifier)"
         SourceDir="$(OutputPath)"
-        Abi="$(AndroidAbi)"
         ProjectName="HelloAndroid"
         MonoRuntimeHeaders="$(MicrosoftNetCoreAppRuntimePackDir)\native\include\mono-2.0"
         MainLibraryFileName="$(AssemblyName).dll"
         StripDebugSymbols="$(StripDebugSymbols)"
-        AssemblySearchPaths="@(AssemblySearchPaths)"
         OutputDir="$(ApkDir)">
         <Output TaskParameter="ApkBundlePath" PropertyName="ApkBundlePath" />
         <Output TaskParameter="ApkPackageId" PropertyName="ApkPackageId" />
index 48aeb1f..0ee5290 100644 (file)
@@ -8,11 +8,10 @@ runtimepack:
        ../../../../.././build.sh Mono+Libs -os Android -arch $(MONO_ARCH) -c $(MONO_CONFIG)
 
 run:
-       $(DOTNET) build \
+       $(DOTNET) publish \
        /p:TargetArchitecture=$(MONO_ARCH) \
-       /p:TargetOS=Android \
        /p:Configuration=$(MONO_CONFIG) \
        /p:DeployAndRun=true
 
 clean:
-       rm -rf bin
+       rm -rf ../../../../../artifacts/bin/AndroidSampleApp
index 1da046f..c837d89 100644 (file)
@@ -12,10 +12,6 @@ public class AndroidAppBuilderTask : Task
     [Required]
     public string SourceDir { get; set; } = ""!;
 
-    public ITaskItem[]? AssemblySearchPaths { get; set; }
-
-    public ITaskItem[]? ExtraAssemblies { get; set; }
-
     [Required]
     public string MonoRuntimeHeaders { get; set; } = ""!;
 
@@ -24,11 +20,8 @@ public class AndroidAppBuilderTask : Task
     /// </summary>
     public string MainLibraryFileName { get; set; } = ""!;
 
-    /// <summary>
-    /// Target arch, can be 'x86', 'x86_64', 'armeabi-v7a' or 'arm64-v8a'
-    /// </summary>
     [Required]
-    public string Abi { get; set; } = ""!;
+    public string RuntimeIdentifier { get; set; } = ""!;
 
     public string? ProjectName { get; set; }
 
@@ -56,6 +49,8 @@ public class AndroidAppBuilderTask : Task
     {
         Utils.Logger = Log;
 
+        string abi = DetermineAbi();
+
         var apkBuilder = new ApkBuilder();
         apkBuilder.ProjectName = ProjectName;
         apkBuilder.OutputDir = OutputDir;
@@ -65,10 +60,25 @@ public class AndroidAppBuilderTask : Task
         apkBuilder.BuildApiLevel = BuildApiLevel;
         apkBuilder.BuildToolsVersion = BuildToolsVersion;
         apkBuilder.StripDebugSymbols = StripDebugSymbols;
-        apkBuilder.AssemblySearchPaths = AssemblySearchPaths?.Select(a => a.ItemSpec)?.ToArray();
-        apkBuilder.ExtraAssemblies = ExtraAssemblies?.Select(a => a.ItemSpec)?.ToArray();
-        (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(SourceDir, Abi, MainLibraryFileName, MonoRuntimeHeaders);
+        (ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(SourceDir, abi, MainLibraryFileName, MonoRuntimeHeaders);
 
         return true;
     }
+
+    private string DetermineAbi()
+    {
+        switch (RuntimeIdentifier)
+        {
+            case "android-x86":
+                return "x86";
+            case "android-x64":
+                return "x86_64";
+            case "android-arm":
+                return "armeabi-v7a";
+            case "android-arm64":
+                return "arm64-v8a";
+            default:
+                throw new ArgumentException(RuntimeIdentifier + " is not supported for Android");
+        }
+    }
 }
index da39656..05a73a0 100644 (file)
     <PackageReference Include="Microsoft.Build.Framework" Version="$(RefOnlyMicrosoftBuildFrameworkVersion)" />
     <PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(RefOnlyMicrosoftBuildTasksCoreVersion)" />
     <PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(RefOnlyMicrosoftBuildUtilitiesCoreVersion)" />
-    <PackageReference Include="System.Reflection.MetadataLoadContext" Version="4.7.1" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="ApkBuilder.cs" />
     <Compile Include="AndroidAppBuilder.cs" />
-    <Compile Include="AssemblyResolver.cs" />
     <Compile Include="Utils.cs" />
   </ItemGroup>
 
index 5ae2e5a..919cf0a 100644 (file)
@@ -18,8 +18,6 @@ public class ApkBuilder
     public string? BuildToolsVersion { get; set; }
     public string? OutputDir { get; set; }
     public bool StripDebugSymbols { get; set; }
-    public string[]? AssemblySearchPaths { get; set; }
-    public string[]? ExtraAssemblies { get; set; }
 
     public (string apk, string packageId) BuildApk(
         string sourceDir, string abi, string entryPointLib, string monoRuntimeHeaders)
@@ -102,41 +100,6 @@ public class ApkBuilder
             extensionsToIgnore.Add(".dbg");
         }
 
-        var assembliesToResolve = new List<string>();
-
-        if (!string.IsNullOrEmpty(entryPointLibPath))
-                assembliesToResolve.Add(entryPointLibPath);
-
-        if (ExtraAssemblies != null)
-            assembliesToResolve.AddRange(ExtraAssemblies);
-
-        // try to resolve dependencies of entryPointLib + ExtraAssemblies from AssemblySearchPaths
-        // and copy them to sourceDir
-        if (AssemblySearchPaths?.Length > 0)
-        {
-            string[] resolvedDependencies = AssemblyResolver.ResolveDependencies(assembliesToResolve.ToArray(), AssemblySearchPaths, true);
-            foreach (string resolvedDependency in resolvedDependencies)
-            {
-                string destination = Path.Combine(sourceDir, Path.GetFileName(resolvedDependency));
-                if (!File.Exists(destination))
-                    File.Copy(resolvedDependency, destination);
-            }
-        }
-        else
-        {
-            AssemblySearchPaths = new[] {OutputDir};
-        }
-
-        // copy all native libs from AssemblySearchPaths to sourceDir
-        // TODO: skip some if not used by the app
-        string[] allFiles = AssemblySearchPaths.SelectMany(p => Directory.GetFiles(p, "*", SearchOption.AllDirectories)).ToArray();
-        foreach (string nativeLib in allFiles.Where(f => f.EndsWith(".a") || f.EndsWith(".so")))
-        {
-            string destination = Path.Combine(sourceDir, Path.GetFileName(nativeLib));
-            if (!File.Exists(destination))
-                File.Copy(nativeLib, destination);
-        }
-
         // Copy sourceDir to OutputDir/assets-tozip (ignore native files)
         // these files then will be zipped and copied to apk/assets/assets.zip
         Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets-tozip"), file =>
diff --git a/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AssemblyResolver.cs b/tools-local/tasks/mobile.tasks/AndroidAppBuilder/AssemblyResolver.cs
deleted file mode 100644 (file)
index ef01c0f..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-
-internal class AssemblyResolver : MetadataAssemblyResolver
-{
-    private string[] _searchPaths;
-
-    public AssemblyResolver(string[] searchPaths) => _searchPaths = searchPaths;
-
-    public static string[] ResolveDependencies(
-        string[] assembliesToResolve, string[] searchPaths, bool ignoreErrors = true)
-    {
-        var assemblies = new Dictionary<string, Assembly>();
-        var mlc = new MetadataLoadContext(new AssemblyResolver(searchPaths), "System.Private.CoreLib");
-        foreach (string assemblyPath in assembliesToResolve)
-        {
-            try
-            {
-                AddAssembly(mlc, mlc.LoadFromAssemblyPath(assemblyPath), assemblies, ignoreErrors);
-            }
-            catch (Exception)
-            {
-                if (!ignoreErrors)
-                {
-                    throw;
-                }
-            }
-        }
-        return assemblies.Values.Select(i => i.Location).Distinct().ToArray();
-    }
-
-    private static void AddAssembly(MetadataLoadContext mlc, Assembly assembly, Dictionary<string, Assembly> assemblies, bool ignoreErrors)
-    {
-        if (assemblies.ContainsKey(assembly.GetName().Name!))
-            return;
-        assemblies[assembly.GetName().Name!] = assembly;
-        foreach (AssemblyName name in assembly.GetReferencedAssemblies())
-        {
-            try
-            {
-                Assembly refAssembly = mlc.LoadFromAssemblyName(name);
-                AddAssembly(mlc, refAssembly, assemblies, ignoreErrors);
-            }
-            catch (Exception)
-            {
-                if (!ignoreErrors)
-                {
-                    throw;
-                }
-            }
-        }
-    }
-
-    public override Assembly? Resolve(MetadataLoadContext context, AssemblyName assemblyName)
-    {
-        string name = assemblyName.Name!;
-        foreach (string dir in _searchPaths)
-        {
-            string path = Path.Combine(dir, name + ".dll");
-            if (File.Exists(path))
-                return context.LoadFromAssemblyPath(path);
-        }
-        return null;
-    }
-}