Open GoogleCodeExporter opened 9 years ago
Impressive,
I have included:
- the SVNVERSION_SIMPLE (in Makefile.port)
- the CommonAssemblyAttributes part
- CLR_PER_PLATFORM_ASSEMBLY_NAMING and its derivatives
I have changed NETPLATFORM to x64 on mac os X.
I have not included:
- Adding AssemblyInfo file to all binaries, do we need than in addition to the dll?
Question: on Windows (I am far from a windows machine), does the assembly
loading mechanism loads Google.OrTools.x64.dll with the Google.OrTools prefix
(for references)?
Many thanks!
Original comment by laurent....@gmail.com
on 1 Jan 2015 at 12:00
Hi Laurent,
Thanks for your comments, and I'm glad you approve!
Re: Adding AssemblyInfo file to all binaries, do we need than in addition to
the dll?
While it's not vital, I don't think it does any harm. If I understand it
correctly, the executables are all examples or unit tests, so they're unlikely
to travel far, thus reducing the importance.
As regards assembly binding:
Despite fairly extensive research and experience, I'm not aware of any
out-of-the-box mechanism to have the correct platform-specific DLL resolved for
a reference from a platform independent assembly at runtime, regardless of the
naming scheme of the referenced DLL. One avenue I have not investigated is the
Native Image Cache, as typically populated using the ngen.exe framework tool,
but frankly I'd not hold out much hope with that approach given that it's
indented to cache platform-specific compilations of IL assemblies, and the
OrTools assemblies are quite hard for most IL-manipulating tools to digest.
However, I have developed a mechanism for automatic runtime selection that we
use within our organisation. The mechanism is packaged using nuget, requires
powershell during nuget package installation, and MSBuild as the build system.
It also uses some of our custom in-house build tasks. And currently will only
work with C# projects (not VB, F# etc). So in its current form, the mechanism
is a) Windows-specific (as I understand it, due to needing MSBuild and
powershell) b) C#-specific and c) requires some of our in-house tools. It would
not be too difficult to abstract the in-house tools, so issue (c) could be
worked-around. So, if a Windows-specific, C#-specific nuget-packaged mechanism
is of significant interest, I could look at open-sourcing and publishing it,
subject to my organisation granting me the permission and time to resolve issue
(c). Issue (b) could also be worked-around, with time.
In case anyone else wishes to reproduce the mechanism by hand, here's what we
do:
1. Obtain .NET assemblies Google.OrTools.x86.dll and Google.OrTools.x64.dll.
2. Take one of these assemblies and run it through our in-house tool,
eviscerate.exe. eviscerate.exe uses Cecil to remove all the innards of the
assembly, leaving behind just the public .NET facade. All remaining method
bodies simply throw. The corflags are fixed up, and a pure-IL,
platform-agnostic assembly is emitted. I call this the "eviscerated facade",
and it is named Google.OrTools.dll. In r3804, it ends up as just 166 KiB.
3. Assume we have an AnyCPU C# project, Foo, that needs to use OrTools.
4. To Foo.csproj, add an assembly reference to the eviscerated facade,
Google.OrTools.dll. Set CopyLocal to false. This is what csc will compile
against, and will be used for IntelliSense in Visual Studio.
5. Add Google.OrTools.x86.dll and Google.OrTools.x64.dll to Foo.csproj as
content items (*not* as assembly references). Set CopyToOutputDirectory to
Always.
6. Before any other code in Foo executes, subscribe to the
AppDomain.Current.AssemblyResolve event.
7. In the AssemblyResolve handler, if the assembly being resolved is
Google.OrTools, load and return the correct platform-specific assembly.
8. Ensure that you don't have a Google.OrTools.dll in the GAC. And there should
not be a Google.OrTools.dll in Foo's build output directory (hence setting
CopyLocal to false). If you produced your own strong name signed OrTools
binaries (we do), then you're immune from the consequences of some other
software dumping a copy of Google.OrTools.dll in the GAC. Essentially, we don't
want Foo.exe to be able to find Google.OrTools.dll - this failure to resolve
will cause the AssemblyResolve handler to be called.
Notes:
i. In our implementation, all the above steps are performed seamlessly at build
time as a consequence of adding the nuget package to the project. The only
visible effect within Visual Studio is a an assembly reference to the
eviscerated facade.
ii. To acheive (6) and (7) we inject a module initializer into the compiled DLL
using an in-house custom build task, which iteslf uses Cecil. The event
subscription handling code is in a .cs file that is silently added to the
project during the build process (hence the C#-only limitation). A module
initializer is a CLR feature that is not exposed by any of the standard CLR
langauages, but can be used by direct IL manipulation/injection. It essentially
creates a module-global static constructor which the CLR VM guarantees to
execute before any other code in the assembly is executed. This works for .NET
executables and DLLs.
Thanks,
Tom
Original comment by t...@zanyants.com
on 1 Jan 2015 at 1:10
Just to clarify - in our mechanism, steps 1 & 2 are not performed at build
time, but are part of creating the nuget package.
Original comment by t...@zanyants.com
on 1 Jan 2015 at 1:12
Original issue reported on code.google.com by
t...@zanyants.com
on 31 Dec 2014 at 6:15Attachments: