简体   繁体   English

将网络模块链接到 msbuild 中的单个文件

[英]Linking netmodules to a single file in msbuild

I want to ship a single .NET assembly generated from several C# projects via .netmodules.我想通过 .netmodules 发送从多个 C# 项目生成的单个 .NET 程序集。

I've experimented with ILmerge, but it has other problems.我已经尝试过 ILmerge,但它还有其他问题。 I also had a look at the AssemblyResolve way, but I don't really understand it (both covered here: How to merge multiple assemblies into one? ).我还查看了 AssemblyResolve 方式,但我并不真正理解它(两者都在这里介绍: 如何将多个程序集合并为一个? )。

I've found a possible solution that would work fine for the task via .netmodules.我找到了一个可能的解决方案,它可以通过 .netmodules 很好地完成任务。 No external programs, standard tools, the resulting assembly looks like it came from one project only (in ildasm).没有外部程序、标准工具,生成的程序集看起来像是来自一个项目(在 ildasm 中)。

Here's a MWE: Lib.csproj这是一个 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 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>

The output type of both projects is set to module.两个项目的输出类型都设置为模块。 The "Exe" project uses the "Lib" netmodule via the AddModules switch (required for compilation). “Exe”项目通过 AddModules 开关(编译所需)使用“Lib”网络模块。 This results in two .netmodules in the Exe output directory.这会在 Exe 输出目录中生成两个 .netmodules。

In the final step, the linker is used to link all .netmodules into one Assembly (see https://docs.microsoft.com/en-us/cpp/build/reference/netmodule-files-as-linker-input?view=vs-2017 ):在最后一步中,链接器用于将所有 .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

The question: Can this last step be performed by MSBuild?问题:这最后一步可以由 MSBuild 执行吗? A CMake solution would also be appreciated, but I could not get output type "Module" from CMake. CMake 解决方案也将不胜感激,但我无法从 CMake 获得输出类型“模块”。

I would approach it in one of two ways.我会以两种方式之一来处理它。

Solution 1: Create one more project to bring them all and with a task bind them.解决方案 1:再创建一个项目以将它们全部引入并通过任务绑定它们。

In the .csproj of this project it should be enough to add:在这个项目的 .csproj 中添加:

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

This should pass those files to the compiler task as the AddModules parameter (see usage of Csc task in Microsoft.CSharp.CurrentVersion.targets , line 250).这应该将这些文件作为AddModules参数传递给编译器任务(请参阅Microsoft.CSharp.CurrentVersion.targetsCsc任务的用法,第 250 行)。

This will result in one assembly.这将导致一个程序集。 That assembly will span across the .netmodule files and the file resulting from compiling the third project.该程序集将跨越.netmodule文件和编译第三个项目产生的文件。 It means you need to copy/distribute all of them for that assembly to work.这意味着您需要复制/分发所有这些文件才能使该程序集正常工作。

But you really did that yourself, you already have AddModule items in your Exe.csproj so I'm probably missing something.但是你真的是自己做的,你的Exe.csproj已经有AddModule项目,所以我可能遗漏了一些东西。

Solution 2: Let the second project build the assembly.解决方案 2:让第二个项目构建程序集。

It could be done like so:可以这样做:

<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>

I have a very similar solution.我有一个非常相似的解决方案。 The above is more a hint at how to approach it that a copy-paste solution.以上更多是关于如何处理它的提示,即复制粘贴解决方案。


Disclaimer: I just started experimenting with msbuild recently, I'm happy to improve this answer if something doesn't work.免责声明:我最近才开始尝试使用 msbuild,如果某些东西不起作用,我很乐意改进这个答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM