Многофункциональная сборка NuGet с символами для управления внутренними зависимостями

Может быть, я проталкиваю конверт здесь, но я отчаянно пытаюсь использовать NuGet, чтобы облегчить DLL-ад, в котором я оказался.

У нас есть 4 основных продукта, которые живут во взаимосвязанных репозиториях Mercurial. Все они "разделяют" 3 основных сборки, а затем все остальное в значительной степени зависит от конкретного продукта. Сейчас стало очень сложно управлять, потому что один продукт был обновлен до.NET 4.0 и использует внешние зависимости, для которых требуется.NET 4.0, а другой продукт застрял в.NET 3.5 по причинам, в которые я даже не хочу входить.

Таким образом, мы утратили способность объединять различия между продуктами.

Чтобы это исправить, я хочу вынуть 3 основные сборки и превратить их в собственный проект с собственным циклом выпуска, а также позаботиться о том, чтобы они могли компилироваться как в.NET 3.5, так и в 4.0, а затем превратить их в Пакеты NuGet, содержащие несколько версий фреймворка.

НО, я также хочу, чтобы разработчики могли просматривать источники этих проектов.

Поэтому я настроил частный сервер NuGet и частный сервер SymbolSource. Затем я аккуратно объединил все изменения из всех репозиториев и выбросил все, кроме сборок ядра. Затем я тщательно отредактировал вручную файлы.csproj, чтобы вместо платформы AnyCPU каждый проект имел цели платформы 3.5 и 4.0, которые задают условные константы (для управления специфичными для платформы функциями, такими как System.Dynamic) и устанавливают версию платформы.

Затем я настроил конфигурации решений для "3.5 Debug", "3.5 Release", "4.0 Debug" и "4.0 Release". Каждый из них нацелен на соответствующую конфигурацию (отладка или выпуск) и платформу (3.5 или 4.0).

Я могу построить все хорошо в Visual Studio для любой платформы. Теперь у меня есть проблема, когда дело доходит до NuGet, потому что есть два способа создания пакета, и у обоих есть слабость, если я что-то упустил:

Пакет по файлу проекта

nuget pack MyProject.csproj -Build -Symbols -Version <insert-from-build-server> -Properties "Configuration=Release;Platform=3.5;"

Проблемы с этим:

  • В то время как версия 3.5 собрана и упакована, в выводе говорится: "Построение проекта для целевой платформы.NETFramework,Version=v4.0".
  • Если я распаковываю полученные пакеты, сборки находятся под lib\net40 что неправильно.
  • Я не думаю, что есть какой-либо способ упаковать 2 целевых фреймворка таким образом, вы должны сделать это иначе с помощью папок и соглашений.
  • Я готов согласиться с тем, что вы не можете упаковать фреймворки вместе и сделать 2 пакета под названием MyProject (который я бы сделал как 4.0) и MyProject.V35 ... однако я не могу понять, как создать один и тот же проект и nuspec. и получить 2 разных результата с разными идентификаторами.

Пакет по Nuspec File

С помощью этого метода я должен сделать всю сборку самостоятельно, а затем выполнить кучу копирования файлов, чтобы настроить структуру папок, такую ​​как

* MyProject.nuspec
* net40
    * MyProject.dll
    * MyProject.pdb
* net35
    * MyProject.dll
    * MyProject.pdb

Тогда я могу бежать nuget pack MyProject.nuspec но тогда нет никакого источника, чтобы идти с символами, потому что без файла.csproj у NuGet нет никакого способа выяснить, где взять все исходные файлы, и я не вижу никакой документации о том, как сделать это, используя соглашения о каталогах или.

Итак, мои вопросы:

  1. Есть ли способ добавить исходные файлы в пакет на основе соглашения?
  2. Есть ли способ дважды упаковать пакет на основе проекта с разными идентификаторами?
  3. Есть ли другой путь, который, возможно, я не рассматривал?

Любые мысли будут высоко ценится.

3 ответа

Решение

Ответ Ксавье привел меня в правильном направлении, а также сообщил мой поиск в Google. Я не был в полной мере осведомлен о декларациях файлов, и при поиске по этим строкам я нашел пост Джошуа Фланагана " Советы по созданию пакетов NuGet", что превосходно. Ксавье и Джошуа вместе научили меня нескольким вещам:

  1. Вам не нужно собирать дерево файлов, соответствующее соглашениям, чтобы создать пакет. Гораздо лучше использовать элемент file, чтобы выбрать файлы и направить их в каталог назначения в собранном пакете NuGet.
  2. Флаг NuSet -Symbols не работает только для упаковки в файл.csproj. Когда вы используете его на .csproj файл, то, конечно, вот как он выясняет, как упаковать все ваши исходные файлы. Но вы также можете использовать -Symbols на .nuspec файл, который включает в себя источник через элементы файла. Обычный пакет NuGet не будет включать каталог src, но пакет Symbols будет.

