.NET Core build rebuilding projects that have not changed - msbuild

I have some C# and F# projects that were migrated from .NET Framework 4.6.1 to .NET Core 2.0. After modifying one source file and building in VS 2017 it keeps rebuilding several (sometimes all) projects every time I select "Build Solution" without further changes. I can see this from the final line of the output:
========== Build: 3 succeeded, 0 failed, 11 up-to-date, 0 skipped ==========
Building from the command line with dotnet build also take a long time, though I can't be sure that it's rebuilding, because it doesn't output a count of how many projects were rebuilt, like VS does.
How do I troubleshoot why unchanged projects are being rebuilt?

There are still a few bugs with the "up-to-date" check in visual studio, especially if there are items marked as "copy to output directory" in subfolders.
The projects aren't actually recompiled, but an MSBuild-"build" is triggered that will check for all inputs (and then do nothing). For the "up-to-date" projects, VS skips invoking MSBuild completely which makes it faster.
You can check for similar issues or report new issues for the up-to-date check at https://github.com/dotnet/project-system

Related

Debugging Visual Studio build dependencies - avoiding unnecessary project builds

Using Visual Studio 2015 Enterprise on Windows 10 64-bit. Working with a solution which contains a bunch of C# library projects.
When building the solution, then building it again, then repeating this, each time there are a handful of projects which build every time. There have been no changes to any of the source files, yet VS still wants to build these projects.
Anyone have any tips on debugging the build dependencies to figure out WHY it wants to build these projects each time?

MSBuild sets TargetFrameworkDirectories incorrectly

When I try to build a C# Console Application (and possibly others) it appears that TargetFrameworkDirectories is set incorrectly; in particular it omits the Facades directory.
Since I've been trying to diagnose the problem for a while, here is a list of possibly relevant facts.
The problem manifested itself when trying to build in Visual Studio 2012 a project that referenced the Reactive Extension libraries (managed using NuGet). The error (or warning) was warning MSB3267: The primary reference "System.Runtime", which is a framework assembly, could not be resolved in the currently targeted framework. ".NETFramework,Version=v4.5". The problem occurs during msbuild executing ResolveAssemblyReference
I can reproduce the error from command line with msbuild, which seems simpler
Other workstations do not exhibit the problem. Running msbuild with verbosity turned up on a good machine and on the bad machine turned up some differences in the log file
On a good machine TargetFrameworkDirectories (a parameter of ResolveAssemblyReference) is C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\,C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\Facades\ but on a bad machine it lacks the second entry (the Facades directory)
Scanning through the good and bad msbuild log files the following differences turn up:
Target AssignProjectConfiguration is skipped in the bad build, but runs in the good build
A number of targets like GetInstalledSDKLocations are skipped in the good build but are not mentioned in the bad build
The ResolveAssemblyReference task is passed Assemblies with Implicit=true in the good build but not in the bad build.
The ResolveAssemblyReference task is passed the task parameter TargetFrameworkDirectories with C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\ in the bad build, but the good build the Facades directory (see above) as a second item.
Since this is driven by C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets I diffed that file on the good and bad machine. They contained many differences. The first difference is the project element (line 17) which has an extra attribute TreatAsLocalProperty="OutDir" on the good machine. On the good machine the targets file contains more comments, such as <!-- VS10 without SP1 and without VS11 will not have VisualStudioVersion set, so do that here -->. Jumping to the AssignProjectConfiguration target, the good machine has Condition="'$(CurrentSolutionConfigurationContents)' != '' or '#(ProjectReference)'!=''" while the bad machine has Condition="'#(ProjectReference)'!=''" (which I assume explains why it was skipped).
One final thing I tried was repairing "Microsoft .NET Framework 4.5" and "Microsoft .NET Framework 4.5 Multi-Targeting Pack". It did not help.
Any advice would be appreciated, especially if I can avoid reinstalling Visual Studio 2012!
UPDATE: It seems that reinstalling .NET 4.5 followed by "merely" repairing VS2012 solved my problems. My best guess as to what caused this problem is that somehow my Microsoft.Common.targets was altered to an old version. I have no idea what could have altered the targets file.
As suggested by #leppie it was a .NET problem. For some reason repairing .NET did not seem to fix the problem. However reinstalling .NET 4.5 (followed by repairing VS2012) did seem to fix it.

BizTalk 2010 project compilation using MSBuild

I am trying to use MSBuild to compile a solution with a few BizTalk 2010 projects (maps, schemas, pipelines) and a few non-BizTalk projects (console app, web app).
MSBuild gets triggered by Nant. The problem is that, everytime I run the compilation, the BizTalk projects get recompiled (and the assembly version number changes). This happens even if there are absolutely no changes to any part of the entire solution.
In other words, If I build the solution once, the assemblies get created fine. Immediately, if I build again, the non-BizTalk assemblies do not get re-created (MSBuild reports Skipping target "CoreCompile" because all output files are up-to-date with respect to the input files). But, the BizTalk assemblies happily get re-created. This is annoying.
Please can someone help/advise?
BizTalk Server 2009 and 2010 .btproj project files are, indeed, MSBuild projects. As you have noticed, the way standard BizTalk targets are authored prevents incremental build of BizTalk projects.
Fortunately, MSBuild is extensible and can be customized in many ways. Please, follow the instructions on this post to to alter the standard build logic of .btproj files in order to add incremental support for your build system.

