简体   繁体   中英

Is C# compile/build an incremental process?

Our solution contains lots of C# projects. There are complicated dependency relationship between them, eg. project A/B/C, A dependents on B, B dependents on C. If I change one file in project C, then rebuild the solution, project A,B,C will be rebuild together.

In C++, build contains two process, compile and link. If I change one file in project C, then I build the solution, the relevant file in A and B will be compiled(other's files won't be compiled, their .obj will be reused in link process), then do link.

In java, just the changed file in project C will be recompiled, others file will be kept then package to .jar. It reuse previous work output(not changed file's .class).

In a word, C# doesn't reuse any previous work output. It doesn't have any middle file just like Java's .class and C++'s .obj. So in this point, I feel C# doesn't do incremental build process. Some little change will cause a big build process. I don't understand why C# doesn't use previous work output to accelerate the build process.

I am not sure whether my understanding of C# compile/build process is right. Could you please help to explain more? Thanks a lot.

The C# compiler does incremental compilations, I'm not sure where you got the idea that it doesn't. Maybe, due to the complexity of your solution, you are not understanding the dependencies correctly and projects that you assumed would not need to be recompiled are in fact necessary.

The best way to check the compiler's behavior is to create a simple dummy solution and play around with it:

Setup:

  1. Create an empty Visual Studio C# solution.
  2. Add any two projects, A and B .
  3. Make project B a reference in project A .
  4. Implement a class FooInB in B and use it in another class in A BarInA .

Now lets play around a bit with this setup:

  1. Compile the solution. You will see that both projects compile.
  2. Compile the solution again. You will see that none of the projects compile, both are up to date.
  3. Change the implementation in BarInA and compile again. You will see that only one project compiles, A . There is no need to compile B again as there are no changes.
  4. Change the implementation in FooInB and compile one last time. You will see that both projects compile. This behaviour is correct, A depends on B so any change in B will necessarily need that A recompile again to make sure it is pointing to the latest version of B . In a theoretical world where the C# compiler could detect if the changes in B have no consequences in A and could therefore "optimize" away building A again, would be a nightmare scenario where each project could be referencing different and outdated assembly versions.

That said, I'd like to point out that, AFAIK, the C# compiler will only perform incremental compilations at project level. I am not aware of any incremental compilation optimizations at class level inside any given assembly. Someone with much more insight in the inner workings of the compiler might be able to clarify this behavior.

You are kind of right.

If project A depends on project B. A change in dependent project B, does make a recompile of project A necessary.

If project B depends on project C. A change in project B, does not make project C recompile.

In Java, one class/file is compiled to a single .class file. Therefor the whole project does not to be recompiled when a single file changes.

Before distribution these .class files are combined into a .jar. If a single .class file changes, the whole .jar also needs to be reassembled.

In .Net you immediately compile a project to an assembly (.dll or .exe), so a single file change, needs a recompile of the whole assembly.

The same behavior is seen on Java environments where the .jar (or dependencies like .apk) is used to run/debug the application. The whole .jar is also needed during development. And the whole project is recompiled when a single file changes.

You can always place projects, outside of your solution. And only add a reference the .dll they produce. This will minimize compile times.

Ok.. you are actually on the right track.. if there are 3 projects in the solution, you can give reference of one project to the other. It means that project A dependent on project B dependent on project C..

When you build a project, all the built files and dlls (from the post build events ) end up in the bin folder of that project.

So when you build project A, project C will build first (because A->B->C). Project B uses the built components of project C and creates its own components. and project A uses components of B and C and creates its own components.

Because of this, if you only build project A, if the referencing is correct, you will see all build files of B and C in the bin folder on project A.

I have a solution with many projects and even more cross-project references.

For simplicity lets say I have project A B and C .

  • A is my main desktop exe which reffers B and C
  • B contains windows forms and reffers C
  • C contains buisness and database logic.

My main problem is: B takes about fourty five seconds to compile. Now let's say I only change a small line of code in C , the compiler will compile C and after that it will compile B , than A Since I mostly change code in C which compiles very fast I always have to wait for B to compile.

I discovered .NET Daemon from redgate. This is a tool which changes the build process and will only rebuild B if the public API from C changes. This can have a massive impact on your build process. I would say, it saves about 80% of the time spent building over a day based on my personal experience..

However, I just looked and they aren't selling it anymore: https://www.red-gate.com/products/dotnet-development/dotnet-demon/

Visual Studio 2015 will introduce Microsoft's new Roslyn compiler, with improvements which we believe make .NET Demon redundant.

I am still on Visual Studio 2013 but I think initial observation of the build process and the other answers about the NET build may not be true anymore for Visual Studio 2015 with Roslyn. Maybe it behaves more like the dotnet-deamon build.

On a side note: My newer projects use IOC containers, everything is wired up in the main project without much cross project references. This will also improve the build process since almost everything can be build in parallel.

All versions of C# (MSBuild really) support incremental compilation of non-dependent projects.

C# in VS2003 supported incremental compilation within projects . There is a uservoice suggestion to bring the feature forward into the latest C# version.

I've tested with Jenkins MSBuild plugin, the incremental build worked as expected, and only changed project will be recompiled.

What I want is to do a incremental deploy, deploy only these changed/recompiled dlls. Now how can I efficiently find the recompiled dlls.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM