【问题标题】:How do you split a Visual Studio Solution?如何拆分 Visual Studio 解决方案?
【发布时间】:2011-01-03 12:35:31
【问题描述】:

我有一个 Visual Studio 2008 解决方案,其中包含 >40 个相互依赖的 C# 和 C++/CLI 项目。使用该解决方案非常缓慢,通常我一次只需要几个项目。因此,我决定将解决方案拆分为包含 3-5 个项目的多个解决方案。 我还想为所有项目保留“完整”解决方案(这对于自动构建或影响所有项目的大型重构操作很方便)。(这是这里的主要条件。否则,拆分当然,将项目转化为解决方案是微不足道的。)

有什么办法吗?

我的第一个想法是创建新的空解决方案并将一些现有项目文件添加到每个解决方案中。但是如果我这样做,VS 就找不到项目引用了(因为它们不在同一个解决方案中)。我可以将引用添加为“普通”文件引用。但如果我这样做,我的“完整”解决方案将不再起作用,因为依赖项丢失了。

编辑:

谢谢大家的回答。我想澄清一下我的问题:我的解决方案包含 44 个项目,不包括测试。所以把它分成两部分并不是我真正的想法,我更多的是考虑 5-8 部分。这就是为什么我想保留“完整”解决方案,让 VS 可以找出完整构建的正确构建顺序。手动维护 8 个单独解决方案的构建顺序(例如在批处理文件中)对我来说似乎很容易出错。

我还想“按逻辑”对项目进行分组(即,我希望将通常在一个解决方案中一起修改的项目放在一起)。但是该分组并不总是与依赖项匹配。例如,假设我有依赖链

A is referenced by B is referenced by C is referenced by D

并想象 A 和 D 经常一起修改,但 B 和 C 很少改变。 (显然,B 使用的 A 的接口必须保持不变。)然后我希望 A 和 D 在一个解决方案中,B 和 C 在另一个解决方案中。但是,如果我想从头开始构建所有项目,那么只有当我可以拥有一个包含 A、B、C 和 D 的完整“完整”解决方案时,这才有效。构建完成后,我可以打开我的 A/D 解决方案并仅编辑/构建这两个项目。

但我担心我的问题没有优雅的解决方案。 (双关语不是故意的)

