多框架 NuGet 构建,带有用于内部依赖管理的符号 [英] Multi-framework NuGet build with symbols for internal dependency management

查看:16
本文介绍了多框架 NuGet 构建,带有用于内部依赖管理的符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

也许我在这里挑战极限,但我迫切希望利用 NuGet 来缓解我陷入的 DLL 地狱.

Maybe I'm pushing the envelope here, but I'm desperate to leverage NuGet to ease the DLL Hell that I've found myself in.

我们有 4 种主要产品,它们都存在于相互关联的 Mercurial 存储库中.他们所有人都共享"了 3 个核心组件,然后其他所有内容都几乎是特定于产品的.现在变得非常难以管理,因为一个产品已升级到 .NET 4.0 并且正在使用需要 .NET 4.0 的外部依赖项,而另一种产品由于我什至不想进入的原因卡在 .NET 3.5 中.

We have 4 main products that all live in interrelated Mercurial repositories. All of them "share" 3 core assemblies and then everything else is pretty much product-specific. It's become very difficult to manage now because one product has been upgraded to .NET 4.0 and is using external dependencies that require .NET 4.0, while another product is stuck in .NET 3.5 for reasons I don't even want to get into.

因此,我们已经失去了合并产品之间差异的能力.

So, we have lost our ability to merge differences between products.

要修复它,我想取出 3 个主要程序集,并将它们变成具有自己发布周期的自己的项目,并注意确保它们可以针对 .NET 3.5 和 4.0 进行编译,然后将它们转换为包含多个框架版本的 NuGet 包.

To fix it, I want to take out the 3 main assemblies, and turn them into their own project with their own release cycle, and take the care to make sure they can compile against both .NET 3.5 and 4.0, and then turn those into NuGet packages containing multiple framework versions.

但是,我还希望开发人员能够浏览这些项目的源代码.

BUT, I also want developers to be able to browse the source of these projects.

所以我设置了一个私有NuGet服务器私有 SymbolSource 服务器.然后我小心地将所有存储库中的所有更改合并在一起,并丢弃了除我的核心程序集之外的所有内容.然后我煞费苦心地手工编辑了 .csproj 文件,以便每个项目都有 3.5 和 4.0 的平台目标而不是 AnyCPU 平台,它们指定条件常量(用于控制特定于平台的功能,如 System.Dynamic)并设置框架版本.

So I set up a private NuGet server and a private SymbolSource server. Then I carefully merged all the changes from all repositories together, and threw out everything except my core assemblies. Then I painstakingly hand-edited the .csproj files so that instead of the AnyCPU platform, each project has platform targets of 3.5 and 4.0, which specifies conditional constants (to control platform-specific features like System.Dynamic) and sets the framework version.

然后我为3.5 Debug"、3.5 Release"、4.0 Debug"和4.0 Release"设置解决方案配置.每一个都针对适当的配置(调试或发布)和平台(3.5 或 4.0).

Then I set up solution configurations for "3.5 Debug", "3.5 Release", "4.0 Debug", and "4.0 Release". Each one targets the appropriate Configuration (Debug or Release) and Platform (3.5 or 4.0).

我可以在 Visual Studio 中为任何平台构建一切.现在我在谈到 NuGet 时遇到了一个问题,因为有两种方法可以创建一个包,并且都有一个弱点,除非我遗漏了什么:

I can build everything fine within Visual Studio for any platform. Now I have a problem when it comes to NuGet, because there are two ways to create a package, and both have a weakness, unless I'm missing something:

按项目文件打包

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

这样做的问题是:

  • 在构建和打包 3.5 版本时,输出显示Building project for target framework '.NETFramework,Version=v4.0'."
  • 如果我解压生成的包,则程序集位于 lib et40 下,这是错误的.
  • 我认为没有办法以这种方式打包 2 个框架目标,您必须使用文件夹和约定以另一种方式进行.
  • 我愿意接受您不能将框架打包在一起并制作 2 个名为 MyProject(我将使用 4.0)和 MyProject.V35 的包......但是我不知道如何拥有相同的project 和 nuspec 并以不同的 id 得到 2 个不同的结果.
  • While the 3.5 version is built and packaged, the output says "Building projecct for target framework '.NETFramework,Version=v4.0'."
  • If I unpack the resulting packages, the assemblies are under lib et40 which is wrong.
  • I don't think there is any way to package 2 framework targets this way, you have to do it the other way with folders and conventions.
  • I am willing to accept that you can't package the frameworks together and make 2 packages called MyProject (which I would do as 4.0) and MyProject.V35 ... however I can't figure out how to have the same project and nuspec and wind up with 2 different results with different ids.

按 Nuspec 文件打包

用这种方法,我必须自己做所有的msbuilding,然后做一堆文件复制来设置一个文件夹结构,比如

With this method, I have to do all the msbuilding myself and then do a bunch of file copying to set up a folder structure like

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

然后我可以运行 nuget pack MyProject.nuspec 但是没有与符号一起使用的源,因为没有 .csproj 文件,NuGet 无法确定从哪里获取所有源文件,我也没有看到任何关于如何使用目录约定来做到这一点的文档.

