Skip to content

Commit c33aadb

Browse files
authored
Revert "[Xamarin.Android.Build.Tasks] don't use so many temp files (#2505)"
This reverts commit b4c4f66.
1 parent b4c4f66 commit c33aadb

File tree

7 files changed

+101
-324
lines changed

7 files changed

+101
-324
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/GenerateJavaStubs.cs

Lines changed: 91 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -70,23 +70,17 @@ public class GenerateJavaStubs : Task
7070

7171
public override bool Execute ()
7272
{
73-
var temp = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
7473
try {
75-
Directory.CreateDirectory (temp);
76-
7774
// We're going to do 3 steps here instead of separate tasks so
7875
// we can share the list of JLO TypeDefinitions between them
7976
using (var res = new DirectoryAssemblyResolver (this.CreateTaskLogger (), loadDebugSymbols: true)) {
80-
Run (res, temp);
77+
Run (res);
8178
}
82-
} catch (XamarinAndroidException e) {
79+
}
80+
catch (XamarinAndroidException e) {
8381
Log.LogCodedError (string.Format ("XA{0:0000}", e.Code), e.MessageWithoutCode);
8482
if (MonoAndroidHelper.LogInternalExceptions)
8583
Log.LogMessage (e.ToString ());
86-
} finally {
87-
// Delete our temp directory
88-
if (Directory.Exists (temp))
89-
Directory.Delete (temp, true);
9084
}
9185

9286
if (Log.HasLoggedErrors) {
@@ -101,10 +95,12 @@ public override bool Execute ()
10195
return !Log.HasLoggedErrors;
10296
}
10397

104-
void Run (DirectoryAssemblyResolver res, string temp)
98+
void Run (DirectoryAssemblyResolver res)
10599
{
106100
PackageNamingPolicy pnp;
107101
JavaNativeTypeManager.PackageNamingPolicy = Enum.TryParse (PackageNamingPolicy, out pnp) ? pnp : PackageNamingPolicyEnum.LowercaseHash;
102+
var temp = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName ());
103+
Directory.CreateDirectory (temp);
108104

109105
foreach (var dir in FrameworkDirectories) {
110106
if (Directory.Exists (dir.ItemSpec))
@@ -115,10 +111,9 @@ void Run (DirectoryAssemblyResolver res, string temp)
115111

116112
// Put every assembly we'll need in the resolver
117113
foreach (var assembly in ResolvedAssemblies) {
118-
var assemblyFullPath = Path.GetFullPath (assembly.ItemSpec);
119-
res.Load (assemblyFullPath);
114+
res.Load (Path.GetFullPath (assembly.ItemSpec));
120115
if (MonoAndroidHelper.FrameworkAttributeLookupTargets.Any (a => Path.GetFileName (assembly.ItemSpec) == a))
121-
selectedWhitelistAssemblies.Add (assemblyFullPath);
116+
selectedWhitelistAssemblies.Add (Path.GetFullPath (assembly.ItemSpec));
122117
}
123118

124119
// However we only want to look for JLO types in user code
@@ -138,62 +133,72 @@ void Run (DirectoryAssemblyResolver res, string temp)
138133
var java_types = all_java_types.Where (t => !JavaTypeScanner.ShouldSkipJavaCallableWrapperGeneration (t));
139134

140135
// Step 2 - Generate Java stub code
141-
var success = Generator.CreateJavaSources (
136+
var keep_going = Generator.CreateJavaSources (
142137
Log,
143138
java_types,
144139
temp,
145140
ApplicationJavaClass,
146141
UseSharedRuntime,
147142
int.Parse (AndroidSdkPlatform) <= 10,
148143
ResolvedAssemblies.Any (assembly => Path.GetFileName (assembly.ItemSpec) == "Mono.Android.Export.dll"));
149-
if (!success)
150-
return;
144+
145+
var temp_map_file = Path.Combine (temp, "acw-map.temp");
151146

152147
// We need to save a map of .NET type -> ACW type for resource file fixups
153148
var managed = new Dictionary<string, TypeDefinition> ();
154149
var java = new Dictionary<string, TypeDefinition> ();
155-
using (var stream = new MemoryStream ())
156-
using (var acw_map = new StreamWriter (stream)) {
157-
foreach (var type in java_types) {
158-
string managedKey = type.FullName.Replace ('/', '.');
159-
string javaKey = JavaNativeTypeManager.ToJniName (type).Replace ('/', '.');
160-
161-
acw_map.WriteLine ("{0};{1}", type.GetPartialAssemblyQualifiedName (), javaKey);
162-
163-
TypeDefinition conflict;
164-
if (managed.TryGetValue (managedKey, out conflict)) {
165-
Log.LogWarning (
166-
"Duplicate managed type found! Mappings between managed types and Java types must be unique. " +
167-
"First Type: '{0}'; Second Type: '{1}'.",
168-
conflict.GetAssemblyQualifiedName (),
169-
type.GetAssemblyQualifiedName ());
170-
Log.LogWarning (
171-
"References to the type '{0}' will refer to '{1}'.",
172-
managedKey, conflict.GetAssemblyQualifiedName ());
173-
continue;
174-
}
175-
if (java.TryGetValue (javaKey, out conflict)) {
176-
Log.LogError (
177-
"Duplicate Java type found! Mappings between managed types and Java types must be unique. " +
178-
"First Type: '{0}'; Second Type: '{1}'",
179-
conflict.GetAssemblyQualifiedName (),
180-
type.GetAssemblyQualifiedName ());
181-
success = false;
182-
continue;
183-
}
184-
managed.Add (managedKey, type);
185-
java.Add (javaKey, type);
186-
acw_map.WriteLine ("{0};{1}", managedKey, javaKey);
187-
acw_map.WriteLine ("{0};{1}", JavaNativeTypeManager.ToCompatJniName (type).Replace ('/', '.'), javaKey);
150+
var acw_map = new StreamWriter (temp_map_file);
151+
152+
foreach (var type in java_types) {
153+
string managedKey = type.FullName.Replace ('/', '.');
154+
string javaKey = JavaNativeTypeManager.ToJniName (type).Replace ('/', '.');
155+
156+
acw_map.WriteLine ("{0};{1}", type.GetPartialAssemblyQualifiedName (), javaKey);
157+
158+
TypeDefinition conflict;
159+
if (managed.TryGetValue (managedKey, out conflict)) {
160+
Log.LogWarning (
161+
"Duplicate managed type found! Mappings between managed types and Java types must be unique. " +
162+
"First Type: '{0}'; Second Type: '{1}'.",
163+
conflict.GetAssemblyQualifiedName (),
164+
type.GetAssemblyQualifiedName ());
165+
Log.LogWarning (
166+
"References to the type '{0}' will refer to '{1}'.",
167+
managedKey, conflict.GetAssemblyQualifiedName ());
168+
continue;
169+
}
170+
if (java.TryGetValue (javaKey, out conflict)) {
171+
Log.LogError (
172+
"Duplicate Java type found! Mappings between managed types and Java types must be unique. " +
173+
"First Type: '{0}'; Second Type: '{1}'",
174+
conflict.GetAssemblyQualifiedName (),
175+
type.GetAssemblyQualifiedName ());
176+
keep_going = false;
177+
continue;
188178
}
179+
managed.Add (managedKey, type);
180+
java.Add (javaKey, type);
181+
acw_map.WriteLine ("{0};{1}", managedKey, javaKey);
182+
acw_map.WriteLine ("{0};{1}", JavaNativeTypeManager.ToCompatJniName (type).Replace ('/', '.'), javaKey);
183+
}
184+
185+
acw_map.Close ();
189186

190-
acw_map.Flush ();
191-
MonoAndroidHelper.CopyIfStreamChanged (stream, AcwMapFile);
187+
//The previous steps found an error, so we must abort and not generate any further output
188+
//We must do so subsequent unchanged builds fail too.
189+
if (!keep_going) {
190+
File.Delete (temp_map_file);
191+
return;
192192
}
193193

194+
MonoAndroidHelper.CopyIfChanged (temp_map_file, AcwMapFile);
195+
196+
try { File.Delete (temp_map_file); } catch (Exception) { }
197+
194198
// Only overwrite files if the contents actually changed
195199
foreach (var file in Directory.GetFiles (temp, "*", SearchOption.AllDirectories)) {
196-
var dest = Path.Combine (OutputDirectory, "src", file.Substring (temp.Length + 1));
200+
var dest = Path.GetFullPath (Path.Combine (OutputDirectory, "src", file.Substring (temp.Length + 1)));
201+
197202
MonoAndroidHelper.CopyIfChanged (file, dest);
198203
}
199204

@@ -214,24 +219,38 @@ void Run (DirectoryAssemblyResolver res, string temp)
214219

215220
var additionalProviders = manifest.Merge (all_java_types, selectedWhitelistAssemblies, ApplicationJavaClass, EmbedAssemblies, BundledWearApplicationName, MergedManifestDocuments);
216221

217-
using (var stream = new MemoryStream ()) {
218-
manifest.Save (stream);
222+
var temp_manifest = Path.Combine (temp, "AndroidManifest.xml");
223+
var real_manifest = Path.GetFullPath (MergedAndroidManifestOutput);
219224

220-
// Only write the new manifest if it actually changed
221-
MonoAndroidHelper.CopyIfStreamChanged (stream, MergedAndroidManifestOutput);
222-
}
225+
manifest.Save (temp_manifest);
226+
227+
// Only write the new manifest if it actually changed
228+
MonoAndroidHelper.CopyIfChanged (temp_manifest, real_manifest);
223229

224230
// Create additional runtime provider java sources.
225231
string providerTemplateFile = UseSharedRuntime ? "MonoRuntimeProvider.Shared.java" : "MonoRuntimeProvider.Bundled.java";
226-
string providerTemplate = GetResource<JavaCallableWrapperGenerator> (providerTemplateFile);
232+
string providerTemplate = new StreamReader (typeof (JavaCallableWrapperGenerator).Assembly.GetManifestResourceStream (providerTemplateFile)).ReadToEnd ();
227233

228234
foreach (var provider in additionalProviders) {
229-
var contents = providerTemplate.Replace ("MonoRuntimeProvider", provider);
230-
var real_provider = Path.Combine (OutputDirectory, "src", "mono", provider + ".java");
231-
MonoAndroidHelper.CopyIfStringChanged (contents, real_provider);
235+
var temp_provider = Path.Combine (temp, provider + ".java");
236+
File.WriteAllText (temp_provider, providerTemplate.Replace ("MonoRuntimeProvider", provider));
237+
var real_provider_dir = Path.GetFullPath (Path.Combine (OutputDirectory, "src", "mono"));
238+
Directory.CreateDirectory (real_provider_dir);
239+
var real_provider = Path.Combine (real_provider_dir, provider + ".java");
240+
MonoAndroidHelper.CopyIfChanged (temp_provider, real_provider);
232241
}
233242

234243
// Create additional application java sources.
244+
245+
Action<string,string,string,Func<string,string>> save = (resource, filename, destDir, applyTemplate) => {
246+
string temp_file = Path.Combine (temp, filename);
247+
string template = applyTemplate (new StreamReader (typeof (GenerateJavaStubs).Assembly.GetManifestResourceStream (resource)).ReadToEnd ());
248+
File.WriteAllText (temp_file, template);
249+
Directory.CreateDirectory (destDir);
250+
var real_file = Path.Combine (destDir, filename);
251+
MonoAndroidHelper.CopyIfChanged (temp_file, real_file);
252+
};
253+
235254
StringWriter regCallsWriter = new StringWriter ();
236255
regCallsWriter.WriteLine ("\t\t// Application and Instrumentation ACWs must be registered first.");
237256
foreach (var type in java_types) {
@@ -243,28 +262,17 @@ void Run (DirectoryAssemblyResolver res, string temp)
243262
}
244263
regCallsWriter.Close ();
245264

246-
var real_app_dir = Path.Combine (OutputDirectory, "src", "mono", "android", "app");
265+
var real_app_dir = Path.GetFullPath (Path.Combine (OutputDirectory, "src", "mono", "android", "app"));
247266
string applicationTemplateFile = "ApplicationRegistration.java";
248-
SaveResource (applicationTemplateFile, applicationTemplateFile, real_app_dir,
267+
save (applicationTemplateFile, applicationTemplateFile, real_app_dir,
249268
template => template.Replace ("// REGISTER_APPLICATION_AND_INSTRUMENTATION_CLASSES_HERE", regCallsWriter.ToString ()));
250269

251270
// Create NotifyTimeZoneChanges java sources.
252271
string notifyTimeZoneChangesFile = "NotifyTimeZoneChanges.java";
253-
SaveResource (notifyTimeZoneChangesFile, notifyTimeZoneChangesFile, real_app_dir, template => template);
254-
}
255-
256-
string GetResource <T> (string resource)
257-
{
258-
using (var stream = typeof (T).Assembly.GetManifestResourceStream (resource))
259-
using (var reader = new StreamReader (stream))
260-
return reader.ReadToEnd ();
261-
}
262-
263-
void SaveResource (string resource, string filename, string destDir, Func<string, string> applyTemplate)
264-
{
265-
string template = GetResource<GenerateJavaStubs> (resource);
266-
template = applyTemplate (template);
267-
MonoAndroidHelper.CopyIfStringChanged (template, Path.Combine (destDir, filename));
272+
save (notifyTimeZoneChangesFile, notifyTimeZoneChangesFile, real_app_dir, template => template);
273+
274+
// Delete our temp directory
275+
try { Directory.Delete (temp, true); } catch (Exception) { }
268276
}
269277

270278
void WriteTypeMappings (List<TypeDefinition> types)
@@ -279,10 +287,11 @@ void WriteTypeMappings (List<TypeDefinition> types)
279287

280288
void UpdateWhenChanged (string path, Action<Stream> generator)
281289
{
282-
using (var stream = new MemoryStream ()) {
283-
generator (stream);
284-
MonoAndroidHelper.CopyIfStreamChanged (stream, path);
285-
}
290+
var np = path + ".new";
291+
using (var o = File.OpenWrite (np))
292+
generator (o);
293+
MonoAndroidHelper.CopyIfChanged (np, path);
294+
File.Delete (np);
286295
}
287296
}
288297
}

src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceDesigner.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,12 @@ private void WriteFile (string file, CodeTypeDeclaration resources, string langu
239239
}
240240
}
241241
}
242-
243-
MonoAndroidHelper.CopyIfStringChanged (code, file);
242+
243+
var temp_o = Path.Combine (Path.GetDirectoryName (file), "__" + Path.GetFileName (file) + ".new");
244+
using (TextWriter o = File.CreateText (temp_o))
245+
o.Write (code);
246+
MonoAndroidHelper.CopyIfChanged (temp_o, file);
247+
try { File.Delete (temp_o); } catch (Exception) { }
244248
}
245249

246250
private void AddRename (string android, string user)

0 commit comments

Comments
 (0)