Многофункциональная сборка 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 нет никакого способа выяснить, где взять все исходные файлы, и я не вижу никакой документации о том, как сделать это, используя соглашения о каталогах или.
Итак, мои вопросы:
- Есть ли способ добавить исходные файлы в пакет на основе соглашения?
- Есть ли способ дважды упаковать пакет на основе проекта с разными идентификаторами?
- Есть ли другой путь, который, возможно, я не рассматривал?
Любые мысли будут высоко ценится.
3 ответа
Ответ Ксавье привел меня в правильном направлении, а также сообщил мой поиск в Google. Я не был в полной мере осведомлен о декларациях файлов, и при поиске по этим строкам я нашел пост Джошуа Фланагана " Советы по созданию пакетов NuGet", что превосходно. Ксавье и Джошуа вместе научили меня нескольким вещам:
- Вам не нужно собирать дерево файлов, соответствующее соглашениям, чтобы создать пакет. Гораздо лучше использовать элемент file, чтобы выбрать файлы и направить их в каталог назначения в собранном пакете NuGet.
- Флаг NuSet -Symbols не работает только для упаковки в файл.csproj. Когда вы используете его на
.csproj
файл, то, конечно, вот как он выясняет, как упаковать все ваши исходные файлы. Но вы также можете использовать-Symbols
на.nuspec
файл, который включает в себя источник через элементы файла. Обычный пакет NuGet не будет включать каталог src, но пакет Symbols будет.
Итак, позвольте мне описать процесс сборки, который происходит на моем CI-сервере:
- Постройте решение, используя конфигурацию решения "3.5 Release".
- Постройте решение, используя конфигурацию решения "4.0 Release".
- Используйте ILMerge.exe для интернализации некоторых сборок. У меня есть эти выходные данные (например)
bin\Release-3.5\merged
поэтому мне не нужно переименовывать целевую сборку в temp.dll, прежде чем использовать ее при слиянии. - Постройте пакет против
.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.