C#编译/构建增量过程吗?

时间:2016-01-04 06:10:28

标签: c# build-process

我们的解决方案包含许多C#项目。它们之间存在复杂的依赖关系,例如。项目A / B / C,B上的受抚养人,B上的受抚养人。如果我在项目C中更改了一个文件,然后重建解决方案,项目A,B,C将一起重建。

在C ++中,build包含两个进程,编译和链接。如果我在项目C中更改了一个文件,那么我构建解决方案,将编译A和B中的相关文件(其他文件将不会被编译,其.obj将在链接过程中重用),然后进行链接。

在java中,只需重新编译项目C中已更改的文件,其他文件将保留,然后打包到.jar。它重用以前的工作输出(未更改文件的.class)。

总之,C#不会重复使用任何以前的工作输出。它没有任何中间文件,就像Java的.class和C ++的.obj。所以在这一点上,我觉得C#不做增量构建过程。一些小的改变将导致一个大的构建过程。我不明白为什么C#不使用以前的工作输出来加速构建过程。

我不确定我对C#编译/构建过程的理解是否正确。你能帮忙解释一下吗?非常感谢。

6 个答案:

答案 0 :(得分:7)

C#编译器进行渐进式编译,我不知道你在哪里知道它没有。也许,由于解决方案的复杂性,您无法正确理解依赖关系,并且您认为不需要重新编译的项目实际上是必要的。

检查编译器行为的最佳方法是创建一个简单的虚拟解决方案并使用它:

设定:

  1. 创建一个空的Visual Studio C#解决方案。
  2. 添加任意两个项目,AB
  3. 使项目B成为项目A中的引用。
  4. FooInB中实施一个班级B,并将其用于A BarInA中的另一个班级。
  5. 现在让我们通过这个设置玩一下:

    1. 编译解决方案。您将看到两个项目都已编译。
    2. 再次编译解决方案。您将看到没有任何项目编译,两者都是最新的。
    3. 更改BarInA中的实现并重新编译。您 会看到一个项目编译,A。没有必要 再次编译B,因为没有变化。
    4. 更改FooInB中的实现并最后一次编译。您将看到两个项目都编译。这种行为是正确的,A取决于B,因此B中的任何更改都必须再次A重新编译,以确保它指向最新版本的B 1}}。在理论世界中, C#编译器可以检测B中的更改是否在A中没有后果,因此可以"优化"再次建立A,这将是一个噩梦般的场景,每个项目都可以引用不同的和过时的装配版本。
    5. 那就是说,我想指出,AFAIK,C#编译器只会在 project 级别执行增量编译。我不知道任何给定程序集内的类级别的任何增量编译优化。对编译器内部工作有更深入了解的人可能能够澄清这种行为。

答案 1 :(得分:3)

你是对的。

如果项目A依赖于项目B.依赖项目B的变更确实需要重新编译项目A.

如果项目B依赖于项目C.项目B的更改,不会使项目C重新编译。

在Java中,一个类/文件被编译为单个.class文件。因此,当单个文件发生更改时,不会重新编译整个项目。

在分发之前,这些.class文件合并为.jar。如果单个.class文件发生更改,则还需要重新组装整个.jar。

在.Net中,您立即将项目编译为程序集(.dll或.exe),因此单个文件更改需要重新编译整个程序集。

在使用.jar(或.apk等依赖项)运行/调试应用程序的Java环境中可以看到相同的行为。在开发过程中也需要整个.jar。当单个文件发生变化时,整个项目将被重新编译。

您始终可以在解决方案之外放置项目。并且只添加他们生成的.dll的引用。这将最小化编译时间。

答案 2 :(得分:1)

好的..你实际上是在正确的轨道上..如果解决方案中有3个项目,你可以将一个项目的参考提供给另一个。这意味着项目A依赖项目B依赖于项目C ..

构建项目时,所有构建的文件和dll(来自后期构建事件)最终都会出现在该项目的bin文件夹中。

因此,当您构建项目A时,项目C将首先构建(因为A-> B-> C)。项目B使用项目C的构建组件并创建自己的组件。和项目A使用B和C的组件并创建自己的组件。

因此,如果您只构建项目A,如果引用正确,您将在项目A的bin文件夹中看到B和C的所有构建文件。

答案 3 :(得分:1)

我有一个包含许多项目和更多跨项目参考的解决方案。

为简单起见,我假设我有项目A BC

  • A是我的主要桌面文件,它引用了BC
  • B包含Windows表单并引用C
  • C包含商业和数据库逻辑。

我的主要问题是:B需要大约四十五秒才能编译。现在假设我只更改C中的一小段代码,编译器将编译C,然后编译B,而不是A 由于我主要更改C中编译得非常快的代码,所以我总是要等B进行编译。

我从redgate发现了.NET Daemon。这是一个更改构建过程的工具,只有在B的公共API发生更改时才会重建C。这会对您的构建过程产生巨大影响。我想说,根据我的个人经验,它可以节省大约80%的时间用于建造一天......

然而,我只是看了,他们不再卖了它:https://www.red-gate.com/products/dotnet-development/dotnet-demon/

  

Visual Studio 2015将介绍微软的新Roslyn编译器,   我们认为改进使.NET Demon变得多余。

我仍然在使用Visual Studio 2013,但我认为对于使用Roslyn的Visual Studio 2015,对构建过程的初步观察以及有关.NET构建的其他答案可能不再适用。也许它的行为更像是dotnet-deamon版本。

旁注:我的新项目使用IOC容器,所有内容都在主项目中连接,没有太多的交叉项目引用。这也将改善构建过程,因为几乎所有东西都可以并行构建。

答案 4 :(得分:1)

所有版本的C#(MSBuild确实)都支持非依赖项目的增量编译。

VS2003中的C#支持增量编译within projects。有一个uservoice suggestion可以将该功能推向最新的C#版本。

答案 5 :(得分:0)

我已经使用Jenkins MSBuild插件进行了测试,增量版本按预期工作,只会重新编译已更改的项目。

我想要的是进行增量部署,只部署这些已更改/重新编译的dll。现在我如何才能有效地找到重新编译的dll。