Bug 13974 - CopyMdbFiles task in Xamarin.Android.Common.targets doesn't work for read-only files
Summary: CopyMdbFiles task in Xamarin.Android.Common.targets doesn't work for read-onl...
Status: VERIFIED FIXED
Alias: None
Product: Android
Classification: Xamarin
Component: MSBuild ()
Version: 4.8.x
Hardware: PC Windows
: Normal normal
Target Milestone: 4.16.0
Assignee: dean.ellis
URL:
Depends on:
Blocks:
 
Reported: 2013-08-14 13:16 UTC by Grant Macklem
Modified: 2014-08-13 07:40 UTC (History)
5 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
VERIFIED FIXED

Description Grant Macklem 2013-08-14 13:16:14 UTC
It seems that the CopyMdbFiles task was (re)added to the Xamarin.Android.Common.targets file in Xamarin.Android 4.8.0.  However, if a .mdb file is marked as read-only, the "LinkAssemblies" task fails during build with a System.UnauthorizedAccessException listing the path to the .mdb file.  In our case, we have a precompiled component and its corresponding .mdb file checked into TFS.  It seems Xamarin.Android attempts to copy the .mdb file multiple times, and it fails after the first time.

As a workaround, we can check out the .mdb file.  However, the modification date of the file in the object directories does not change, indicating that the file is not changing.  Can the CopyMdbFiles task be updated to check if the file exists before copying and simply not copy a second time in that case?

For now, we are commenting out the CopyMdbFiles task in the Xamarin.Android.Common.targets file.  This prevents all other .mdb files from being copied as well, but we haven't seen any problems resulting from that yet.
Comment 1 Jonathan Pryor 2013-08-14 16:28:39 UTC
Please provide the full stack trace when the error occurs. You may need to enable Diagnostic build output:

http://docs.xamarin.com/guides/android/deployment%2c_testing%2c_and_metrics/diagnostics#1.diagnostic-msbuild-output

The <CopyMdbFiles/> task is used to copy assemblies (and debug symbols) into $(MonoAndroidIntermediateAssemblyDir), which is e.g. obj\Debug\assemblies.

<CopyMdbFiles/> also regenerates the .dll.mdb file if the .dll file has been updated (timestamp check); it does seem that this process could result in deleting a "source" .dll.mdb file.

Without a stack trace, I'm not sure which scenario you're hitting.
Comment 2 Grant Macklem 2013-08-14 17:59:13 UTC
In looking at the diagnostic output, the CopyMdbFiles task seems to succeed and the LinkAssemblies task is the one that fails.  Here is the stack trace for the error (I have shortened the paths and removed redundant "error MSB4018" text).  Let me know if you need more of the diagnostic output.

C:\Program Files (x86)\MSBuild\Xamarin\Android\Xamarin.Android.Common.targets(926,5): error MSB4018: The "LinkAssemblies" task failed unexpectedly. [...\DataDashboard\DataDashboard.MonoDroid.csproj]
 System.UnauthorizedAccessException: Access to the path '...\DataDashboard\obj\Release\android\assets\System.ComponentModel.Composition.dll.mdb' is denied. [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at System.IO.File.InternalCopy(String sourceFileName, String destFileName, Boolean overwrite, Boolean checkHost) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at System.IO.File.Copy(String sourceFileName, String destFileName, Boolean overwrite) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Mono.Linker.Steps.OutputStep.CopyAssembly(FileInfo fi, String directory, Boolean symbols) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Mono.Linker.Steps.OutputStep.OutputAssembly(AssemblyDefinition assembly) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Mono.Linker.Steps.OutputStep.ProcessAssembly(AssemblyDefinition assembly) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Mono.Linker.Steps.BaseStep.Process(LinkContext context) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Mono.Linker.Pipeline.Process(LinkContext context) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at MonoDroid.Tuner.Linker.Process(LinkerOptions options, LinkContext& context) [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Xamarin.Android.Tasks.LinkAssemblies.Execute() [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() [...\DataDashboard\DataDashboard.MonoDroid.csproj]
    at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__20.MoveNext() [...\DataDashboard\DataDashboard.MonoDroid.csproj]
Done Building Project "...\DataDashboard\DataDashboard.MonoDroid.csproj" (SignAndroidPackage target(s)) -- FAILED.
Comment 3 Grant Macklem 2013-08-26 17:02:49 UTC
I'm not sure if I need to change the status from NEEDINFO after posting the stack trace, so I'll try to see if I have permission.
Comment 4 Jonathan Pryor 2014-07-31 11:57:46 UTC
Fixed in monodroid/d94edb84.
Comment 5 Prashant manu 2014-08-08 07:23:03 UTC
Could you please provide us some direction or test steps to check this issue?
Comment 6 Jonathan Pryor 2014-08-08 08:46:10 UTC
@Prashant: I'd have to ask Dean, but I suspect that the repro steps are:

1. Run on Windows. ;-)
2. Add a .dll to your project (not a Project reference; an actual .dll), along with a corresponding .dll.mdb debug symbols file.
3. Mark both the .dll and the .dll.mdb as "readonly" (File Properties within Explorer)
4. Build

(I believe the common scenario is people checking .dll's into TFS, then building the project from a checkout, as TFS marks most files as readonly.)

On previous releases, this would fail (Comment #2); it shouldn't anymore.
Comment 7 dean.ellis 2014-08-11 05:54:47 UTC
@Prashant @jonp is correct, you can just add am assembly reference, but make sure the assembly has a .mdb file which is read only (and the .dll too). That should trigger the issue.
Comment 8 Prashant manu 2014-08-12 11:28:29 UTC
@ Dean, As per comment 6 we have tried adding dll.mdb debug symbols file along with .dll. But we are not able to select dll.mdb file to add to project. 
Screencast: http://screencast.com/t/BzGjTTND9qjl

Please review the screencast and let us know how to proceed over, if there is any deviation in our understanding for the same
Comment 9 dean.ellis 2014-08-12 11:38:39 UTC
I can't get to the screencast link. 

What should happen is this. If you had a .dll and .mdb in the same folder (i.e Dependencies or something), then reference the .dll from the project (Add Reference) as you normally would. The MSBuild task should pickup that the .mdb is there and copy that over rather than trying to regenerate it. 

Now if the .mdb is readonly that should cause a problem later.
Comment 10 Prashant manu 2014-08-13 07:40:33 UTC
Now able to build project successfully after referencing .dll [.dll and the .dll.mdb as "readonly"].

Also on adding .dll, it pickup the .mdb file as well.

Screencast: http://screencast.com/t/uWbBF1SphWh

Environment Info:
VS 2013
Xamarin  3.5.23.0 (39e124c90b45ae541f67228b3188d3251a4f34ad)
Java SDK: C:\Program Files\Java\jdk1.7.0_67
java version "1.7.0_67"