Then I can run nuget pack MyProject.nuspec but then there is no source to go with the symbols, because without the .csproj file, NuGet has no way to figure out where to get all the source files, and I don't see any documentation on how to do this using directory conventions either.

所以我的问题是:

  1. 有没有办法将源文件添加到基于约定的包中?
  2. 有没有办法将基于项目的包以不同的 id 打包两次?
  3. 还有其他可能我没有考虑过的途径吗?

任何想法将不胜感激.

推荐答案

Xavier 的回答让我找到了正确的方向,也为我的 Google 搜索提供了信息.我并不完全了解文件声明,当沿着这些方向搜索时,我发现了 Joshua Flanagan 的帖子 构建 NuGet 包的技巧,非常棒.Xavier 和 Joshua 一起教会了我一些事情:

Xavier's answer led me in the proper direction, and also informed my Google searching. I was not fully aware of the file declarations, and when searching along those lines, I found Joshua Flanagan's post Tips for building NuGet packages, which is excellent. Xavier and Joshua together taught me a few things:

  1. 您不必为了构建包而组装符合约定的文件树.最好使用 file 元素来选择文件并将它们定位到组装好的 NuGet 包中的目标目录.
  2. NuGet 的 -Symbols 标志不仅适用于打包 .csproj 文件.当您确实在 .csproj 文件上使用它时,当然,这就是它如何确定如何打包所有源文件的方式.但是您也可以在包含源文件元素的 .nuspec 文件上使用 -Symbols.普通的 NuGet 包不会包含 src 目录,但 Symbols 包会.
  1. You don't have to assemble a conventions-conforming file tree in order to build a package. It's much better to use the file element to select files and target them to a destination directory within the assembled NuGet package.
  2. NuGet's -Symbols flag doesn't just work for packaging on a .csproj file. When you do use it on a .csproj file, then sure, that's how it figures out how to package up all your source files. But you can also use -Symbols on a .nuspec file that includes the source via file elements. The normal NuGet package will not include the src directory, but the Symbols package will.

现在,让我描述一下我的 CI 服务器上发生的构建过程:

So now, let me describe my build process as it occurs on my CI server:

  1. 使用3.5 Release"解决方案配置构建解决方案.
  2. 使用4.0 Release"解决方案配置构建解决方案.
  3. 使用 ILMerge.exe 内部化一些程序集.我有这些输出到(例如) binRelease-3.5merged 所以我不必在合并中使用它之前将目标程序集重命名为 temp.dll.李>
  4. 在 Powershell 中针对 .nuspec 构建包.
  1. Build the solution using the "3.5 Release" solution configuration.
  2. Build the solution using the "4.0 Release" solution configuration.
  3. Use ILMerge.exe to internalize some assemblies. I have these output to (for example) binRelease-3.5merged so I don't have to monkey with renaming the target assembly to temp.dll before I use it in the merge.
  4. Build the package against the .nuspec in Powershell.

这里是打包命令:

nuget pack srcMyProjectMyProject.nuspec -OutputDirectory .output -Build -Symbols -Version $Version

请注意,$Version 是从构建服务器传入的,因此我可以将其构建号用作版本的最后一部分.

Note that $Version is passed in from the build server so I can use its build number as the last part of the version.

这是 .nuspec 文件:

Here is the .nuspec file:

<?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="binRelease-4.0mergedMyProject.dll" target="lib
et40" />
        <file src="binRelease-4.0mergedMyProject.pdb" target="lib
et40" />
        <file src="binRelease-4.0MyProject.xml" target="lib
et40" />
        <file src="binRelease-3.5mergedMyProject.dll" target="lib
et35" />
        <file src="binRelease-3.5mergedMyProject.pdb" target="lib
et35" />
        <file src="binRelease-3.5MyProject.xml" target="lib
et35" />
        <file src="***.cs" target="src" />
    </files>
</package>

请注意,我已经从我的 nuspec 中删除了很多信息量更大的元素,因为这对于像这样的内部项目来说并不重要.

Note that I have removed a lot of the more informative elements from my nuspec because it just doesn't matter for an internal project like this.

结果是我的私有 NuGet 服务器的一个包,其中包含 .NET 3.5 和 4.0 程序集的 DLL、PDB 和 XML 文档,然后是我的私有 SymbolServer 的单独符号包,其中包括上述所有内容以及来源.这很容易通过我高度 推荐你下载.

The result is a package for my private NuGet server that contains DLL, PDB, and XML documentation for the assembly for both .NET 3.5 and 4.0, and then a separate symbols package for my private SymbolServer that includes all of the above plus the source. This is very easy to view with the NuGet Package Explorer which I highly recommend you download.

最后,我使用 symbolsource.org 建议的 Visual Studio 设置测试了所有内容(除了我自己的私有符号服务器)我能够调试代码并轻松进入源代码.

Finally, I tested everything and with the Visual Studio setup suggested at symbolsource.org (except with my own private symbol server) I was able to debug the code and easily step into the source.

再次感谢 Xavier 带领我走上正确的道路!

Thanks again to Xavier for leading me down the right path!

这篇关于多框架 NuGet 构建,带有用于内部依赖管理的符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