dsplaisted / strongnamer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Build failing when assembly dependencies haven't been signed yet

Nick-Lucas opened this issue · comments

I may have misdiagnosed my issue here, but it's preventing me from building so I will try to explain first.

I have a solution with the following dependencies:

  • ClassLib1
  • ClassLib2
  • ClassLib3
  • ClassLibCommon

The dependency tree would look like this:

  • Solution
    • ClassLib1
      • ClassLibCommon
    • ClassLib2
      • ClassLibCommon
    • ClassLib3
      • ClassLibCommon

On build I'm receiving an error like:

The "StrongNamer.AddStrongName" task failed unexpectedly.
Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'ClassLibCommon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e33b67d3bb5581e4'
   at Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters)
   at Mono.Cecil.DefaultAssemblyResolver.Resolve(AssemblyNameReference name)
   at Mono.Cecil.MetadataResolver.Resolve(TypeReference type)
   at Mono.Cecil.TypeReference.Resolve()
   at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
   at Mono.Cecil.MetadataBuilder.GetConstantType(TypeReference constant_type, Object constant)
   at Mono.Cecil.MetadataBuilder.AddConstant(IConstantProvider owner, TypeReference type)
   at Mono.Cecil.MetadataBuilder.AddParameter(UInt16 sequence, ParameterDefinition parameter, ParamTable table)
   at Mono.Cecil.MetadataBuilder.AddParameters(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddTypeDefs()
   at Mono.Cecil.MetadataBuilder.BuildTypes()
   at Mono.Cecil.MetadataBuilder.BuildModule()
   at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__1_0(MetadataBuilder builder, MetadataReader _)
   at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
   at Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
   at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   at StrongNamer.AddStrongName.ProcessAssembly(ITaskItem assemblyItem, StrongNameKeyPair key)
   at StrongNamer.AddStrongName.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()	UiBootstrapper	B:\Repositories\DataAnalysisDesktop\packages\StrongNamer.0.0.3\build\StrongNamer.targets	9	

When I look at the SignedAssemblies folder I see ClassLib3 with a size of 0kb.
I believe what's happening, is ClassLib3 (which I only added this week, all the others have been around for a long time) is being tackled first, and the signing fails because it can't find the signed ClassLibCommon.

As a result the entire build falls over.

It's my theory that this would be resolved if failed signing attempts were queued up for later, and the signing moved on, OR the dependency tree could be inferred and signing ordered correctly.

If there's any more information I can give please let me know.

Okay I've done a bit more digging and implemented the recursive solution just to see:

Have a look at void ProcessAssemblies for what's new
https://github.com/Nick-Lucas/strongnamer/blob/master/src/StrongNamer/AddStrongName.cs

Looks like it doesn't solve my problem, but I was right that it's failing on ClassLib3 with the exception being related to ClassLibCommon

Output looks like this:

The "StrongNamer.AddStrongName" task failed unexpectedly.
System.InvalidOperationException: 1 assemblys could not be signed. Affects: [B:\Repositories\ApplicationPath\packages\ClassLib3.1.2.2\lib\netstandard1.3\ClassLib3.dll]
____
Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'ClassLibCommon, Version=1.0.0.0, Culture=neutral, PublicKeyToken=e33b67d3bb5581e4'
   at Mono.Cecil.BaseAssemblyResolver.Resolve(AssemblyNameReference name, ReaderParameters parameters)
   at Mono.Cecil.DefaultAssemblyResolver.Resolve(AssemblyNameReference name)
   at Mono.Cecil.MetadataResolver.Resolve(TypeReference type)
   at Mono.Cecil.TypeReference.Resolve()
   at Mono.Cecil.Mixin.CheckedResolve(TypeReference self)
   at Mono.Cecil.MetadataBuilder.GetConstantType(TypeReference constant_type, Object constant)
   at Mono.Cecil.MetadataBuilder.AddConstant(IConstantProvider owner, TypeReference type)
   at Mono.Cecil.MetadataBuilder.AddParameter(UInt16 sequence, ParameterDefinition parameter, ParamTable table)
   at Mono.Cecil.MetadataBuilder.AddParameters(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethod(MethodDefinition method)
   at Mono.Cecil.MetadataBuilder.AddMethods(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddType(TypeDefinition type)
   at Mono.Cecil.MetadataBuilder.AddTypeDefs()
   at Mono.Cecil.MetadataBuilder.BuildTypes()
   at Mono.Cecil.MetadataBuilder.BuildModule()
   at Mono.Cecil.ModuleWriter.<>c.<BuildMetadata>b__1_0(MetadataBuilder builder, MetadataReader _)
   at Mono.Cecil.ModuleDefinition.Read[TItem,TRet](TItem item, Func`3 read)
   at Mono.Cecil.ModuleWriter.BuildMetadata(ModuleDefinition module, MetadataBuilder metadata)
   at Mono.Cecil.ModuleWriter.WriteModuleTo(ModuleDefinition module, Disposable`1 stream, WriterParameters parameters)
   at Mono.Cecil.ModuleDefinition.Write(String fileName, WriterParameters parameters)
   at StrongNamer.AddStrongName.ProcessAssembly(ITaskItem assemblyItem, StrongNameKeyPair key)
   at StrongNamer.AddStrongName.ProcessAssemblys(ITaskItem[] assemblysToSign, StrongNameKeyPair key, Dictionary`2 updatedReferencePaths)
   at StrongNamer.AddStrongName.ProcessAssemblys(ITaskItem[] assemblysToSign, StrongNameKeyPair key, Dictionary`2 updatedReferencePaths)
   at StrongNamer.AddStrongName.ProcessAssemblys(ITaskItem[] assemblysToSign, StrongNameKeyPair key, Dictionary`2 updatedReferencePaths)
   at StrongNamer.AddStrongName.Execute()
   at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
   at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()	UiBootstrapper	B:\Repositories\DataAnalysisDesktop\packages\StrongNamer.0.0.4\build\StrongNamer.targets	9	

Some notes from debugging through this:

Looks like this is a Mono.Cecil problem, where types from a dependency are being used as constants (may affect other scenarios)

It looks like Mono.Cecil will try to resolve any constants from dependent assemblies of assemblies StrongNamer tries to sign (Write), this is resulting in the DefaultAssemblyResolver being used to find ClassLibCommon since an enum from this is being used as the default parameter value (a CLR constant) in two cases in ClassLib3.

The resolve is failing because ClassLibCommon is not cached, or in ., or in bin in the project folder.

More notes incoming as I get deeper

Okay so the above analysis is correct and it tries to resolve the dependency assembly where the constant is declared, it then fails to find it.

This occurs on Mono.Cecil.MetaDataResolver which defaults IAssemblyResolver assembly_resolver to DefaultAssemblyResolver which is only sufficient for the current project's directory, and not to access the Packages directory or other locations of assemblies. A custom AssemblyResolver can be passed to MetaDataResolver on instantiation.

I've confirmed that passing a custom assembly resolver on AssemblyDefinition.Read will persist right down to this layer on future operations, so propose implementing an assembly resolver which is given the locations of all solution assemblies ready to be quickly and correctly resolved for the build-time checks

closed by #11