7

I realize that it's been asked and answered that Visual Studio does not support CIL/MSIL projects. The MSBuildContrib project has an ILASM task which allows you to compile IL files at build time.

Googled came up empty on examples for how to use this task.

Are there any examples of using ILASM as part of a Visual Studio solution? I realize that #develope and ILIDE support CIL... the objective here is to compile some CIL files as part of a Visual Studio solution.

Mark
  • 9,320
  • 6
  • 57
  • 70
  • May I ask why you really need to compile with IL? What does it have that C#/VB.NET/F# cannot do? – leppie Nov 01 '10 at 11:30
  • 2
    @Leppie - That's a topic fit for long debate, suffice to say that there are (admitedly few) things that are far easier to achieve with IL than with C# or VB - particularly when creating generics which work with delegates. IL, naughtily, allows you to dynamically pcik and choose which arguments to push to the stack before invoking a method. C# and VB do not. Normally a good thing, but sometimes bending the rules opens new doors. Dynamic delegates are an example of this. – Mark Nov 01 '10 at 18:56
  • @Mark, can you briefly tell (or provide a link to) what can you improve for Delegates using MSIL? Can this help you write methods that work for all delegate types? – Ark-kun Oct 17 '12 at 01:17

2 Answers2

16

I gave Hans credit for answering this question, but after some experimentation I've got a solution which comes slightly closer to home:

HOW TO COMPILE CIL/MSIL INSIDE VISUAL STUDIO

The following hack gets you a project which:

  • Respects the Debug vs. Release build configuration in Visual Studio.
  • Optionally signs the resulting CIL assembly with the key file set up in the project preferences.
  • Can be added to source control.

Follow these steps:

  1. Create an empty C# classs library
  2. In the solution folder, right click the project and choose "unload project"
  3. Right click the unloaded project and choose "edit project"
  4. In the csprof file, scroll down to the bottom, and find the line which says "Import ... Project="$(MSBuildBinPath)\Microsoft.CSharp.targets", and replace it with the code at http://pastebin.com/KEJtyQLu (copied below)

Here's the XML:

  <Import Project="$(MSBuildToolsPath)\Microsoft.Common.targets" />

  <Target Name="CreateManifestResourceNames" />

  <Target Name="CoreCompile" Inputs="$(MSBuildAllProjects);@(Compile);" Outputs="@(IntermediateAssembly);$(NonExistentFile);">
    <GetFrameworkPath>
      <Output TaskParameter="Path" PropertyName="FrameworkPath" />
    </GetFrameworkPath>

    <PropertyGroup>
      <IlAsmCommand>&quot;$(FrameworkPath)\Ilasm.exe&quot; /NOLOGO /DLL /OUTPUT:&quot;@(IntermediateAssembly)&quot; </IlAsmCommand>
    </PropertyGroup>

    <PropertyGroup Condition=" '$(Configuration)' == 'Debug' " >
      <IlAsmCommand>$(IlAsmCommand) /DEBUG </IlAsmCommand>
    </PropertyGroup>

    <PropertyGroup Condition=" '$(Configuration)' == 'Release' " ><IlAsmCommand>$(IlAsmCommand) /OPTIMIZE </IlAsmCommand></PropertyGroup>

    <PropertyGroup Condition=" '$(AssemblyOriginatorKeyFile)' != '' " >
      <IlAsmCommand>$(IlAsmCommand) /KEY:&quot;$(AssemblyOriginatorKeyFile)&quot; </IlAsmCommand>
    </PropertyGroup>

    <Exec Command="$(IlAsmCommand) @(Compile->'&quot;%(FullPath)&quot;', ' ')" 
          Outputs="@(IntermediateAssembly)" />

    <CallTarget Targets="$(TargetsTriggeredByCompilation)" Condition="'$(TargetsTriggeredByCompilation)' != ''" />

  </Target>
Suzanne Soy
  • 3,027
  • 6
  • 38
  • 56
Mark
  • 9,320
  • 6
  • 57
  • 70
  • Thanks, that gave me a useful starting point. I was using MonoDevelop which normally can compile CIL projects fine, but whether the flaw was with it or with me I couldn't get signing to work correctly, and basing changes to the ilproj file on the above sorted it. For a mono build replace `"$(FrameworkPath)\Ilasm.exe"` with `ildasm` (case-sensitive) and drop out the debug and release additions (which both hit features mono ildasm doesn't yet support. Conversely, with MS it can also be good to add in `/RESOURCE:someResourceFile.res` (I just hard-coded into the first `IlAsmCommand`) – Jon Hanna Dec 31 '13 at 20:23
  • Check me on this, but between all of the above and [MSBuild reserved and well-known properties](https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-reserved-and-well-known-properties), I think I have contents for the first `IlAsmCommand` element that correctly includes the resource file - `"$(FrameworkPath)\Ilasm.exe" /NOLOGO /DLL /RESOURCE:"@(Compile->'%(RelativeDir)%(Filename).res', ' ')" /OUTPUT:"@(IntermediateAssembly)" ` This assumes the .res file has the same path and name as corresponding `.il` file. – Bondolin Sep 07 '21 at 15:37
1

You could add a "makefile project". The template is under Visual C++, General. This project type allows you to specify custom build commands for the Build, Clean and Rebuild actions. The environment will be setup automatically so you don't have to mess with paths. The C++ IDE also supports creating a custom build rule so you can automatically trigger the right tool (ilasm.exe) from the file name extension (.il).

That's however about as good as it gets. There is no automatic mapping of multiple .il files in the project to a single build command. Writing an nmake.exe makefile is required to get that. And beware that custom build rules support got broken in vs2010.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • Thank you Hans! That's more or less what I need. BTW - any idea why the MSBUILD templates on Codeplex were discontinued? I tried them in VS2010 and got no joy... seemed like a useful contribution. – Mark Nov 01 '10 at 18:59
  • is there any danger in canibalizing a csproj, removing the "csharp.targets" and then adding custom build tasks to comile the IL? Would this work better or worse in terms of source control? – Mark Nov 01 '10 at 19:01
  • Nothing I posted in this answer is in any way related to MSBuild. You give the build commands just like you'd specify them in a pre/post build event. – Hans Passant Nov 01 '10 at 19:12