Итак, позвольте мне описать процесс сборки, который происходит на моем CI-сервере:

  1. Постройте решение, используя конфигурацию решения "3.5 Release".
  2. Постройте решение, используя конфигурацию решения "4.0 Release".
  3. Используйте ILMerge.exe для интернализации некоторых сборок. У меня есть эти выходные данные (например) bin\Release-3.5\merged поэтому мне не нужно переименовывать целевую сборку в temp.dll, прежде чем использовать ее при слиянии.
  4. Постройте пакет против .nuspec в Powershell.

Вот команда package:

nuget pack src\MyProject\MyProject.nuspec -OutputDirectory .\output -Build -Symbols -Version $Version

Обратите внимание, что $Version передается с сервера сборки, поэтому я могу использовать его номер сборки в качестве последней части версии.

Вот файл.nuspec:

<?xml version="1.0"?>
<package>
    <metadata>
        <id>MyProject</id>
        <version>0.0.0</version>
        <title>MyProject</title>
        <authors>David Boike</authors>
        <owners>David Boike</owners>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>MyProject</description>
        <releaseNotes></releaseNotes>
        <copyright>Copyright 2012</copyright>
        <tags>my tags</tags>
    </metadata>
    <files>
        <file src="bin\Release-4.0\merged\MyProject.dll" target="lib\net40" />
        <file src="bin\Release-4.0\merged\MyProject.pdb" target="lib\net40" />
        <file src="bin\Release-4.0\MyProject.xml" target="lib\net40" />
        <file src="bin\Release-3.5\merged\MyProject.dll" target="lib\net35" />
        <file src="bin\Release-3.5\merged\MyProject.pdb" target="lib\net35" />
        <file src="bin\Release-3.5\MyProject.xml" target="lib\net35" />
        <file src="**\*.cs" target="src" />
    </files>
</package>

Обратите внимание, что я удалил много более информативных элементов из своего nuspec, потому что это не имеет значения для внутреннего проекта, подобного этому.

В результате получается пакет для моего частного сервера NuGet, который содержит документацию по DLL, PDB и XML для сборки для.NET 3.5 и 4.0, а затем отдельный пакет символов для моего частного SymbolServer, который включает в себя все вышеперечисленное и источник. Это очень легко увидеть с помощью NuGet Package Explorer, который я настоятельно рекомендую вам скачать.

Наконец, я протестировал все, и с помощью установки Visual Studio, предложенной на Symbolource.org (за исключением моего собственного частного сервера символов), я смог отладить код и легко перейти к исходному тексту.

Еще раз спасибо Ксавье за ​​ведение меня по правильному пути!

Вы знаете, что есть третий вариант? При нацеливании на файл csproj он также будет искать файл nuspec с тем же именем, что и файл вашего проекта (myProject.csproj -> myProject.nuspec). Это означает, что вы можете добавить дополнительные метаданные к результирующему пакету, определив их в файле nuspec, при этом все еще ориентируясь на файл csproj. По сути, вы получите пакет, содержащий объединенные метаданные из файла csproj и файла nuspec.

В вашем конкретном сценарии, если вы хотите упаковать несколько сборок платформы одного и того же проекта, вам действительно придется сначала создать эти проекты перед упаковкой с использованием nuspec.

Я бы посоветовал вам создать два проекта: один для NET35, другой для NET40 и добавить файлы в виде ссылок в один из проектов. Таким образом, вы можете построить оба проекта и упаковать весь вывод в один пакет NuGet, используя файл nuspec.

Теперь, что касается символов, я думаю, что у вас может быть второй файл nuspec (например, myProject.symbols.nuspec), куда вы можете добавить все содержимое проекта (источники и т. Д.), Используя подстановочные символы, как показано ниже.

<file src="myProject35\**\*.cs" target="src" />
<file src="myProject40\bin\Release\*.dll" target="lib\net40" />
<file src="myProject40\bin\Release\*.pdb" target="lib\net40" />
<file src="myProject35\bin\Release\*.dll" target="lib\net35" />
<file src="myProject35\bin\Release\*.pdb" target="lib\net35" />

Надеюсь, что это поможет или, по крайней мере, предоставит вам некоторую информацию, чтобы найти выход:)

Ура, Ксавье

Ознакомьтесь с новыми функциями NuGet 2.5, относящимися к ссылкам, зависящим от версии фреймворка: http://docs.nuget.org/docs/release-notes/nuget-2.5

Возможно, вы можете использовать конфигурации сборки с элементами условных ссылок в файлах csproj (условно для TargetFrameworkVersion), затем запустить сборку во всех конфигурациях и создать выходные данные для net35 и net40 с необязательным таргетингом ссылок в nupkg.

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