Skip to content

Commit fa6814d

Browse files
[Xamarin.Android.Build.Tasks] remove the linksrc directory
I've removed various MSBuild targets that copy assemblies into the `obj\Debug\linksrc` directory, and instead just use `@(ResolvedUserAssemblies)` or `@(ResolvedAssemblies)` where appropriate. Things seem to *work*, I can build and deploy `samples\HelloWorld` and the Xamarin.Forms app in this repo. Let's see what breaks? The size of `tests\Xamarin.Forms-Performance-Integration\Droid\obj\` is improved dramatically: Before: 184.27 MB After: 111.74 MB ~73MB savings. These MSBuild tasks were completely removed: 3 ms _CopyMdbFiles 1 calls 43 ms _CopyPdbFiles 1 calls 127 ms _CopyIntermediateAssemblies 1 calls I will need to retest this on a slower machine where I'm seeing Windows Defender have an impact on build times.
1 parent 1bb9b02 commit fa6814d

File tree

7 files changed

+100
-118
lines changed

7 files changed

+100
-118
lines changed

src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/Linker.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ static Pipeline CreatePipeline (LinkerOptions options)
6262

6363
if (options.LinkNone) {
6464
pipeline.AppendStep (new FixAbstractMethodsStep ());
65-
pipeline.AppendStep (new OutputStep ());
65+
pipeline.AppendStep (new OutputStepWithTimestamps ());
6666
return pipeline;
6767
}
6868

@@ -117,7 +117,7 @@ static Pipeline CreatePipeline (LinkerOptions options)
117117
pipeline.AppendStep (new StripEmbeddedLibraries ());
118118
// end monodroid specific
119119
pipeline.AppendStep (new RegenerateGuidStep ());
120-
pipeline.AppendStep (new OutputStep ());
120+
pipeline.AppendStep (new OutputStepWithTimestamps ());
121121

122122
return pipeline;
123123
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
using System.IO;
2+
using Mono.Cecil;
3+
using Mono.Cecil.Cil;
4+
using Mono.Linker.Steps;
5+
using Xamarin.Android.Tools;
6+
7+
namespace MonoDroid.Tuner
8+
{
9+
/// <summary>
10+
/// A subclass of OutputStep that overrides CopyAssembly and timestamps files properly with Files.CopyIfChanged
11+
/// * original source from: https://github.com/mono/linker/blob/aa65acca5e41fbc1f8f597799381b853049704ff/src/linker/Linker.Steps/OutputStep.cs#L198-L231
12+
/// </summary>
13+
class OutputStepWithTimestamps : OutputStep
14+
{
15+
static FileInfo GetOriginalAssemblyFileInfo (AssemblyDefinition assembly)
16+
{
17+
return new FileInfo (assembly.MainModule.FileName);
18+
}
19+
20+
protected override void CopyAssembly (AssemblyDefinition assembly, string directory)
21+
{
22+
// Special case. When an assembly has embedded pdbs, link symbols is not enabled, and the assembly's action is copy,
23+
// we want to match the behavior of assemblies with the other symbol types and end up with an assembly that does not have symbols.
24+
// In order to do that, we can't simply copy files. We need to write the assembly without symbols
25+
if (assembly.MainModule.HasSymbols && !Context.LinkSymbols && assembly.MainModule.SymbolReader is EmbeddedPortablePdbReader) {
26+
WriteAssembly (assembly, directory, new WriterParameters ());
27+
return;
28+
}
29+
30+
FileInfo fi = GetOriginalAssemblyFileInfo (assembly);
31+
string target = Path.GetFullPath (Path.Combine (directory, fi.Name));
32+
string source = fi.FullName;
33+
if (source == target)
34+
return;
35+
36+
Files.CopyIfChanged (source, target);
37+
38+
if (!Context.LinkSymbols)
39+
return;
40+
41+
var mdb = source + ".mdb";
42+
if (File.Exists (mdb))
43+
Files.CopyIfChanged (mdb, target + ".mdb");
44+
45+
var pdb = Path.ChangeExtension (source, "pdb");
46+
if (File.Exists (pdb))
47+
Files.CopyIfChanged (pdb, Path.ChangeExtension (target, "pdb"));
48+
}
49+
}
50+
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs

Lines changed: 19 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -503,11 +503,9 @@ public void CheckTimestamps ([Values (true, false)] bool isRelease)
503503
// Xamarin.Android unless fastdev is enabled.
504504
foreach (var file in new [] { "typemap.mj", "typemap.jm" }) {
505505
var info = new FileInfo (Path.Combine (intermediate, "android", file));
506-
if (!info.Exists) {
507-
Assert.Ignore ($"{info.Name} does not exist, timestamp check skipped");
508-
continue;
506+
if (info.Exists) {
507+
Assert.IsTrue (info.LastWriteTimeUtc > start, $"`{file}` is older than `{start}`, with a timestamp of `{info.LastWriteTimeUtc}`!");
509508
}
510-
Assert.IsTrue (info.LastWriteTimeUtc > start, $"`{file}` is older than `{start}`, with a timestamp of `{info.LastWriteTimeUtc}`!");
511509
}
512510

513511
//One last build with no changes
@@ -1186,12 +1184,6 @@ public void BuildBasicApplicationCheckMdbRepeatBuild ()
11861184
File.Exists (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android/assets/UnnamedProject.pdb")),
11871185
"UnnamedProject.dll.mdb must be copied to the Intermediate directory");
11881186
Assert.IsTrue (b.Build (proj), "second build failed");
1189-
Assert.IsTrue (
1190-
b.Output.IsTargetSkipped ("_CopyMdbFiles"),
1191-
"the _CopyMdbFiles target should be skipped");
1192-
Assert.IsTrue (
1193-
b.Output.IsTargetSkipped ("_CopyPdbFiles"),
1194-
"the _CopyPdbFiles target should be skipped");
11951187
Assert.IsTrue (
11961188
File.Exists (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android/assets/UnnamedProject.dll.mdb")) ||
11971189
File.Exists (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android/assets/UnnamedProject.pdb")),
@@ -1251,39 +1243,39 @@ public Class2 ()
12511243
Assert.IsTrue (libb.Build (lib), "Library1 Build should have succeeded.");
12521244
using (var b = CreateApkBuilder (Path.Combine (path, "App1"))) {
12531245
Assert.IsTrue (b.Build (proj), "App1 Build should have succeeded.");
1254-
var assetsPdb = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets", "Library1.pdb");
1255-
var linkDst = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linkdst", "Library1.pdb");
1256-
var linkSrc = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linksrc", "Library1.pdb");
1246+
var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);
1247+
var outputPath = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath);
1248+
var assetsPdb = Path.Combine (intermediate, "android", "assets", "Library1.pdb");
1249+
var linkDst = Path.Combine (intermediate, "linkdst", "Library1.pdb");
1250+
var binSrc = Path.Combine (outputPath, "Library1.pdb");
12571251
Assert.IsTrue (
12581252
File.Exists (assetsPdb),
12591253
"Library1.pdb must be copied to Intermediate directory");
12601254
Assert.IsFalse (
12611255
File.Exists (linkDst),
12621256
"Library1.pdb should not be copied to linkdst directory because it has no Abstrsact methods to fix up.");
12631257
Assert.IsTrue (
1264-
File.Exists (linkSrc),
1265-
"Library1.pdb must be copied to linksrc directory");
1266-
var outputPath = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath);
1258+
File.Exists (binSrc),
1259+
"Library1.pdb must be copied to bin directory");
12671260
using (var apk = ZipHelper.OpenZip (Path.Combine (outputPath, proj.PackageName + "-Signed.apk"))) {
12681261
var data = ZipHelper.ReadFileFromZip (apk, "assemblies/Library1.pdb");
12691262
if (data == null)
12701263
data = File.ReadAllBytes (assetsPdb);
1271-
var filedata = File.ReadAllBytes (linkSrc);
1272-
Assert.AreEqual (filedata.Length, data.Length, "Library1.pdb in the apk should match {0}", linkSrc);
1264+
var filedata = File.ReadAllBytes (binSrc);
1265+
Assert.AreEqual (filedata.Length, data.Length, "Library1.pdb in the apk should match {0}", binSrc);
12731266
}
1274-
linkDst = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linkdst", "App1.pdb");
1275-
linkSrc = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linksrc", "App1.pdb");
1267+
linkDst = Path.Combine (intermediate, "linkdst", "App1.pdb");
1268+
binSrc = Path.Combine (outputPath, "App1.pdb");
12761269
Assert.IsTrue (
12771270
File.Exists (linkDst),
12781271
"App1.pdb should be copied to linkdst directory because it has Abstrsact methods to fix up.");
12791272
Assert.IsTrue (
1280-
File.Exists (linkSrc),
1281-
"App1.pdb must be copied to linksrc directory");
1282-
FileAssert.AreEqual (linkSrc, linkDst, "{0} and {1} should not differ.", linkSrc, linkDst);
1283-
linkDst = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linkdst", "App1.dll");
1284-
linkSrc = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "linksrc", "App1.dll");
1285-
FileAssert.AreEqual (linkSrc, linkDst, "{0} and {1} should match.", linkSrc, linkDst);
1286-
1273+
File.Exists (binSrc),
1274+
"App1.pdb must be copied to bin directory");
1275+
FileAssert.AreEqual (binSrc, linkDst, "{0} and {1} should not differ.", binSrc, linkDst);
1276+
linkDst = Path.Combine (intermediate, "linkdst", "App1.dll");
1277+
binSrc = Path.Combine (outputPath, "App1.dll");
1278+
FileAssert.AreEqual (binSrc, linkDst, "{0} and {1} should match.", binSrc, linkDst);
12871279
}
12881280
}
12891281
}
@@ -1332,15 +1324,9 @@ public void BuildBasicApplicationCheckMdbAndPortablePdb ()
13321324
File.Exists (Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "android", "assets", "NetStandard16.pdb")),
13331325
"NetStandard16.pdb must be copied to Intermediate directory");
13341326
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "second build failed");
1335-
Assert.IsTrue (
1336-
b.Output.IsTargetSkipped ("_CopyMdbFiles"),
1337-
"the _CopyMdbFiles target should be skipped");
13381327
var lastTime = File.GetLastWriteTimeUtc (pdbToMdbPath);
13391328
pdb.Timestamp = DateTimeOffset.UtcNow;
13401329
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "third build failed");
1341-
Assert.IsFalse (
1342-
b.Output.IsTargetSkipped ("_CopyMdbFiles"),
1343-
"the _CopyMdbFiles target should not be skipped");
13441330
Assert.Less (lastTime,
13451331
File.GetLastWriteTimeUtc (pdbToMdbPath),
13461332
"{0} should have been updated", pdbToMdbPath);
@@ -2876,16 +2862,10 @@ public void BuildBasicApplicationCheckPdb ()
28762862
}
28772863
b.BuildLogFile = "build1.log";
28782864
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "second build failed");
2879-
Assert.IsTrue (
2880-
b.Output.IsTargetSkipped ("_CopyMdbFiles"),
2881-
"the _CopyMdbFiles target should be skipped");
28822865
b.BuildLogFile = "build2.log";
28832866
var lastTime = File.GetLastWriteTimeUtc (pdbToMdbPath);
28842867
pdb.Timestamp = DateTimeOffset.UtcNow;
28852868
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "third build failed");
2886-
Assert.IsFalse (
2887-
b.Output.IsTargetSkipped ("_CopyMdbFiles"),
2888-
"the _CopyMdbFiles target should not be skipped");
28892869
Assert.Less (lastTime,
28902870
File.GetLastWriteTimeUtc (pdbToMdbPath),
28912871
"{0} should have been updated", pdbToMdbPath);

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,13 +346,11 @@ public Class2 ()
346346
public void AppProjectTargetsDoNotBreak ()
347347
{
348348
var targets = new List<string> {
349-
"_CopyIntermediateAssemblies",
350349
"_GeneratePackageManagerJava",
351350
"_ResolveLibraryProjectImports",
352351
"_BuildAdditionalResourcesCache",
353352
"_CleanIntermediateIfNuGetsChange",
354353
"_CopyConfigFiles",
355-
"_CopyPdbFiles",
356354
};
357355
var proj = new XamarinFormsAndroidApplicationProject {
358356
OtherBuildItems = {
@@ -367,7 +365,6 @@ public void AppProjectTargetsDoNotBreak ()
367365
if (IsWindows) {
368366
//NOTE: pdb2mdb will run on Windows on the current project's symbols if DebugType=Full
369367
proj.SetProperty (proj.DebugProperties, "DebugType", "Full");
370-
targets.Add ("_CopyMdbFiles");
371368
targets.Add ("_ConvertPdbFiles");
372369
}
373370
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) {

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,7 @@ public void CheckBuildIdIsUnique ()
6666
var allFilesInArchive = Directory.GetFiles (archivePath, "*", SearchOption.AllDirectories);
6767
string extension = "dll";
6868
Assert.IsTrue (allFilesInArchive.Any (x => Path.GetFileName (x) == $"{proj.ProjectName}.{extension}"), $"{proj.ProjectName}.{extension} should exist in {archivePath}");
69-
//NOTE: Windows is still generating mdb files here
70-
extension = IsWindows ? "dll.mdb" : "pdb";
69+
extension = "pdb";
7170
Assert.IsTrue (allFilesInArchive.Any (x => Path.GetFileName (x) == $"{proj.ProjectName}.{extension}"), $"{proj.ProjectName}.{extension} should exist in {archivePath}");
7271

7372
string intermediateOutputDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath);

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Build.Tasks.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
<Compile Include="Linker\MonoDroid.Tuner\Linker.cs" />
128128
<Compile Include="Linker\MonoDroid.Tuner\LinkerOptions.cs" />
129129
<Compile Include="Linker\MonoDroid.Tuner\MonoDroidMarkStep.cs" />
130+
<Compile Include="Linker\MonoDroid.Tuner\OutputStepWithTimestamps.cs" />
130131
<Compile Include="Linker\MonoDroid.Tuner\PreserveHttpAndroidClientHandler.cs" />
131132
<Compile Include="Linker\MonoDroid.Tuner\StripEmbeddedLibraries.cs" />
132133
<Compile Include="Tasks\Aapt.cs" />

0 commit comments

Comments
 (0)