Why does Tfs2010 build my Wix project before anything else?

A similar question was asked and answered about a year ago, but was either a different issue (everything was in beta) or misdiagnosed. It's located here: MSbuild task fails because "Any CPU" solution is built out of order.
My issue is that I have a wix installer project, and after upgrading to Tfs2010 on monday, the build fails on linking because it can't find the build product of the Wpf application in the project. After some digging, it's because it hasn't been built yet. Building in Vs2010 works as normal. The wix project is set to depend on the Wpf project, and when viewing Project Build Order in the IDE, everything looks as normal.
The problem was originally encountered with only two platform definitions in the solution; x86 and x64. There are also two flavors, Debug and Release, and TFSBuild.proj is set to build all four combinations. There was no occurence of AnyCPU anywhere. Per the referenced question above, I tried changing the Wpf project to use AnyCPU so that it would be built first. At this point, the wix project used the exact configuration and the Wpf project used the flavor with AnyCPU. However, doing so didn't seem to change anything.
I'm using the Tfs2010 RTM, Vs2010 RTM, and the most recent version of Wix, which at the time of this writing is 3.5.1602.0, from 2010-04-02. Anyone else running into this?
2010-04-27: After a fair amount of digging, and reproducing on a cloned VM build machine, I believe I know what's going on and also what's failing, but I don't quite know how to fix it.
The situation is that this bug seems to exhibit symptoms based on pure luck-of-the-draw project ordering in the solution file. It appears as if the solution file will just blindly build the projects in the order they appear, relying on its ability to detect unbuilt references and build them on demand when needed.
In my particular solution file, my Wix project was ordered before my Wpf application project. This resulted in the Wix project being built first, and while the dependency on the Wpf project was detected correctly, the actual MSBuild task was skipped because of the undefined $(BuildProjectReferences) variable I mention a couple of comments down from the main post in this thread. With MSBuild verbosity still on diagnostic, BuildProjectReferences can be seen as undefined building the Wix project, and it can be seen defined as true upon building the Wpf project within the task to build the Wix project. Yet, when tested, it evaluates undefined again, the task is skipped, and the Wix build fails because it can't find the build output of the unbuilt Wpf project.
So bottom line: project dependency is skipped because of bad $(BuildProjectReferences) variable. Interestingly, this variable is present only in the Wix2010.targets file, and not in wix.targets; I guess that's why this is just showing up after I installed Tfs2010 and Vs2010.
The solution: How do I make sure that BuildProjectReferences is passed along correctly to the subsequent MSBuild tasks? Is there something special with variable scoping going on?
2010-09-14: A bug was opened for this issue in the WiX toolset: http://sourceforge.net/tracker/?func=detail&atid=642714&aid=2990231&group_id=105970 and fixed a while ago. Hopefully, this is no longer an issue. If so, please do open a new bug.
To address your comment directly, nothing in my solution has an AnyCPU configuration in their build files. I created the AnyCPU configurations only to test the solution suggested by the thread I linked to in my original post. After it didn't work, I removed the AnyCPU configurations again.
Furthermore, the projects are in the same solution file, however in separate solution folders (interface folder, installer folder) if that matters.
Interestingly enough, I was going to make a small sandbox example so that I could illustrate the problem I was having, however after creating my tiny sample solution, I couldn't get the error to reproduce. This makes me think that perhaps this is a result of using a team project that was upgraded from a Tfs2008 team project rather than one that was created fresh in Tfs2010. I may try branching my project into a new one to test this theory if I can't figure out why the test solution works.
p.s. also, I'm new to stackoverflow--why on earth are comments limited in length if the "answer your own question" workflow is intended only to provide concrete answers?
So I threw the build verbosity up to diagnostic and read through it today, and one line in particular stood out to me:
Task "MSBuild" skipped, due to false condition; ('#(_ProjectReferenceWithConfiguration)'!='' and '$(BuildingInsideVisualStudio)' != 'true' and '$(BuildProjectReferences)' == 'true' and '#(_MSBuildProjectReferenceExistent)' != '') was evaluated as ('..\WpfApp\WpfApp.csproj'!='' and '' != 'true' and '' == 'true' and '..\WpfApp\WpfApp.csproj' != '').
This was seen as my installer project was attempting to build my wpf project since the wpf project is referenced. In particular, for some reason $(BuildProjectReferences) is evaluating to '' when I'm fairly sure it should be 'true'.
However earlier in the log, at the beginning of the MSBuild task for the WpfApp project, I saw this:
Task "MSBuild" (TaskId:15)
...
Initial Properties:
...
BuildProjectReferences = true
So the property was indeed correct up until the beginning of the task, but then was apparently overwritten? I'm sort of unclear as to how these properties get set.
Its a bug, a bug, a bug. I don't know, who is responsible, but here's a working dirty filthy hack:
Open your .sln file in notepad.
Find your wix projects in the list of projects.
Cut them out, and paste them back after all other projects are listed.
Cry in the shower as you try to scrub the dirty off, only to emerge hours later, rubbed raw and still with the stench of filth clinging to you like corpse's skin.
Following Rob Mensching's edit of my original post, it seems that this has indeed been fixed in WiX 3.6.0917.0 at the latest.
I was seeing this problem (wix 3.7 not finding the dependent project output) in my local and TFS builds (for both VS2010 and VS2012).
I finally got around it by setting the msbuild property /m:1 to only use a single build process. I set /m to allow msbuild to figure out how many processes it could use to simultaneously build with.
I faced with a same problem today and find a solution like this:
Open your solution file on notepad the find your setup project and change postProject setting. This will tell msbuild this project should wait another project to build. I don't know why but it is not added by default.
Project("{GUID}") = "MyInstaller", "MyInstallerPath", "{Installer Project GUID}"
ProjectSection(ProjectDependencies) = postProject
{Prebuild Project GUID} = {Prebuild Project GUID}
EndProjectSection
EndProject
'Prebuild Project GUID' is the number on the right of the project that you want to install.
TFS uses a set of properties to control the names of the solutions and configurations to build ( iterate through ). For each combination of solution and configuration it then uses the project dependencies / build order to control the order of the projects getting built. It's possible that your EXE/DLL's are AnyCPU and that your WiX is x86 and that although the WiX has a dependency on the EXE/DLL the x86 is built before your AnyCPU. Or maybe they are even in different solutions so it's kind of hard to tell without looking at your source but that's basically how it works.
What we did is to first report the bug to wix and then we found your question.
We solved the problem on our side by saying that, by default, the wix project will build the references. We updated the file C:\Program Files\MSBuild\Microsoft\WiX\v3.5\wix2010.targets by setting <BuildProjectReferences>True</BuildProjectReferences> in the project which set the path. So, yes, we have done this manually ; we have reported the bug as well as our fix.

