Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Delete inconsistent debug symbols (#701)
Browse files Browse the repository at this point in the history
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=58221

The build scenario:

 1. Use Windows. (This doesn't happen on macOS.)

 2. Clone: https://github.com/xamarin/xamarin-forms-samples/tree/master/Templates/DataTemplateSelector

 3. Edit `Selector\Selector.csproj` and change `$(DebugType)` to Portable.

 4. Open `Selector.sln` within VS and restore all packages.

 5. Build the `Droid\Selector.Droid.csproj` project:

        msbuild /p:Configuration=Release /t:SignAndroidPackage Droid\Selector.Droid.csproj

 6. Touch (update the timestamp of) `Selector\Selector.csproj`.

 7. Build the project `Droid\Selector.Droid.csproj` project again.

        msbuild /p:Configuration=Release /t:SignAndroidPackage Droid\Selector.Droid.csproj

Expected results: No errors.

Actual results: Linking fails:

	error MSB4018: The "LinkAssemblies" task failed unexpectedly.\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018: Mono.Linker.MarkException: Error processing method: 'Xamarin.Forms.View Xamarin.Forms.Platform.Android.VisualElementRenderer`1::get_View()' in assembly: 'Xamarin.Forms.Platform.Android.dll' ---> System.ArgumentNullException: Value cannot be null.\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018: Parameter name: instruction\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.InstructionOffset..ctor(Instruction instruction)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadScope(ScopeDebugInformation scope)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadScopes(Collection`1 scopes)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadScope(ScopeDebugInformation scope)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadScopes(Collection`1 scopes)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadScope(ScopeDebugInformation scope)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadDebugInfo()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadMethodBody()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.Cil.CodeReader.ReadMethodBody(MethodDefinition method)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.MetadataReader.ReadMethodBody(MethodDefinition method)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.MethodDefinition.<>c.<get_Body>b__41_0(MethodDefinition method, MetadataReader reader)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TRet& variable, TItem item, Func`3 read)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Cecil.MethodDefinition.get_Body()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Steps.MarkStep.ProcessQueue()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    --- End of inner exception stack trace ---\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Steps.MarkStep.ProcessQueue()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Steps.MarkStep.Process()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Steps.MarkStep.Process(LinkContext context)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Mono.Linker.Pipeline.Process(LinkContext context)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at MonoDroid.Tuner.Linker.Run(Pipeline pipeline, LinkContext context)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at MonoDroid.Tuner.Linker.Process(LinkerOptions options, LinkContext& context)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Xamarin.Android.Tasks.LinkAssemblies.Execute(DirectoryAssemblyResolver res)\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Xamarin.Android.Tasks.LinkAssemblies.Execute()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()\r [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]
	error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() [C:\Users\jonpr\Dev\xamarin-forms-samples\Templates\DataTemplateSelector\Droid\Selector.Droid.csproj]

The cause of the error is in the interaction between the
`_CopyIntermediateAssemblies`, `_CopyMdbFiles`, and
`_StripEmbeddedLibraries` targets.

During the initial build in Step (5), `obj\Release\linksrc` is
populated with copies of the original assemblies and debug symbols for
those assemblies. The contents of `obj\Release\linksrc` are then
updated *in place* by various tasks such as the
`<StripEmbeddedLibraries/>` and `<LinkAssemblies/>` tasks. After
stripping and linking, the timestamps in `obj\Release\linksrc` are
updated and the assemblies and associated debug symbols may be smaller
than the original copies.

During the rebuild in Step (7), `_CopyIntermediateAssemblies` replaces
`obj\Release\linksrc\Xamarin.Forms.Platform.Android.dll` with a copy
of the original file in `packages\Xamarin.Forms...\lib\MonoAndroid10`.
The `_CopyMdbFiles` task -- which is responsible for copying
`.dll.mdb` files into `obj\Release\linksrc` -- does *not* update the
`Xamarin.Forms.Platform.Android.dll.mdb` file. The result of this
inaction is that when the `<StripEmbeddedLibraries/>` task executes,
the assembly and corresponding debug symbols are out-of-sync:
`Xamarin.Forms.Platform.Android.dll` is the original+unstripped
assembly, while `Xamarin.Forms.Platform.Android.dll.mdb` has been
*modified* as part of (both?) the `<StripEmbeddedLibraries/>` and/or
`<LinkAssemblies/>` task.

When `<StripEmbeddedLibraries/>` executes again as part of the
rebuild, it takes these out-of-sync files and then proceeds to
*corrupt* the `Xamarin.Forms.Platform.Android.dll.mdb` file. After the
`<StripEmbeddedLibraries/>` task completes, we eventually hit the
`<LinkAssemblies/>` task, during which Cecil attempts to load the
now-corrupt `Xamarin.Forms.Platform.Android.dll.mdb` file, which
results in the above `ArgumentNullException`.

The fix is in the `_CopyIntermediateAssemblies` target: when we copy
assemblies into the `obj\Release\linksrc` directory, ensure that any
corresponding `.dll.mdb` files for those asssemblies are *deleted*.
This will allow `_CopyMdbFiles` to re-copy the debug symbols, ensuring
that everything stays in sync.

*Additionally*, update the `_CopyIntermediateAssemblies` target to
`<Touch/>` the copied files so that timestamps compare properly.
Otherwise, on the 2nd+ build, the target re-executes because the
project assembly is newer than e.g. a BCL assembly:

	Target _CopyIntermediateAssemblies needs to be built as input file
	'…/xamarin-android/bin/TestDebug/temp/BuildBasicApplicationCheckPdb/bin/Debug/UnnamedProject.dll'
	is newer than output file 'obj/Debug/linksrc/NetStandard16.dll'

Without the `<Touch/>`, the above will *always* be true.
  • Loading branch information
jonpryor authored and dellis1972 committed Jul 24, 2017
1 parent f2eb704 commit 1ea5f07
Showing 1 changed file with 3 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1486,6 +1486,9 @@ because xbuild doesn't support framework reference assemblies.
DestinationFiles="@(_AndroidResolvedSatellitePaths->'$(MonoAndroidLinkerInputDir)%(DestinationSubDirectory)%(Filename)%(Extension)')"
SkipUnchangedFiles="true"
/>
<Touch Files="@(ResolvedUserAssemblies->'$(MonoAndroidLinkerInputDir)%(Filename)%(Extension)')" />
<Touch Files="@(_AndroidResolvedSatellitePaths->'$(MonoAndroidLinkerInputDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
<Delete Files="@(ResolvedAssemblies->'$(MonoAndroidLinkerInputDir)%(Filename)%(Extension).mdb')" />
</Target>

<Target Name="_CollectConfigFiles"
Expand Down

0 comments on commit 1ea5f07

Please sign in to comment.