1

我想通过 .netmodules 从几个 C# 项目生成一个 .NET 程序集。

我已经尝试过 ILmerge,但它还有其他问题。我还查看了 AssemblyResolve 方式,但我并不真正理解它(两者都在这里介绍:如何将多个程序集合并为一个?)。

我找到了一个可能的解决方案,可以通过 .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 获得输出类型“模块”。

4

1 回答 1

1

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

解决方案 1:再创建一个项目将它们全部带入并通过任务绑定它们。

在这个项目的 .csproj 中添加以下内容就足够了:

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

这应该将这些文件作为参数传递给编译器任务(参见第 250 行中任务的AddModules用法)。CscMicrosoft.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,如果出现问题,我很乐意改进这个答案。

于 2020-02-28T11:36:48.893 回答