Advantages of using MSBuild or NAnt versus running DevEnv.exe from command-line

Can anyone explain what advantages there are to using a tool like MSBuild (or NAnt) to build a collection of projects versus running DevEnv.exe from the command-line?
A colleague I had worked with in the past had explained that (at least with older versions of Visual Studio) using DevEnv.exe was much slower than the other techniques, but I haven't read any evidence of that or if that is now a moot point now that starting with 2005, Visual Studio uses MSBuild under the hood.
I know one advantage of using MSBuild allows you to build your projects without requiring Visual Studio to be installed on the build machines, but I wasn't sure if there were others.
One reason is because there's much more to building a product than just compiling it. Tasks such as creating installs, updating version numbers, creating escrows, distributing the final packages, etc. can be much easier because of what these tools (and their extensions) provide.
While you could do all this with regular scripts, using NAnt or MSBuild give you a solid framework for doing all this. There's a lot of community support for both, including additional tasks that can be downloaded (such as the MSBuild Community Tasks Project). Plus, there's support for them in numerous third party and open source products.
If you're just interested in compiling (and not the entire build process), you may find one time saving benefit of MSBuild is the support for building with multiple processors.
The obvious answer from my team is that not everbody has visual studio installed, in particular we do not install Visual Studio onto our build/CI servers.
The prime reason for using an external build tool like NAnt or MsBuild is the ability to automate your build process and thus provide continous feedback on the status of your system. Also they can be used for loads of things besides a "pure" build and that's where you really start to get value from them, it's an extremly valuable thing to be able to build and test your application with a single command.
You can also start adding stuff like collection of metrics, packinging of release binaries and all sorts of nifty stuff like that.
As far as C# goes, devenv.exe 2005 runs the compiler in-proc, which may cause out of memory exceptions for sizable solutions. Msbuild resorts to launching csc.exe process for each project. Projects that don't compile with devenv /build work fine with msbuild. Hope you like this reason.
We are experimenting with switching from DevEnv to a tool (Visual Build Pro) that uses MsBuild under the hood and we got a "Reference required to assembly 'System.Drawing..." error for a project which doesn't need it and which builds fine in Visual Studio.
We have a large system consisting of C#, managed C++, and plain old unmanaged C++ assemblies/dlls. There is C++ code that depends on managed C++ code that depends of C# code that depends of managed C++ code that depends on plain old C++ code (whew!). When we were setting up our automated build environment a few years ago we discovered that MSBuild.exe didn't properly handle all of the dependencies that we have.
Working with Microsoft we were able to solve some of the issues but not all of them. If my memory serves me, we never could get the C# assemblies that depended on managed C++ dlls to build. So we ended up making a custom build script that called devenv.exe from the command line and it worked just fine.
Of course, that was with VS2005, it might be fixed now, but the script is still working so we haven't revisited the issue.