【问题讨论】:

    标签: visual-studio visual-studio-2008


    【解决方案1】:

    几年后...

    考虑使用 solution filters 加载项目子集,其中也有 MSBuild support,并且通过扩展,您可能可以将其与 Azure DevOps 联系起来。

    【讨论】:

      【解决方案2】:

      您可以制作多个解决方案并将任何项目添加到您喜欢的每个解决方案中。

      您希望构建的项目可能依赖于其他项目。在这种情况下,您需要从使用“项目”引用(引用解决方案中的任何其他项目)更改为使用文件引用(引用该项目创建的程序集 .dll)。

      因此,让我们将它们视为“库”(编译一次,然后大量使用)和“核心”项目(您正在改变很多)。制作解决方案以包含您的“库”项目,并(最好)添加一个构建后步骤,将生成的调试/发布 dll 复制到共享库文件夹中。将核心项目添加到新解决方案中。更改所有核心解决方案引用以通过共享文件夹中的预构建二进制 dll 引用您的库(请参阅发布构建 dll,以便您的最终版本正常工作)。

      如果您更改了库,那么您需要构建库解决方案来重建它,然后使用核心解决方案来重建依赖于该库的应用程序。 (因此,将任何经常更改的代码放在核心解决方案中而不是放在库中是个好主意。您可以在以后成熟时移动项目,和/或在需要时将库放入核心项目中大量修改了一段时间)

      [2018 年编辑] 如今,可以使用本地 nuget 或 npm 服务器分发库,除非有特定原因不采用这种方法,否则这将是首选。

      如果库需要一段时间才能构建并且更改很少,最后一个选择是使它们成为“预编译”库 - 将最终的 dll 文件检查到源代码控制中,然后您的团队成员只需获取最新版本并针对库进行构建,而无需获取或构建他们的源代码。 (要更新这些库,您必须记住在构建之前检查二进制 .dll 文件,然后在重建它们之后再次检查它们,因此您必须权衡优点(更快、更容易的日常构建)与缺点(对库做出更多努力,源代码管理中的二进制文件更大)。

      【讨论】:

      • 这就是我所做的。所以我想没有办法保持所有项目完好无损的“完整”解决方案?
      • 这是该问题的最佳答案,并且正是我工作过的解决方案太大的地方所使用的过程。
      • +1 同意。这仍然是我所知道的最简单有效的方法
      • -1 建议将预编译的二进制文件签入源代码控制。请改用打包解决方案(例如 NuGet)。
      • 公平地说,那是在 2010 年!是的,这些天 nuget/npm 等可能是图书馆更好的解决方案 - 答案已更新。
      【解决方案3】:

      除了这里提到的soldrFunnel 我可以推荐使用 Solution Load Manager。是的,SSD 有帮助,但 VS 有问题:在处理 100 多个项目时,它会崩溃、变得无响应以及出现其他问题。将它们放在一起进行重大重构、重建和调试是必须的,但每天处理较小的项目子集将大大提高性能和满意度。

      ps。我想知道是否有人对漏斗与解决方案负载管理器进行了比较?

      【讨论】:

        【解决方案4】:

        我们的解决方案中有 500 多个项目。将每个项目保留在一个解决方案中是有好处的,尤其是在更改影响所有其他项目的基础项目时(例如,帮助程序类)。

        我们发现继续使用的最佳方法是使用 vsFunnel extension for Visual Studio。它能够在没有项目的情况下加载解决方案。这些项目仍列在解决方案中,但直到需要时才实际加载。当项目通过 UI 打开时,它会按需加载。

        真正的诀窍是从 vsFunnel UI 启用“加载依赖项”。当您打开一个项目时,它会加载所有依赖项目等,这使得处理目标项目变得更加容易。

        例如,在我们的 500 多个项目中,我们通常专注于单个应用程序,它可能有 20 个依赖项目。只有那些被加载,而不是整个 500+。

        提示:选择 Load Dependencies 和 Load None - 然后当您在 UI 中打开目标项目时,所有相关项目都会被加载。

        事实证明,这可以节省大量时间(加上 SSD 驱动器!)

        【讨论】:

          【解决方案5】:

          在您提出问题三年后,我们的团队仍然面临同样的问题 - 不是编译时间,而是没有好的方法将逻辑上分离的内容拆分为单独的解决方案。 p>

          我们最终以soldr (open source) 的形式构建了我们自己的工具,这是一个跨解决方案构建工具。它可以选择利用 nuget 来管理您的代码库或独立工作。这个想法是将您的工作分成逻辑上有意义的尽可能多的解决方案(.sln)。在我们的例子中,我们有一个用于我们的内部框架,然后一个sln 用于我们的每个后端库,一个用于每个产品,等等。每个解决方案都有一个“组件”目录(类似于 nuget“包”目录)我们存储当前解决方案引用的实际库文件(DLL 等)的位置。这些 DLL 必须从新构建的依赖项中更新,目标 sln 才能看到新版本。

          然后我们使用our aforementioned build tool 而不是体力劳动。使用非常简单的规则和约定,它自动推断解决方案间的依赖关系。然后,它可以正确构建整个依赖关系图(或生成一个 MSBuild 文件来这样做),在每个步骤中构建并将输出复制到下一个目标的组件目录。我们还添加了用于过滤将要构建的内容(例如仅构建直接依赖项)、打印依赖关系图、运行单元测试等功能。

          更新:为了利用 nuget,我们添加了对生成具有自动推断依赖关系的 nuspec 文件的支持。

          【讨论】:

            【解决方案6】:

            另一种选择是拥有一个包罗万象的解决方案,并创建不同的构建配置。

            窗口顶部是一个组合框,您可以在其中选择“调试”或“发布”构建配置。将其下拉并选择“配置管理器...”选项。

            在“活动解决方案配置”下,下拉组合框并选择。创建一个新配置(例如,名为“CoreOnly”)并选择“Copy settings from”作为“Debug”。 取消勾选“创建新项目配置”选项。

            现在,您的“CoreOnly”构建配置将出现在窗口中。它显示了所有项目的列表。对于您不想构建的任何项目,请取消选中右侧栏中的“构建”复选框。关闭对话框。

            现在,要构建所有项目,请从配置下拉列表中选择“调试”,然后正常构建。当您的所有项目都已构建后,您可以通过切换到 CoreOnly 配置下拉到仅构建“核心”项目。只要您记得在编辑不在任何核心项目中的代码时构建 Debug(所有项目)构建,就可以了,而且您的 CoreOnly 构建会更快。

            这种方法的缺点是解决方案的打开速度可能非常慢(尽管在 Visual Studio 2008Visual Studio 2010Visual Studio 2012 中这比在 @ 987654324@,所以你可能没有问题)并且如果一个项目没有在你的配置中启用,它永远不会被重建,所以你的构建(或正在运行的应用程序)可能会崩溃 - 如果您认为您对禁用的项目进行了更改(或影响),则必须记住切换回常规的“构建所有内容”配置。

            【讨论】:

            • 谢谢。我从未想过使用构建配置来提高构建速度,但这是个好主意。
            • 是的,它在 VS2008 中运行良好。在 VS2005 中,我们有一个包含 75 个项目的解决方案,打开时间超过 5 分钟,但在 VS2008 中缩短到 20 秒,这使它成为一种更有用的方法。
            【解决方案7】:

            您可能要考虑的另一种方法是仅卸载您不使用的项目,只需右键单击并卸载您不使用的项目...这应该会导致 Visual Studio 更加快速。 VS 内存中保留了很多东西。

            您可以做的其他事情是编辑构建定义并删除任何未修改的项目(取决于您的链接方式......您知道需要/更新/不需要什么)。

            解决方案 -> 右键单击​​ -> 配置管理器 -> 在任何不会更改且不需要的项目上取消选中 Build 每次构建 出于其他原因。这通过使用这些项目的最后一次构建的输出来加速您的构建,无论他们将二进制文件转储到何处。

            注意:您仍然可以右键单击项目并构建以更新其输出,然后重新构建解决方案以获取最新...您可以这样做,而不是来回更改构建配置包括它。

            更新
            本着走性能路线的精神(例如,真的等到 VS 2010),您是否采取了其他一些堆栈溢出问题中列出的措施:Very slow compile times on Visual StudioVisual Studio Optimizations?这些可以产生很大的不同,并且可以在我们wait on VS 2010 to ship时将性能提高到可接受的水平。
            还有一些可以对性能产生良好影响的事情:

            • highly recommend an SSD 如果可以的话。它们成本高昂,但绝对值得,您的解决方案中的文件越多,它们的回报就越大。当我们在工作中订购新机器时,整个开发团队都使用 SSD,差异是惊人的。当您处理大型解决方案时,它会旋转驱动器,将物理磁头切换到数千个位置,只是为了读取文件……这就是 SSD 获胜的地方,寻道时间实际上是 0 毫秒。
            • 同样,免费的解决方案是一个很好的 drafragmenter(仅当您使用物理设备时,不要对 SSD 进行碎片整理)会产生很大的不同...如果您使用的是牢记视觉工作室。我推荐MyDefrag(免费软件),因为它的碎片整理的本机算法会记住目录结构,因此至少物理驱动器不会花费太多时间来切换解决方案中需要的文件,它们都非常关闭在磁盘上。
            • 根据上述 SSD 建议,请记住,廉价驱动器和快速驱动器之间的 SSD 性能存在巨大差异,请在此处进行一些研究。不用担心您的系统,使用免费实用程序such as gParted 您可以非常轻松地移动整个操作系统驱动器,并且您的旧驱动器仍然是备份...只要 SSD 可以容纳您的 C 中的数据,你很好。

            【讨论】:

            • 我试过卸载(应该在问题中这么说)。但是如果我卸载一个库(使用 Jason 的术语),我就不能再构建一个依赖它的项目了。它会因缺少符号而出现构建错误。 (可能与混合 C++/CLI 和 C# 代码有关)
            • 值得注意的是,Visual Studio 2010 团队在性能部门进行了巨大的改进,这可能会使您的问题成为非问题。 VS 2010 发布后,您有多少机会切换到它?您是否因为成本/其他团队成员而被阻止?
            • 感谢配置管理器中的“取消选中构建”。这必须节省几年!
            【解决方案8】:

            没有什么好的方法可以做到这一点。这些工具的构建并未考虑到这一点。相反,您应该尽可能多地将您的项目组合在一起。即使代码量相同,构建的运行速度也会快很多倍。

            您必须克服这样的想法:需要单独的项目才能拥有良好的抽象。这似乎是一种非常干净的强制分离方式。但是这个工具链不值这个价。改用语言功能;类、命名空间等。

            【讨论】:

            • 叹息。不是我希望的答案,但显然是真的。谢谢。
            • Jason Williams 的答案应该被标记为正确的答案。您不应该为了构建过程而拆分或组合项目...
            • @MrLane nDepend 分析不同意你的观点
            【解决方案9】:

            您应该分离关注点,尤其是在 Visual Studio 解决方案中对项目进行分组时。我最近在工作中遇到了这个问题,我必须创建一堆单元测试,而开发人员创建的原始测试包含在解决方案中。起初,我以为OK。我将把我的测试放在这里 b/c 我知道它会起作用,并且不必担心获得正确的依赖关系。但后来在我为每个不同的单元添加了大约 20 个测试项目后,我意识到它的构建速度非常慢。

            然后我决定为每组测试创建一个解决方案,而不是将它们全部放在一个位置。这也有助于更好地组织您的代码,以便更容易找到。例如,我创建了一个文件夹“Test > Unit > MyUnitTest”和“Test > Integration > MyIntegrationTest”。它不仅使以后查找内容变得容易,而且可以帮助您加快构建速度。此外,如果有一群人同时处理代码,每个开发人员都可能会更改项目设置和配置,而不会弄乱其他人。

            一般规则是在一个特定区域中仅将 7 个或更少的项目组合在一起。如果您有超过 7 个项目,那么您可能会创建另一个子类别,以使其更抽象,更容易让人脑一目了然地理解所有复杂的细节(尤其是对于系统新手或者如果您几个月甚至几年后才回到项目中)。

            【讨论】:

            • 正是我的观点。但如果我这样做,我最终会得到 10-15 个独立的解决方案,它们之间存在不可见的依赖关系(即你必须以完全正确的顺序构建它们),这会破坏我所有的自动构建脚本。
            • 然后您可以创建一个脚本以正确的顺序构建它们。我知道有一次我创建了一个解决方案并设置了构建前或构建后的操作,以便以正确的顺序构建所有解决方案。这样您就不必自己手动构建每个解决方案,并且顺序总是正确的。你也可以创建一个批处理文件或类似的东西,但是你会遇到相对路径的问题。如果使用 Build All 的 post-build 解决方案,那么您可以在项目设置中访问 VS 的相对路径变量,这非常有用。
            猜你喜欢
            • 1970-01-01
            • 2015-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多