多框架NuGet构建带有内部依赖关系管理的符号

时间:2012-10-12 21:41:46

标签: nuget nuget-package multiplatform

也许我在这里推动信封,但我迫切希望利用NuGet来缓解我发现自己的DLL地狱。

我们有4个主要产品都存在于相互关联的Mercurial存储库中。所有这些都“共享”了3个核心组件,然后其他一切都是针对特定产品的。现在管理变得非常困难,因为一个产品已升级到.NET 4.0并且正在使用需要.NET 4.0的外部依赖项,而另一个产品因为我甚至不想进入的原因而陷入.NET 3.5。 / p>

因此,我们失去了合并产品差异的能力。

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

但是,我也希望开发人员能够浏览这些项目的来源。

所以我设置了private NuGet serverprivate SymbolSource server。然后我仔细地将所有存储库中的所有更改合并在一起,并丢弃除核心程序集之外的所有内容。然后我精心手工编辑.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个框架目标,你必须用文件夹和约定来做其他方式。
  • 我愿意接受你不能将框架打包在一起并制作两个名为MyProject的软件包(我会做4.0)和MyProject.V35 ......但我无法弄清楚如何拥有相同的框架项目和nuspec,并使用不同的ID来结束2个不同的结果。

按Nuspec文件打包

使用这种方法,我必须自己完成所有msbuilding,然后进行一堆文件复制以设置文件夹结构,如

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

然后我可以运行nuget pack MyProject.nuspec但是没有源代码可以使用这些符号,因为没有.csproj文件,NuGet无法确定从哪里获取所有源文件,而且我不知道请参阅使用目录约定的任何文档。

所以我的问题是:

  1. 有没有办法将源文件添加到基于约定的包中?
  2. 有没有办法用不同的ID将基于项目的包打包两次?
  3. 还有其他途径,或许我没有考虑过吗?
  4. 任何想法都会非常感激。

3 个答案:

答案 0 :(得分:15)

Xavier的回答让我朝着正确的方向前进,并通知了我的Google搜索。我并不完全了解文件声明,在搜索这些行时,我找到了Joshua Flanagan的帖子Tips for building NuGet packages,这非常好。泽维尔和约书亚一起教我一些事情:

  1. 您不必为了构建包而组装符合约定的文件树。最好使用file元素来选择文件并将它们定位到组装好的NuGet包中的目标目录。
  2. NuGet的-Symbols标志不仅适用于.csproj文件的打包。当你在.csproj文件上使用它时,确定,它是如何计算如何打包所有源文件的。但您也可以在包含源文件元素的-Symbols文件上使用.nuspec。普通的NuGet包不包含src目录,但符号包将包含。
  3. 现在,让我描述我在CI服务器上发生的构建过程:

    1. 使用“3.5版本”解决方案配置构建解决方案。
    2. 使用“4.0 Release”解决方案配置构建解决方案。
    3. 使用ILMerge.exe内化某些程序集。我有这些输出(例如)bin\Release-3.5\merged所以我不必将目标程序集重命名为temp.dll,然后才在合并中使用它。
    4. 针对Powershell中的.nuspec构建软件包。
    5. 这是包命令:

      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服务器的包,其中包含用于.NET 3.5和4.0的程序集的DLL,PDB和XML文档,然后是我的私有SymbolServer的单独符号包,其中包含以上所有内容来源。使用{<3}}非常容易查看,我高度建议您下载。

      最后,我测试了所有内容并使用NuGet Package Explorer(除了我自己的私有符号服务器)我能够调试代码并轻松进入源代码。

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

答案 1 :(得分:8)

你知道有一个第三个​​选项吗? 在定位csproj文件时,它还会查找与项目文件同名的nuspec文件(myProject.csproj - &gt; myProject.nuspec)。这意味着您可以通过将结果包定义到nuspec文件中,将额外的元数据添加到生成的包中,同时仍然以csproj文件为目标。从本质上讲,您最终会得到一个包含csproj文件和nuspec文件中合并元数据的包。

在您的特定场景中,如果您想要打包同一项目的多个平台版本,那么在使用nuspec打包之前,您确实必须先构建这些项目。

我建议您创建两个项目,一个针对NET35,另一个针对NET40,并将这些文件作为链接添加到其中一个项目中。因此,您可以构建两个项目,并使用nuspec文件 将所有输出打包到一个NuGet包中。

现在对于符号,我认为你可以有第二个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" />

希望这有助于或至少为您提供一些信息以找到解决方法:)

干杯, 泽维尔

答案 2 :(得分:0)

查看NuGet 2.5中与框架版本相关的参考资料的新功能:http://docs.nuget.org/docs/release-notes/nuget-2.5

您可以选择在csproj文件中使用带有条件引用元素的构建配置(在TargetFrameworkVersion上有条件),然后在所有配置中运行构建,并为net35和net40生成输出,并可选择定位引用你的nupkg。