将Netmodules链接到msbuild中的单个文件

时间:2019-04-02 06:19:00

标签: c# msbuild linker netmodules

我想通过.netmodules运送由多个C#项目生成的单个.NET程序集。

我已经尝试了ILmerge,但是它还有其他问题。我也看过AssemblyResolve的方式,但我不太了解(都在这里介绍:How to merge multiple assemblies into one?)。

我找到了一个可能的解决方案,该解决方案通过.netmodules可以很好地完成任务。没有外部程序,标准工具,生成的程序集看起来就像是来自一个项目(在ildasm中)。

这是MWE:Lib.csproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutputType>Module</OutputType>
    <OutputPath>bin\</OutputPath>
    ...
  </PropertyGroup>
  ...
  <ItemGroup>
    <Compile Include="Lib.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Exe.csproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <OutputType>Module</OutputType>
    <OutputPath>bin\</OutputPath>
    ...
  </PropertyGroup>
  ...
  <ItemGroup>
    <AddModules Include="..\Lib\bin\Lib.netmodule" />
    <Compile Include="Program.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

两个项目的输出类型都设置为模块。 “ Exe”项目通过AddModules开关(编译所需)使用“ Lib”网络模块。这样会在Exe输出目录中产生两个.netmodules。

最后一步,使用链接器将所有.netmodules链接到一个程序集中(请参见https://docs.microsoft.com/en-us/cpp/build/reference/netmodule-files-as-linker-input?view=vs-2017):

link Lib.netmodule Exe.netmodule -subsystem:console -out:Exe.exe -ltcg -entry:Exe.Program.Main

问题:这最后一步可以由MSBuild执行吗? CMake解决方案也将不胜感激,但我无法从CMake获取输出类型“ Module”。

1 个答案:

答案 0 :(得分:1)

我会以两种方式之一来处理它。

解决方案1:再创建一个项目以将其全部合并,并通过任务将其绑定。

在该项目的.csproj中,应该足以添加:

<ItemGroup>
    <AddModules Include="Lib.netmodule" />
    <AddModules Include="Exe.netmodule" />
</ItemGroup>

这应将这些文件作为AddModules参数传递给编译器任务(请参阅Csc,第250行中Microsoft.CSharp.CurrentVersion.targets任务的用法)。

这将导致一个组装。该程序集将跨越.netmodule文件和编译第三个项目所产生的文件。这意味着您需要复制/分发所有组件才能使该组件正常工作。

但是您确实是这样做的,您的AddModule中已经有Exe.csproj个项目,因此我可能缺少了一些东西。

解决方案2:让第二个项目构建程序集。

可以这样做:

<ItemGroup>
  <ModulesToInclude Include="Lib.netmodule" />
</ItemGroup>

<Target Name="LordOfTheRings">
  <!-- The below uses the netmodule generated from VB code, together with C# files, to generate the assembly -->
  <Csc Sources="@(Compile)"
       References="@(ReferencePath)"
       AddModules="@(ModulesToInclude)"
       TargetType="exe" />
</Target>

<Target Name="AfterBuild" DependsOnTargets="LordOfTheRings">
  <!-- This target is there to ensure that the custom target is executed -->
</Target>

我有一个非常相似的解决方案。上面的内容更多地暗示了如何使用复制粘贴解决方案。


免责声明:我最近才开始尝试使用msbuild,如果某些方法不起作用,我很乐意改进此答案。