I am trying to create a pure MSIL assembly from a C++/CLI project using /clr:pure and /clrimagetype:pure flags, however, the output assembly specifically targets x86.
Am I missing anything that might be preventing my project to be compiled as MSIL only?
You can create an AnyCPU dll with C++/CLI, but in the simplest case, you will not be able to use MFC, ATL or the CRT. However, if you just want to write pure managed .NET code in C++/CLI, including managed pointers (which
/clr:safe
does not allow), and get the more elaborate code optimization of the C++/CLI compiler, read on:/clr:pure
. This is on theConfiguration Properties
page in Visual Studio 2010.Omit Default Library Name
toYes /Zl
Incremental Linking
andLink Library Dependencies
Not Set
and the CLR Image Type toForce Pure IL Image /CLRIMAGETYPE:PURE
, but some of these aparently settings aren't honored, since the 32BIT+ flag is still set by the linker in the PE32 header.corflags
step to your build. The best way to do this is to exit Visual Studio and edit your vcxproj file with a text editor. At the bottom of the file, add: This runs thecorflags
tool to turn off the 32BIT flag in your DLL. Make sure that thecorflags.exe
tool is available in your path.That's it, you can now build the AnyCPU dll; it is pure
MSIL
by virtue of the 'pure' settings, and it will load either as x64 or x86 thanks to thecorflags
adjustment. It is up to you to avoid using any incompatible features, such as Interop, at runtime. However--and this is the difference versus just trivially using/clr:safe
mode (which also produces an AnyCPU library)--you can use unsafe managed pointers to access managed value types.[edit:] To elaborate on Ben Voight's comment, one thing that won't work in this type of C++/CLI AnyCPU dll is the use of C/C++ initialization syntax to initialize unmanaged (i.e. native), static primitives, structs, (or arrays):
The linker issues a warning to this effect,
warning LNK4210: .CRTMA section exists; there may be unhandled static initializers or terminators
. You can, however, declare them, initialize them yourself, and use them--that is, take their addresses--and read/write them from managed code (if you want to declare such an array asconst
, then you'll have to provide empty braces{ }
for an initializer and cast a pointer tovolatile
to initialize it.):Ironically, one way to initialize these native static resources or tables is to copy them, during the module constructor or class static constructor, from a managed variable or resource.
Why bother with native statics, you ask? Because they can be quickly accessed without pinning. One nice thing C++/CLI still does for you here is to silently create a managed value-type (struct) to overlay each of your native statics, so that the IL code can get at them directly with IL pointers, thus keeping the assembly /pure.
[edit: corrected mis-statement regarding "native" pointers in an AnyCPU assembly] [edit: clarify: 'unsafe' C# code in pure assembly uses managed pointers via IL instructions such as ldloca, etc.]
If you are using Visual Studio, you should be able to set the Target Machine project property under the Linker -> Advanced settings.
If what you are looking for is to compile your C++/CLI project as "Any CPU", then you need to compile in /clr:safe and /clrimagetype:safe. See the following link for more information:
http://bytes.com/topic/net/answers/660475-any-cpu-build-c-cli