-
Notifications
You must be signed in to change notification settings - Fork 569
Expand file tree
/
Copy pathGenerateMainAndroidManifest.cs
More file actions
145 lines (121 loc) · 6.21 KB
/
GenerateMainAndroidManifest.cs
File metadata and controls
145 lines (121 loc) · 6.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#nullable enable
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Xamarin.Android.Tools;
namespace Xamarin.Android.Tasks;
public class GenerateMainAndroidManifest : AndroidTask
{
public override string TaskPrefix => "GMM";
[Output]
public string []? AdditionalProviderSources { get; set; }
[Required]
public string AndroidRuntime { get; set; } = "";
public string? AndroidSdkDir { get; set; }
[Required]
public string AndroidApiLevel { get; set; } = "";
public string? ApplicationJavaClass { get; set; }
public string? ApplicationLabel { get; set; }
public string? BundledWearApplicationName { get; set; }
public string? CheckedBuild { get; set; }
public bool Debug { get; set; }
public bool EmbedAssemblies { get; set; }
public bool EnableNativeRuntimeLinking { get; set; }
[Required]
public string IntermediateOutputDirectory { get; set; } = "";
public string []? ManifestPlaceholders { get; set; }
public string? ManifestTemplate { get; set; }
public string? MergedAndroidManifestOutput { get; set; }
public string []? MergedManifestDocuments { get; set; }
public bool MultiDex { get; set; }
public bool NeedsInternet { get; set; }
public string? PackageName { get; set; }
[Required]
public ITaskItem [] ResolvedUserAssemblies { get; set; } = [];
[Required]
public string [] SupportedAbis { get; set; } = [];
public string? SupportedOSPlatformVersion { get; set; }
public string? VersionCode { get; set; }
public string? VersionName { get; set; }
AndroidRuntime androidRuntime;
public override bool RunTask ()
{
// Retrieve the stored NativeCodeGenState (and remove it from the cache)
var nativeCodeGenStates = BuildEngine4.UnregisterTaskObjectAssemblyLocal<ConcurrentDictionary<AndroidTargetArch, NativeCodeGenState>> (
MonoAndroidHelper.GetProjectBuildSpecificTaskObjectKey (GenerateJavaStubs.NativeCodeGenStateRegisterTaskKey, WorkingDirectory, IntermediateOutputDirectory),
RegisteredTaskObjectLifetime.Build
);
if (nativeCodeGenStates is null)
throw new InvalidOperationException ($"Internal error: {nameof (NativeCodeGenState)} not found");
// We only need the first architecture, since this task is architecture-agnostic
var templateCodeGenState = nativeCodeGenStates.First ().Value;
var userAssembliesPerArch = MonoAndroidHelper.GetPerArchAssemblies (ResolvedUserAssemblies, SupportedAbis, validate: true);
androidRuntime = MonoAndroidHelper.ParseAndroidRuntime (AndroidRuntime);
// Generate the merged manifest
var additionalProviders = MergeManifest (templateCodeGenState, GenerateJavaStubs.MaybeGetArchAssemblies (userAssembliesPerArch, templateCodeGenState.TargetArch));
AdditionalProviderSources = additionalProviders.ToArray ();
// We still need the NativeCodeGenState for later tasks, but we're going to transfer
// it to a new object that doesn't require holding open Cecil AssemblyDefinitions.
var nativeCodeGenStateObject = MarshalMethodCecilAdapter.GetNativeCodeGenStateCollection (Log, nativeCodeGenStates);
if (nativeCodeGenStateObject is null)
throw new InvalidOperationException ($"Internal error: {nameof (NativeCodeGenStateCollection)} not created");
Log.LogDebugMessage ($"Saving {nameof (NativeCodeGenStateObject)} to {nameof (GenerateJavaStubs.NativeCodeGenStateObjectRegisterTaskKey)}");
BuildEngine4.RegisterTaskObjectAssemblyLocal (MonoAndroidHelper.GetProjectBuildSpecificTaskObjectKey (GenerateJavaStubs.NativeCodeGenStateObjectRegisterTaskKey, WorkingDirectory, IntermediateOutputDirectory), nativeCodeGenStateObject, RegisteredTaskObjectLifetime.Build);
// Dispose the Cecil resolvers so the assemblies are closed.
Log.LogDebugMessage ($"Disposing all {nameof (NativeCodeGenState)}.{nameof (NativeCodeGenState.Resolver)}");
foreach (var state in nativeCodeGenStates.Values) {
state.Resolver.Dispose ();
}
if (Log.HasLoggedErrors && MergedAndroidManifestOutput != null) {
// Ensure that on a rebuild, we don't *skip* the `_GenerateJavaStubs` target,
// by ensuring that the target outputs have been deleted.
Files.DeleteFile (MergedAndroidManifestOutput, Log);
}
return !Log.HasLoggedErrors;
}
IList<string> MergeManifest (NativeCodeGenState codeGenState, Dictionary<string, ITaskItem> userAssemblies)
{
string targetSdkVersion = AndroidApiLevel;
if (MonoAndroidHelper.TryParseApiLevel (targetSdkVersion, out Version version)) {
targetSdkVersion = version.Major.ToString (CultureInfo.InvariantCulture);
}
var manifest = new ManifestDocument (ManifestTemplate) {
PackageName = PackageName,
VersionName = VersionName,
ApplicationLabel = ApplicationLabel ?? PackageName,
Placeholders = ManifestPlaceholders,
Resolver = codeGenState.Resolver,
SdkDir = AndroidSdkDir,
TargetSdkVersion = targetSdkVersion,
MinSdkVersion = MonoAndroidHelper.ConvertSupportedOSPlatformVersionToApiLevel (SupportedOSPlatformVersion).ToString (),
Debug = Debug,
MultiDex = MultiDex,
NeedsInternet = NeedsInternet,
AndroidRuntime = androidRuntime,
};
// Only set manifest.VersionCode if there is no existing value in AndroidManifest.xml.
if (manifest.HasVersionCode) {
Log.LogDebugMessage ($"Using existing versionCode in: {ManifestTemplate}");
} else if (!VersionCode.IsNullOrEmpty ()) {
manifest.VersionCode = VersionCode;
}
manifest.Assemblies.AddRange (userAssemblies.Values.Select (item => item.ItemSpec));
if (!String.IsNullOrWhiteSpace (CheckedBuild)) {
// We don't validate CheckedBuild value here, this will be done in BuildApk. We just know that if it's
// on then we need android:debuggable=true and android:extractNativeLibs=true
manifest.ForceDebuggable = true;
manifest.ForceExtractNativeLibs = true;
}
IList<string> additionalProviders = manifest.Merge (Log, codeGenState.TypeCache, codeGenState.AllJavaTypes, ApplicationJavaClass, EmbedAssemblies, BundledWearApplicationName, MergedManifestDocuments);
// Only write the new manifest if it actually changed
if (manifest.SaveIfChanged (Log, MergedAndroidManifestOutput)) {
Log.LogDebugMessage ($"Saving: {MergedAndroidManifestOutput}");
}
return additionalProviders;
}
}