Связывание сетевых модулей с одним файлом в msbuild

Я хочу отправить одну сборку.NET, сгенерированную из нескольких проектов C#, через.netmodules.

Я экспериментировал с 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" используется сетевой модуль "Lib" через переключатель AddModules (необходим для компиляции). Это приводит к двум.net-модулям в выходном каталоге Exe.

На последнем этапе компоновщик используется для связывания всех модулей.net в одну сборку (см. 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.

0 ответов

Я бы подошел к этому одним из двух способов.

Решение 1. Создайте еще один проект, чтобы собрать их всех и связать их задачей.

В.csproj этого проекта должно быть достаточно добавить:

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

Это должно передать эти файлы в задачу компилятора как AddModules параметр (см. использование Csc задача в Microsoft.CSharp.CurrentVersion.targets, строка 250).

В результате получится одна сборка. Эта сборка будет охватывать.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, я рад улучшить этот ответ, если что-то не сработает.

Другие вопросы по тегам