ILMerge fails to merge: The assembly 'xxx' was not merged in correctly - ilmerge

Problem
Using ILMerge I am trying to merge three assemblies: A, B and C. It fails with the following errormessage. I really need to help to solve this.
"ILMerge.Merge: The assembly 'B' was not merged in correctly. It is still listed as an external reference in the target assembly."
Assembly A does not reference the other two. B references A. C references A and B.
Command line: ilmerge /v2 /target:library /out:test.dll a.dll b.dll c.dll
What I have tried
Use /closed argument. Does not make any difference.
Different versions of ILMerge, I get the same error with both version 3.0.21.3911 and 2.14.1208.
Merge A and B first and the merge in C with the A+B merge. This does not produce any error message but the resulting file is broken. It does not run and when I run in through .NET Obfuscator it complains about it.
Some background
The project is larger than the three assemblies but I have managed to reduce the problem down to these. If I dont include assembly C and only merge A and B the problem goes away.
In the previous version I did not have this problem. Between these two versions there is only non functional changes, like renames (not assembly or namespaces, only classes, methods etc) and reordering of access modifiers (static internal->internal static)
From the documentation
A common problem is that after merging some assemblies, you get an error message
stating that an input assembly was not merged in correctly because it is still listed as an
external reference in the merged assembly. The most common cause of this problem is
that one of the input assemblies, B, has an external reference to the incorrectly merged
assembly, A, and also an external reference to another assembly, C, that itself has an
external reference to A. Suppose the reference to C is to a method that takes an argument
whose type is defined in A. Then the type signature of the method call to the method in C
still refers to the type from A even in the merged assembly. After all, ILMerge cannot go
and modify the assembly C so that it now depends on the type as it is defined in the
output assembly after it has been merged!
The solution is to use the closed option (Section 2.6) to have ILMerge compute the
transitive closure of the input assemblies to prevent this kind of “dangling reference”. In
the example, that would result in all three assemblies A, B, and C, being merged. There is
no way to merge just A and B without there still being an external reference to A.

Related

Distinguish two functions with the same name

I want to use multiple external CMake files in my project. Unfortunately two different files use the same CMake function name foo. I don't want to modify these external files.
Is there a way to call one specific function or will CMake error out? Would it help if one of the functions has a named parameter, i.e., foo(a b c …) and foo(DESTINATION a b c …)?
New function's definition replaces the previous one with the same name. So access to the previous function is lost.
If different functions (but with the same name) are used in different subprojects, you may try to build one subproject as ExternalProject, so function's collision wouldn't occure.
In CMake any function definitions contains the only piece of information for the caller - minimal number of parameters which should be passed to the function. By using this information it is impossible to resolve function's overloading, if it would be implemented.

Specifying target_link_libraries when building shared object in cmake

My project creates a shared object A that 'depends' should reference other shared objects B, C , D and E. After building the project and checking the build with the utility ldd I see no references to the shared objects B, C , D and E. However when I use the directive target_link_libraries(A , B , C , D , E ) in my build the references to the shared objects appear in A.so. My question is two fold:
Is it correct to use target_link_libraries in this way?
If so, why is this use of target_link_libraries correct considering that I'm building a shared object where linking is at runtime.
Example:
My Frobnigator project depends on a ContinuumTransfunctioner and Transmogrifier shared objects that have already been built. My question is about whether the line target_link_libraries(Frobnigator ${Libraries}) is necessary.
cmake_minimum_required(VERSION 3.0)
set(Libraries
ContinuumTransfunctioner
Transmogrifier
)
set(SourceFiles
Wrapper.cpp
Logger.cpp
)
add_library(Frobnigator SHARED ${SourceFiles})
add_library(FrobnigatorStatic STATIC ${SourceFiles})
set_target_properties(FrobnigatorStatic PROPERTIES OUTPUT_NAME Frobnigator)
#target_link_libraries(Frobnigator ${Libraries}) # Do I need this?
Yes, you need to use target_link_libraries even when create SHARED library.
While some symbol resolution is performed at runtime (loading time), there some things which should be performed at build time (linking).
The main thing is ... providing a list of libraries, which should be loading with your library. This list is "embedded" into the library file. There is no other way for dynamic loader to know, which other libraries should be loaded with your one.
Among other things performed at link time is:
Checking that all symbols needed for your library are actually available in other libraries.

How to convert a type, loaded from one project, to an interface

Prerequisites
.NET environment
A Common assembly with an interface IModule
Main project, referencing Common
Implementor project, referencing Common, but not referenced from Main
When everything is built, the Common.dll is present in both Main and Implementor.
Now the Main project tries to load the class implementing IModule at runtime. What I could achieve so far:
Dim asm = Assembly.LoadFrom(asmFile)
For Each asmType in asm.GetExportedTypes()
If asmType.IsClass AndAlso
asmType.GetInterfaces().Any(Function(i) i.Name = GetType(IModule).Name) Then
Dim handle = AppDomain.CurrentDomain.CreateInstanceFrom(asmFile, asmType.FullName)
Dim inst = CType(handle.Unwrap(), IModule) ' EXCEPTION
End If
Next
So I can load the Implementor assembly and find the type implementing IModule. But I can't create an instance of it such that I can cast it to my local IModule. Is this at all possible?
Workaround
I found a workaround - in Implementor project, click on reference to Common and clear "Copy Local" flag. Then I can even use simpler code, like IsAssignableFrom(). But is this the only way? What if I get a DLL from third party, where the IModule is compiled into it?
EDIT:
Assembly.LoadFrom loads the first found matching assembly in a directory tree (via the so called Probing Path). So if you have your Common DLLin folder A and the updated Common DLL is in folder A\B then the one in folder A is taken (if both dlls have the same name).
From MSDN:
The load-from context allows an assembly to be loaded from a path not
included in probing, and yet allows dependencies on that path to be
found and loaded because the path information is maintained by the
context.
The LoadFrom method has the following disadvantages.Consider using
Load instead.
If an assembly with the same identity is already loaded, LoadFrom returns the loaded assembly even if a different path was specified.
If an assembly is loaded with LoadFrom, and later an assembly in the load context attempts to load the same assembly by display name,
the load attempt fails.This can occur when an assembly is
de-serialized.
If an assembly is loaded with LoadFrom, and the probing path includes an assembly with the same identity but a different location,
an InvalidCastException, MissingMethodException, or other unexpected
behavior can occur.
Original Answer:
Use Activator.CreateInstance to create the object and typeof to check if it implements the Interface :
Dim a As assembly = Assembly.LoadFrom(asmFile)
Dim concreteModule As IModule = Nothing
For each type In a.GetExportedTypes().Where(Function(x) x.IsClass)
Dim o = Activator.CreateInstance(type)
If TypeOf o Is IModule
concreteModule = DirectCast(o, IModule)
Exit For
End If
Next
Remark:
You wrote: But I can't create an instance of it such that I can cast it to my local IModule.
The concrete object must implement the Interface you cast to. I don´t know if I understood you correctly but casting from a Interface IModule in a 3rd party dll to a different Interface IModule* in your local dll will not work (unless your local interface implements the other).

Matching Roslyn SourceMemberMethodSymbol with a 'RetargetingMethodSymbol'

I've been putting some 'find references' code together using Roslyn to search for all method declarations that match a particular signature, and then locate all uses of those methods elsewhere.
It's working in 99% of cases, but I've got an issue where an InvocationExpressionSyntax.Symbol is an instance of Microsoft.CodeAnalysis.VisualBasic.Symbols.Retargeting.RetargetingMethodSymbol instead of a regular Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberMethodSymbol. As a consequence this particular call to a target method isn't found (using ISymbol.Equals, which uses reference equality). RetargetingMethodSymbol has an UnderlyingMethod property whose value is the target method I'd expect, but this type is internal and that property isn't exposed.
What is a RetargetingMethodSymbol, and how can I see if it corresponds to a MethodBlockSyntax.Symbol?
What is a RetargetingMethodSymbol?
Consider a method M(object o) that is defined in project A, which targets .NET 2.0.
Project B targets .NET 4.0, and has a reference to A. In the context of project B, M will be wrapped in a RetargetingMethodSymbol, since the object that it refers to in this context isn't the same one that it refers to in the context of A.
How can I see if it corresponds to a MethodBlockSyntax.Symbol?
I don't know what you mean by MethodBlockSyntax.Symbol, but the VS IDE code uses SymbolFinder.FindSourceDefinitionAsync() to find the "original" symbol in cases like this (and also if A was written in C# and B in VB or vice versa).

SSDT emits spurious SQL71502: Function: [dbo].[***] contains an unresolved reference to an object

I have a number of SqlClr aggregate functions that were once in a separate project...but now with SSDT, I can have them all a single db project. Cool. All of them are in the global namespace. They compile and everything works...but I still get warnings from 4 referencing T-SQL functions in the project. The CLR function being referenced is being referenced from 7 other T-SQL functions without warnings.
I can remove the function and let the intellisense put it back in...it finds the function, too. I reference it exactly the same way everywhere its referenced:
select dbo.SomeClrAggregateFunction( a.Column )
from
dbo.SomeTable a
inner join
dbo.OtherTable b
on a.ColumnOne = b.ColumnOne
group by
b.SomeOtherColumn
Again...everything works..I can compile, deploy and test the referencing functions just fine. I just can't get rid of the warnings. I've got a thing about getting rid of warnings, but suppression seems unseemly.